Discriminated Union Encoding
Void
An XDR void is a 0-byte quantity. Voids are useful for describing operations that take no data as input or no data as output. They are also useful in unions, in which some arms might contain data and others do not.
Declaration
The declaration is simply as follows.
void; |
Constant
const is used to define a symbolic name for a constant. It does not declare any data. The symbolic constant can be used anywhere a regular constant can be used.
The following example defines a symbolic constant DOZEN, equal to 12.
const DOZEN = 12; |
Declaration
The declaration of a constant follows this form.
const name-identifier = n; |
Typedef
Typedef does not declare any data either, but serves to define new identifiers for declaring data. The syntax is:
typedef declaration; |
The new type name is actually the variable name in the declaration part of the typedef. The following example defines a new type called eggbox using an existing type called egg and the symbolic constant DOZEN.
typedef egg eggbox[DOZEN]; |
Variables declared using the new type name have the same type as the new type name would have in the typedef, if it were considered a variable. For example, the following two declarations are equivalent in declaring the variable fresheggs:
eggbox fresheggs; egg fresheggs[DOZEN]; |
When a typedef involves a struct, enum, or union definition, you can use another (preferred) syntax to define the same type. In general, a typedef of the following form:
typedef <<struct, union, or enum definition>> identifier; |
can be converted to the alternative form by removing the typedef part and placing the identifier after the struct, enum, or union keyword instead of at the end. For example, here are the two ways to define the type bool.
typedef enum {/* using typedef */ FALSE = 0, TRUE = 1 } bool; enum bool {/* preferred alternative */ FALSE = 0, TRUE = 1 }; |
This syntax is preferred because you do not have to go to the end of a declaration to learn the name of the new type.
Optional-Data
The optional-data union occurs so frequently that it is given a special syntax of its own for declaring it. It is declared as follows.
type-name *identifier; |
This syntax is equivalent to the following union:
union switch (bool opted) { case TRUE: type-name element; case FALSE: void; } identifier; |
The optional-data syntax is also equivalent to the following variable-length array declaration, because the Boolean opted can be interpreted as the length of the array.
type-name identifier<1>; |
Optional data is useful for describing recursive data-structures, such as linked lists and trees.
XDR Language Specification
This section contains the XDR language specification.
Notational Conventions
This specification uses a modified Backus-Naur Form notation for describing the XDR language. Here is a brief description of the notation:
The characters |, (, ), [, ], and * are special.
Terminal symbols are strings of any characters embedded in quotes (").
Nonterminal symbols are strings of nonspecial italic characters.
Alternative items are separated by a vertical bar (|).
Optional items are enclosed in brackets.
Items are grouped by enclosing them in parentheses.
A * following an item means 0 or more occurrences of the item.
For example, consider the following pattern:
"a " "very" (", " " very")* [" cold " "and"] " rainy " ("day" | "night")
An infinite number of strings match this pattern. A few of them are:
a very rainy day a very, very rainy day a very cold and rainy day a very, very, very cold and rainy night
Lexical Notes
The following conventions are used in the specification.
White space serves to separate items and is otherwise ignored.
An identifier is a letter followed by an optional sequence of letters, digits, or underbars (_). The case of identifiers is not ignored.
A constant is a sequence of one or more decimal digits, optionally preceded by a minus sign (-), as seen in the following code example.
Example C-1 XDR Specification