この節では、XDR 言語を修正バッカス-ナウア記法で記述します。その表記規則を次に簡単に説明します。
特殊文字として、|、(、)、[、]、* を使用する
終端記号は、引用符 (") で囲んだ文字列または文字とする
非終端記号は、非特殊文字からなる文字列で、イタリックで表示する
代替項目は縦棒 (|) で区切って並べる
省略可能な項目は角括弧で囲む
項目をグループ化するときは、括弧で囲む
項目の後に * が付いている場合は、その項目の 0 回以上の繰り返しを表す
たとえば、次のパターンを考えてみます。
"a " "very" (", " " very")* [" cold " "and"] " rainy " ("day" | "night")
このパターンには、次の文字列を始めとして無数の文字列が一致します。
a very rainy day a very, very rainy day a very cold and rainy day a very, very, very cold and rainy night
空白は項目と項目の区切りに使用し、意味を持たない
任意の桁数の 10 進数を定数といい、始めに負符号 (-)を付けることができる
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 * |
次に示すものはキーワードとして予約されており、識別子として使用できない。
表 C-1 XDR キーワード
|
|
|
|
|
|
|
cas |
default |
|
|
|
|
|
|
|
|
|
switch |
|
|
配列のサイズ指定に使用できるのは、符号なし定数だけである。識別子で指定するときは、その識別子をそれまでに const
定義を使用して符号なし定数として宣言しておく必要がある
同様に、構造体と共用体の宣言の有効範囲内では、変数名は一意的にする。構造体と共用体の宣言がネストしている場合は、新たな有効範囲ができる
共用体の要素識別子は、整数を表す型でなければならない。すなわち、int
、unsigned int
、bool
、enum
、または、このどれかの型を typedef
で定義したものでなければならない。case で指定する値は、要素識別子の型に応じた値でなければならない。また、union
宣言の有効範囲内で case の値を 2 回以上指定してはならない
ファイルのデータ構造を XDR で記述した簡単な例を次に示します。このデータは、マシン間のファイル転送に使用することができます。
const MAXUSERNAME = 32;/* ユーザー名の最大長 */ const MAXFILELEN = 65535; /* ファイルの最大長 */ const MAXNAMELEN = 255; /* ファイル名の最大長 */ /* ファイルのタイプ */ enum filekind { TEXT = 0, /* ASCII データ */ DATA = 1, /* raw データ */ EXEC = 2 /* 実行可能形式 */ }; /* ファイルタイプごとのファイル情報 */ union filetype switch (filekind kind) { case TEXT: void; /* その他の情報なし */ case DATA: string creator<MAXNAMELEN>; /* データ作成者 */ case EXEC: string interpreter<MAXNAMELEN>; /*プログラムインタプリタ*/ }; /* ファイル全体 */ struct file { string filename<MAXNAMELEN>; /* ファイル名 */ filetype type; /* ファイル情報 */ string owner<MAXUSERNAME>; /* ファイルの所有者 */ opaque data<MAXFILELEN>; /* ファイルデータ*/ }; |
john というユーザーが、(quit) というデータだけが入った自分の LISP プログラム sillyprog を XDR 形式で保存するとします。このファイルは次のように符号化されます。
表 C-2 XDR データ記述の例
オフセット |
バイト (16 進) |
ASCII |
説明 |
---|---|---|---|
0 |
00 00 00 09 |
.... |
ファイル名の長さ = 9 |
4 |
73 69 6c 6c |
sill |
ファイル名の文字列 |
8 |
79 70 72 6f |
ypro |
ファイル名の文字列 (続き) |
12 |
67 00 00 00 |
g... |
ファイル名の文字列 (続き) と 3 バイトのヌルパディング |
16 |
00 00 00 02 |
.... |
ファイルタイプは EXEC = 2 |
20 |
00 00 00 04 |
.... |
インタプリタ名の長さ = 4 |
24 |
6c 69 73 70 |
lisp |
インタプリタの文字列 |
28 |
00 00 00 04 |
.... |
所有者名の長さ = 4 |
32 |
6a 6f 68 6e |
john |
所有者名 |
36 |
00 00 00 06 |
.... |
ファイルデータの長さ = 6 |
40 |
28 71 75 69 |
(qu |
ファイルデータ |
44 |
74 29 00 00 |
t).. |
ファイルデータ (続き) と 2 バイトのヌルパディング |