This section contains the XDR language specification.
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
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.
Syntax Information declaration: type-specifier identifier | type-specifier identifier "[" value "]" | type-specifier identifier "<" [ value ] ">" | "opaque" identifier "[" value "]" | "opaque" identifier "<" [ value ] ">" | "string" identifier "<" [ value ] ">" | type-specifier "*" identifier | "void" value: constant | identifier type-specifier: [ "unsigned" ] "int" | [ "unsigned" ] "hyper" | "float" | "double" | "quadruple" | "bool" | enum-type-spec | struct-type-spec | union-type-spec | identifier enum-type-spec: "enum" enum-body enum-body: "{" ( identifier "=" value ) ( "," identifier "=" value )* "}" struct-type-spec: "struct" struct-body struct-body: "{" ( declaration ";" ) ( declaration ";" )* "}" union-type-spec: "union" union-body union-body: "switch" "(" declaration ")" "{" ( "case" value ":" declaration ";" ) ( "case" value ":" declaration ";" )* [ "default" ":" declaration ";" ] "}" constant-def: "const" identifier "=" constant ";" type-def: "typedef" declaration ";" | "enum" identifier enum-body ";" | "struct" identifier struct-body ";" | "union" identifier union-body ";" definition: type-def | constant-def specification: definition *
The following are keywords and cannot be used as identifiers:
Only unsigned constants can be used
as size specifications for arrays. If an identifier is used, it must have
been declared previously as an unsigned constant in a const
definition.
Constant and type identifiers within the scope of a specification are in the same namespace and must be declared uniquely within this scope.
Similarly, variable names must be unique within the scope of struct
and union
declarations. Nested struct
and union
declarations create new scopes.
The discriminant of a union
must be of a type that evaluates
to an integer. That is, it must be an int
, an unsigned
int,
a bool
, an enum
type, or any typedef
that evaluates to one of these. Also, the case
values must be legal discriminant values. Finally, a case
value cannot be specified more than once within the scope of a union
declaration.
The following example is a short XDR data description of a file data structure that might be used to transfer files from one machine to another.
const MAXUSERNAME = 32;/* max length of a user name */ const MAXFILELEN = 65535; /* max length of a file */ const MAXNAMELEN = 255; /* max length of a file name */ /* Types of files: */ enum filekind { TEXT = 0, /* ascii data */ DATA = 1, /* raw data */ EXEC = 2 /* executable */ }; /* File information, per kind of file: */ union filetype switch (filekind kind) { case TEXT: void; /* no extra information */ case DATA: string creator<MAXNAMELEN>; /* data creator */ case EXEC: string interpreter<MAXNAMELEN>; /*proginterptr*/ }; /* A complete file: */ struct file { string filename<MAXNAMELEN>; /* name of file */ filetype type; /* info about file */ string owner<MAXUSERNAME>; /* owner of file */ opaque data<MAXFILELEN>; /* file data */ };
Suppose now that a user named linda wants to store her LISP program sillyprog that contains just the data "quit." Her file would be encoded as listed in the following table.
Table C–1 XDR Data Description Example
Offset |
Hex Bytes |
ASCII |
Description |
---|---|---|---|
0 |
00 00 00 09 |
– |
Length of file name = 9 |
4 |
73 69 6c 6c |
sill |
File name characters |
8 |
79 70 72 6f |
ypro |
More characters |
12 |
67 00 00 00 |
g |
3 zero-bytes of fill |
16 |
00 00 00 02 |
– |
Filekind is EXEC = 2 |
20 |
00 00 00 04 |
– |
Length of interpreter = 4 |
24 |
6c 69 73 70 |
lisp |
Interpreter characters |
28 |
00 00 00 04 |
– |
Length of owner = 4 |
32 |
6a 6f 68 6e |
linda |
Owner characters |
36 |
00 00 00 06 |
– |
Length of file data = 6 |
40 |
28 71 75 69 |
(qu |
File data bytes |
44 |
74 29 00 00 |
t) |
2 zero-bytes of fill |