RPC 言語は XDR 言語を拡張したものです。唯一の拡張は program 型と version 型の追加です。
XDR 言語への RPC 拡張の説明については、 付録 B 「RPC プロトコルおよび言語の仕様」 を参照してください。
RPC 言語は C 言語と同様です。この節では、実際の例を示しながら RPC 言語の構文について説明します。また、RPC 型と XDR 型の定義が、出力ッダーファイル内で、どのように C 型の定義にコンパイルされるかについても説明します。
RPC 言語ファイルは以下の定義から構成されています。
definition-list: definition; definition; definition-list
また、RPC 言語ファイルは 6 つの型の定義を認めています。
definition: enum-definition const-definition typedef-definition struct-definition union-definition program-definition
定義は宣言と同じではありません。1 つまたは一連のデータ要素の型定義以外の定義によっては領域を割り当てることはできません。これは、変数は定義するだけでは十分でなく、宣言もする必要があることを意味しています。
RPC/XDR 列挙型の構文は、C 列挙型と同様です。
enum-definition: "enum" enum-ident "{" enum-value-list "}" enum-value-list: enum-value enum-value "," enum-value-list enum-value: enum-value-ident enum-value-ident "=" value XDR enum のコードと、それを C にコンパイルした結果の例を以下に示します。 enum colortype { enum colortype { RED = 0, RED = 0, GREEN = 1, --> GREEN = 1, BLUE = 2 BLUE = 2, }; }; typedef enum colortype colortype;
XDR シンボル定数は、整数定数が使用される場合は常に使用できます。たとえば、配列サイズを以下のように指定します。
const-definition: const const-ident = integer
次の例では、定数 DOZEN が 12 になるように定義します。
const DOZEN = 12; --> #define DOZEN 12
XDR typedef
の構文は、C typedef
と同様です。
typedef-definition: typedef declaration
次の例では、最大の長さが 255 文字のファイル名文字列を宣言するために使用される fname_type
を定義しています。
typedef string fname_type<255>; --> typedef char *fname_type;
XDR には、4 種類の宣言があります。これらの宣言は、struct
または typedef
の一部でなければならず、単独では使用できません。
declaration: simple-declaration fixed-array-declaration variable-array-declaration pointer-declaration
単純な宣言は単純な C の宣言とほとんど同じです。
simple-declaration: type-ident variable-ident
例 :
colortype color; --> colortype color;
固定長配列宣言は C の配列宣言とほとんど同じです。
fixed-array-declaration: type-ident variable-ident [value]
例 :
colortype palette[8]; --> colortype palette[8];
多くのプログラマは、変数の宣言を型の宣言と混同します。rpcgen は変数の宣言をサポートしないことに注意することが重要です。以下に、コンパイルできないプログラムの例を示します。
int data[10]; program P { version V { int PROC(data) = 1; } = 1; } = 0x200000;
上記の例は、変数の宣言があるためにコンパイルできません。
int data[10]
int data[10] の代わりに、以下を使用してください。
typedef int data[10];
または
struct data {int dummy [10]};
C 言語には、可変長配列宣言の明示的な構文がありません。XDR 言語には、山括弧を使用する構文があります。
variable-array-declaration: type-ident variable-ident <value> type-ident variable-ident < >
最大のサイズは山括弧の間に指定されます。サイズを省略すると、配列が任意のサイズを持つということが示されます。
int heights<12>; /* 最大で 12 項目 */ int widths<>; /* 任意の数の項目 */
C では可変長配列の明示的な構文がないため、これらの宣言は struct
宣言にコンパイルされます。たとえば、heights 宣言は次の struct
宣言にコンパイルされます。
struct { u_int heights_len; /* 配列の項目の数 */ int *heights_val; /* 配列へのポインタ */ } heights;
配列の項目の数は _len 構成要素に格納され、配列へのポインタは _val 構成要素に格納されます。各構成要素名の最初の部分は、宣言された XDR 変数 (heights) の名称と同様です。
ポインタ宣言は、C で行われる場合とまったく同様に XDR でも行われます。アドレスポインタは、実際にはネットワーク上に送信されないのに対して、XDR ポインタは、リストおよびツリーなどの再帰的なデータ型を送信するのに有効です。XDR 言語では、型は「ポインタ」ではなく、「オプショナルデータ」と呼ばれます。
pointer-declaration: type-ident *variable-ident
例 :
listitem *next; --> listitem *next;
RPC/XDR struct
はその C の構造体とほとんど同じように宣言されます。宣言は以下のように行われます。
struct-definition: struct struct-ident "{" declaration-list "}" declaration-list: declaration ";" declaration ";" declaration-list
次に、二次元の座標である XDR 構造体と、その構造体がコンパイルされて生成される C 構造体の例を示します。
struct coord { struct coord { int x; --> int x; int y; int y; }; }; typedef struct coord coord;
出力は、最後に追加された typedef
を除いて入力と同一です。これによって、項目を宣言する際に、struct
coord の代わりに coord を使用することができます。
XDR 共用体は識別された共用体であり、C 共用体には似ていません。XDR 共用体は Pascal 変形レコードに、より似ています。
union-definition: "union" union-ident "switch" "("simple declaration")" "{" case-list "}" case-list: "case" value ":" declaration ";" "case" value ":" declaration ";" case-list "default" ":" declaration ";"
次に、「データの読み取り」操作の結果として返される型の例を示します。エラーがない場合はデータのブロックを返し、エラーが発生した場合は何も返しません。
union read_result switch (int errno) { case 0: opaque data[1024]; default: void; };
上記のコードは以下のようにコンパイルされます。
struct read_result { int errno; union { char data[1024]; } read_result_u; }; typedef struct read_result read_result;
出力 struct の共用体構成要素が、後に付いている _u を除いて型の名称と同じ名称であることに注意してください。
RPC プログラムは、次の構文を使用して宣言します。
program-definition: "program" program-ident "{" version-list "}" "=" value; version-list: version ";" version ";" version-list version: "version" version-ident "{" procedure-list "}" "=" value; procedure-list: procedure ";" procedure ";" procedure-list procedure: type-ident procedure-ident "(" type-ident ")" "=" value;
-N オプションを指定すると、rpcgen は次の構文も認識します。
procedure: type-ident procedure-ident "(" type-ident-list ")" "=" value; type-ident-list: type-ident type-ident "," type-ident-list
たとえば以下のようになります。
/* * time.x: 時間を取得するか、または設定してください。 * 時間は、1970 年 1 月 1 日 0:00 から経過した秒数で表されます。 */ program TIMEPROG { version TIMEVERS { unsigned int TIMEGET(void) = 1; void TIMESET(unsigned) = 2; } = 1; } = 0x20000044;
void
引き数型は、引数が渡されないことを意味していることに注意してください。
このファイルは、出力ヘッダーファイルの、以下の #define 文にコンパイルされます。
#define TIMEPROG 0x20000044 #define TIMEVERS 1 #define TIMEGET 1 #define TIMESET 2
RPC 言語規則には、いくつかの例外があります。
新しい機能の節で、rpcgen の C 形式モードの機能について説明しました。これらの機能は、void
引数に関連しています。引数の値が void
である場合は、引数は渡される必要はありません。
C には組み込みのブール型はありません。しかし、RPC ライブラリは、TRUE または FALSE の、bool_t
と呼ばれるブール型を使用します。XDR 言語でブール型として宣言されたパラメータは、出力ヘッダーファイルの bool_t
にコンパイルされます。
例 :
bool married; --> bool_t married;
C 言語には組み込みの文字列型がありませんが、その代わりに、NULL で終了する char *
規則を使用します。C では、文字列は通常 NULL で終了する一次元の配列とみなされます。
XDR 語では、文字列は string
キーワードを使用して宣言され、出力ッダーファイルの char *
型にコンパイルされます。山括弧の間で指定される最大サイズによって、文字列内で使用できる文字の最大数が指定されます (NULL 文字はカウントされない)。最大サイズを省略すると、任意の長さの文字列を指定できます。
例 :
string name<32>; --> char *name; string longname<>; --> char *longname;
NULL 文字列を渡すことはできません。ただし、長さが 0 の文字列 (すなわち、ターミネータまたは NULL バイト) を渡すことはできます。
XDR では、隠されたデータは、任意のバイトのシーケンスなどの、型のないデータを記述するために使用されます。隠されたデータは、固定長または可変長の配列として宣言することもできます。たとえば、以下のようになります。
opaque diskblock[512]; --> char diskblock[512]; opaque filedata<1024>; --> struct { u_int filedata_len; char *filedata_val; } filedata;
void
宣言では、変数は指定されません。void
宣言には、void
以外何も記述しません。void
宣言は、共用体定義とプログラム定義の 2 つの部分で行うことができます (たとえば、引数を渡さない遠隔手続きの引き数または結果として)。