英語フランス語スペイン語

OnWorksファビコン

rxgen - クラウドでオンライン

Ubuntu Online、Fedora Online、Windows オンライン エミュレーター、または MAC OS オンライン エミュレーター上の OnWorks 無料ホスティング プロバイダーで rxgen を実行します。

これは、Ubuntu Online、Fedora Online、Windows オンライン エミュレーター、または MAC OS オンライン エミュレーターなどの複数の無料オンライン ワークステーションの XNUMX つを使用して、OnWorks 無料ホスティング プロバイダーで実行できるコマンド rxgen です。

プログラム:

NAME


rxgen - Rx リモート プロシージャ コール パッケージ用のスタブ ジェネレーター

SYNOPSIS


rxgen [-h | -c | -C | -S | -r] [-dkpR]
[-I DIR] [-P 接頭辞] [-o アウトファイル] [ファイル内]

rxgen -s 輸送 [-o アウトファイル] [ファイル内]

rxgen -l [-o アウトファイル] [ファイル内]

rxgen -m [-o アウトファイル] [ファイル内]

DESCRIPTION


rxgen Rx RPC プロトコルを実装するための C コードを生成するツールです。 入力として受け取ります
C に似たアプリケーション インターフェイスの記述であり、多数のサーバーを生成します。
および/または RPC ベースのプログラムにリンクされるクライアント スタブ ルーチン。 これらのスタブにより、
ローカル プロシージャ コールを介してリモート プロシージャを呼び出すプログラム。 rxgen 拡張子です
サンの rpcgen (バージョン 3.9) を完全に保持します rpcgen 機能(少なくともその時点では)
バージョン)。 を参照してください。 rpcgen(1) Sun の RPC 固有のフラグの詳細については、
RPC 言語に関する RPC プログラミング ガイドと役立つ例を参照してください。

OPTIONS


rxgen いくつかの異なるモードで動作します。 生成された出力ファイルを生成できます。
個別に(次のいずれかを使用して) -h, -c, -Cまたは -S)またはまとめて。 すべての出力ファイルは、
デフォルトが使用される (つまり、オプションなし) 場合、または出力が制限されている場合に作成されます。
サーバースタブ(-C-S-r フラグが使用されます。 以下にその種類について説明します。
生成された出力ファイル (簡単にするために、 ファイル名 メインの出力ファイル名を指します):

-h 標準の RPCL 定義 (デフォルト) から C データ定義 (ヘッダー ファイル) を生成します。
拡張: ファイル名.h)。

-c RPCL で記述されたプロトコルをシリアル化するために必要な XDR ルーチンをコンパイルします。
すべての宣言に対して XDR ルーチンを生成します (デフォルトの拡張子: ファイル名.xdr.c)。

-C すべてのクライアント側スタブ ルーチンを生成します (デフォルトの拡張子: ファイル名.cs.c)。
このファイル内のルーチンを呼び出すと、引数がパックされて送信されます。
Rx (または R)。

-S すべてのサーバー側スタブ ルーチンを生成します (デフォルトの拡張子: ファイル名.ss.c)。
引数が展開され、対応するサーバー ルーチンが呼び出されます。

-r によって生成される XNUMX つのデフォルト拡張ファイルを生成します。 -C-S オプション。

次のオプションは、以下の任意の組み合わせで使用できます。 rxgen 呼び出し:

-R デフォルトの Rx ではなく、古い \R プロトコルのコードを生成します。

-k 生成されたコードがカーネルで使用されることを意図している場合は、指定する必要があります。
特別な「インクルード」およびその他の詳細は、ターゲット出力が
カーネル。

-p パッケージ組み合わせフラグ: XNUMX つのパッケージ内に複数のパッケージが含まれる場合
仕様ファイルでは、単一のリクエスト実行ルーチンがすべてのリクエストに対して
このフラグの結果。 デフォルトでは、個別の実行要求スタブが生成されます。
各パッケージ。

-I DIR
に似て -I C コンパイラのフラグ (cc)。 このフラグは事前に渡されます。
プロセッサー (cpp)そのディレクトリ DIR の標準ルックアップ リストの前に検索されます。
#include ファイル。 予想通り、複数の -I フラグは同時に使用できます。

-P 接頭辞
この 接頭辞 このスイッチに続く文字列は、生成されたすべての出力ファイルの先頭に追加されます。
複数の実行で同じインターフェースの異なるバージョンを生成する場合に便利です
(カーネルと非カーネルのバージョンなど)。

-d デバッグモード; 必要なときだけ rxgen デバッグする必要があります(たとえば、 dbxの).

-o アウトファイル
出力ファイルの名前を指定します。 何も指定されていない場合、標準出力は次のようになります。
使用済み (-c, -h, -C, -S モードのみ)。 出力ファイルが指定されている場合は、
マルチ出力ファイル オプション (デフォルト、またはオプション付きなど) -r)、 そうして アウトファイル
デフォルトで生成される名前 (構成のメインに基づく名前) を置き換えます。
ファイル名)。

この -s, -l, -m オプションは次の場合にのみ存在します rpcgen サポート。 見る rpcgen(1)
それらの使用に関する情報。

rxgen 構文 概要


仕様ファイル:

|
|
|
|
|


:

"パッケージ"

:

「接頭語」

:

「開始オペコード」

:

「分割プレフィックス」 ";"

:

「いん=」 "|"
「アウト=」 "|"


:

["プロシージャ"] [ ][ 】
[「分割」 | 「マルチ」】
["= ]「;」

:

"(" ")"

:


[「<」 ">" | 「[」 "]"] | ヌル

:

「、」 | ヌル

:

"IN" | 「アウト」 | "INOUT" | ヌル

:

| ヌル

:
:
:
:
:
:
:
:
:



:
:

Sun の RPCL 言語構文 ( rpcgen(1))

rxgen コマンド


コメント 前処理
入力インターフェイスには、C インターフェイスを介して渡されるプリプロセッサ ディレクティブが含まれる場合があります。
プリプロセッサ (つまり「cpp」)。 プリプロセッサはすべての入力ファイルに対して実行される前に実行されるため、
実際に解釈したのは rxgen、すべての cpp ディレクティブ (#include、#ifdefs、#defines など)
合法であり、社会的に歓迎されています rxgen 入力ファイル。 もちろん、これらのプリプロセッサはどれも
ディレクティブは、生成されたファイルのいずれかに含まれます。 区別しやすくするために
異なる種類の出力ファイルの間で、 rxgen 特定の特別なものを定義する cpp の記号
による使用 rxgen プログラマー。 これらは RPC_HDR (ヘッダーにコンパイルするときに定義され、
ファイル名.h、ファイル)、RPC_XDR (xdr にコンパイルするときに定義され、 ファイル名.xdr.c、ファイル)、
RPC_CLIENT (クライアント スタブにコンパイルするときに定義されます。 ファイル名.cs.c、ファイル)、および
RPC_SERVER (サーバー スタブにコンパイルするときに定義され、 ファイル名.ss.c、ファイル)。

加えて、 rxgen 独自の前処理を少し行います。 「%」で始まる行は、
解釈されずに出力ファイルに直接渡されます。 rxgen。 より重いものをまとめて
解釈されないコードをダンプする場合は、そのようなコードをすべて
「#include」ファイルを作成し、「%」を先頭に付けて渡します。 入力インターフェイスには、次のものを含めることもできます。
C スタイルのコメントはもちろん無視されます。 解釈はトークンベースであるため、
個別のステートメントの特別な行方向は必要ありません。 rxgen また、提供しています
非常に豊富で役立つエラー レポートのセット。正確な行の位置と
エラータイプ。 また、 rxgen 標準インクルードの #include 行を自動的に生成します
などのファイル rx/xdr.hrx/rx.h、ここから生成されたヘッダー ファイルとともに
インタフェース。

接頭辞 スタブ 手続き
この パッケージ 声明は伝えます rxgen インターフェースパッケージの名前。 のために使用されます
生成されたすべてのスタブ ルーチンと実行要求プロシージャの名前に接頭辞を付けます。
例:

パッケージ AFS_

これにより、リクエスト実行プロシージャの名前が AFS_ExecuteRequest になります (警告: 古いバージョンでは
バージョン ExecuteRequest 名のパッケージ名の後に「_」が追加されました。
したがって、ExecuteRequest インターフェイス ルーチン)と特定のスタブがないことを確認してください。
ルーチン、たとえば Fetch は、実際には AFS_Fetch という名前になります。 複数のパッケージ ステートメント (現在の
最大サイズは 10) 構成ごとに許可されており、複数のセットの場合に便利です。
インターフェイスが実装されています (最後の例を参照)。 このような場合には、
  -p フラグを指定すると、ExecuteRequest プロシージャが XNUMX つだけ生成されます。
複数のインターフェイスを認識し、その名前の先頭に最初のパッケージが付けられます
声明。 デフォルトの場合、独立した ExecuteRequest プロシージャが作成されます。
リモート プロシージャ コールのパッケージ化された各グループ。

この 接頭辞 ステートメントは、リモート プロシージャ名へのすべての呼び出しの先頭に追加する名前を指定します。
ExecuteRequest スタブ ルーチン。 サーバーが他のサーバーに対して RPC 呼び出しを行う場合に便利です。
サーバー (デバッグ目的など)。 例えば:

接頭辞 S

サーバーから呼び出されるすべてのルーチンの名前の前に名前「S」が追加されます。
半券。 その後、サーバーは元の名前を呼び出してクライアント スタブを取得できます。

rxgen 手続き 宣言
この PROC このステートメントは、この中で最も一般的 (そして意味のある) です。 rxgen インターフェース。 その構文
説明は次のとおりです:

[手続き] [ ][ ] ( 、...、 )
[分割 | マルチ] [= ] ;

ここで、

· "proc" は、手続きステートメントのオプションの接頭辞です。 これは単なるスタイルアイテムです
必須のプロシージャ区切り文字ではありません。

· プロシージャの名前です。 プロシージャの名前も
オプション。 これは、指定されたプロシージャの名前が同じである場合にのみ意味を持ちます。
最後の名前 パッケージ ステートメント (つまり、「パッケージ RCallBack」と次の宣言)
「RCallBack」プロシージャ)。

· が存在する場合、ExecuteRequest プロシージャは代わりにそのスタブを呼び出します。
そのオペコードを使用した呼び出しがデコードされるときに、自動的に生成されたスタブの。

· は、そのプロシージャのオペコードである定数またはシンボルです。 使うかもしれない
プリプロセッサ機能 (#define)、 定数 RPC 言語機能、または古い
オペコードとして適切な定数。 オペコードのさらなる評価/処理が行われます。
特に、重複したオペコードや存在しないオペコードのチェックが実行されます。
オペコード シーケンス内の「ホール」(つまり、連続したオペコードのギャップ) をチェックします。 ために
たとえば、オペコードに「ホール」が存在する場合、ExecuteRequest が実行されるという事実を利用します。
手順は 場合 より高速な(そしてより小さく、コードごとに)インデックス付けされたステートメントではなく
配列メソッド。

だから、 rxgen それぞれに XNUMX つの価値のあるマクロを定義します (つまり、ヘッダー ファイルに追加します)。
パッケージグループ: LOWEST_OPCODE、 HIGHEST_OPCODE、および
NUMBER_OPCODES。 これらは次のような場合に役立つ可能性があります。 rxgen プログラマー。 また、
に注目してください オペコード ステートメントはオプション機能であり、省略できます。 そのような中で
場合によっては、自動オペコード番号が 0 から順に生成されます。

を使用して、初期オペコード番号を変更できます。 開始オペコード (欠如のため
より良い名前) rxgen 指図。 その構文は次のとおりです。

開始オペコード

どこそれは合理的でなければなりません! プロシージャを混合することはできないことに注意してください。
オペコードを含むものと含まないもの、または指定後のオペコードを許可しないもの
開始オペコード 声明。 rxgen そのようなすべての場合に文句を言います。

引数 エントリはプロシージャの指定されたパラメータを表します。 その構文は次のとおりです。

[IN | 入出力 | アウト | 】
[ |<>|[最大]|[]]

型が間接型 (つまり、* が続く) の場合、ポインタは
XNUMX つのレベルをたどって、指定されたデータが送信される必要があります。 これは、
通常、すべての構造体/配列および出力パラメータに使用されます。 顕著な例外
配列/構造体の最大サイズが明示的に指定されている場合です。 ポインタの配列がないので
宣言は許可されており、同様の効果を達成するには typedef を使用する必要があります。 の
パラメータは、入力パラメータ (先頭に IN)、出力パラメータ (先頭に
OUT)、または入出力パラメータ (前に INOUT)。 指定しない場合、
プロシージャの前のパラメータの方向が使用されます。 (注:最初の
パラメータの前に方向プリミティブを置く必要があります!)

· 「分割」は、ファイル転送などの処理を行うスタブ ルーチンを処理するためのハックです。
実行前に情報 (ファイルの長さなど) を交換する必要があるその他の操作
call は出力パラメータを返します。 特別な握手のため、
リモート ファイル転送を実行するときに関係するため、現在、そのような呼び出しはすべて XNUMX つに分割されています。
クライアント側のスタブ ルーチン。 最初の (デフォルトの接頭辞 "Begin" を持つ) は、
すべての IN パラメータと INOUT パラメータをサーバー側に渡します。 XNUMX 番目 (デフォルトでは
プレフィックス「End」) は、サーバーから INOUT パラメータと OUT パラメータを取得するために使用されます。
XNUMX つの呼び出しの間に、ユーザーはファイルに対して適切な呼び出しを行う必要があります。
移行。 たとえば、パッケージ AFS_ の次のプロシージャー宣言

フェッチ (IN a、b、INOUT c、OUT d) 分割 = FETCHOPCODE;

これにより、大まかに XNUMX つの独立したクライアント スタブ ルーチンが生成されます。

BeginAFS_Fetch (IN a、b、c)



EndAFS_Fetch(OUT c, d)

この スプリットプレフィックス ステートメントを使用して、XNUMX つで使用されるデフォルトのプレフィックス名を変更します。
ファイル転送関連のプロシージャを処理するときにクライアント側で生成されるスタブルーチン
呼び出します。 例えば:

スプリットプレフィックス IN=前_ OUT=後_

これにより、ファイル転送関連のルーチンの XNUMX つのクライアント スタブに名前が付けられます。
フェッチ()、 することが Before_AFS_Fetch()After_AFS_Fetch()それぞれ。

· 「マルチ」オプションは、上記の「分割」機能とほぼ同じです。 唯一の
目に見える大きな違いは、XNUMX つのクライアント スタブに加えて、標準の
クライアントスタブも生成されます。 目的はマルチ Rx コールを処理することなので、
マルチ Rx 呼び出しがない場合は、標準プロシージャ スタブ全体が必要です。
という手続きが行われます。 「multi」オプションの副作用として、
特別なマクロ (つまり、「multi_ " これは引数として "Begin" を返します。
ヘッダー出力ファイル内の「End」スタブ。 このマクロは Rx コードによって直接使用されます
このプロシージャのマルチ Rx コールが実行されたとき。

廃止 rxgen 商品特徴
次の rxgen コマンドはまだ有効ですが、間もなく削除される予定です。
もっと良い代替手段があります。 使用しないでください。

この 特別 ステートメントは、特定の非効率性を処理するために使用される一時的なハックです。
標準の xdr ルーチンは、ユーザーがカスタマイズした宣言を処理します。 特にこれは、
宣言の一部として指定された文字列ポインターに適用されます。 例えば、

特別な構造体 BBS SeqBody;

伝える rxgen ユーザー定義の BBS xdr ルーチンのエントリ「SeqBody」が文字列であること (注)
構造ごとに複数の文字列を「特別」にすることができます。複数の文字列は次のように区切られます。
カンマ); したがって、サーバーが生成したスペースの割り当てと割り当て解除が適切に行われます。
この構造体を IN または INOUT パラメータとして含むスタブ。

より良い代替品 特別カスタマイズ ステートメント、これは単に
「カスタマイズされた」トークンの後に、RPCL に基づいた構造体の通常の宣言が続きます。
ルール。 この場合、宣言は生成されたヘッダー ファイルに含まれます (-h
オプション) ただし、この構造に対して xdr ルーチンは生成されません -- ユーザーが指定します
これ。 この構造体のすべてのポインタ エントリは記憶されるため、構造体が
サーバー スタブの IN または INOUT として使用される場合、コア リークは発生しません。 例えば、
検討する

カスタマイズされた構造体 CBS {
長いシーケンス。
char *SeqBody;
}

「xdr_CBS」ルーチンはユーザーによって提供され、DECODE xdr オペコード中に、
「SeqBody」文字列に適切なスペースが割り当てられます。 同様に、そのスペースが解放されます
無料の xdr オペコード中に。

注: 古いスタイルの「配列パラメータ仕様」はサポートされなくなりました。


現在の RPC 言語では利用できない要件がある場合、次のことが可能です。
一部の XDR ルーチンは、これらのデータ型を未定義のままにしてカスタマイズします。 あらゆるデータ型に対して
これは未定義の場合、名前「xdr_」が先頭に付加されたルーチンが存在すると想定されます。
それに。 選択されたセット rxgen 機能を以下に示しますが、より包括的なものとしては、
XNUMX つ (共用体、複雑な例など) を参照してください。 rpcgen プログラミング ガイド
外部の Rescale データ 表現: 技術的 Notes.

Typedef
RPC の typedef ステートメントは、C の typedef と同じです (つまり、「typedef」 ")。
デフォルトでは、ほとんどのユーザー宣言 (つまり、構造体、共用体など) は自動的に
typedef されたもの rxgen。 解析が簡単になるため、その使用が推奨されています。 rxgen
スクリプト。


C の "char *" 文字列規則は、通常は次のことを目的としているため、ある意味あいまいです。
NULL で終わる文字列を意味しますが、ファイルへのポインタを表すこともあります。
単一の文字、文字の配列へのポインタなど。RPC 言語では、null-
終了した文字列は明確に「文字列」と呼ばれます。 例、

文字列 bigname<>;
文字列名;
typedef 文字列ボリューム名;

文字列の最大サイズは任意(上記の「bigname」など)にすることができることに注意してください。
できれば、山括弧で指定するか (つまり、上記の「name」と「volname」) で指定します。 の
実際には、インターフェイスでは常に境界のある文字列のみを使用する必要があります。 プロシージャ呼び出しのサンプル
上記の宣言を使用すると、次のようになります。

GetEntryByName (IN ボリューム名、
OUT struct vldbentry *entry) = VL_GETENTRYBYNAME;

またはもちろん、

GetEntryByName (IN 文字列ボリューム名、
OUT struct vldbentry *entry) = VL_GETENTRYBYNAME;

ユーザーにとって、文字列パラメーターをいつ使用する必要があるかを理解することは非常に重要です。
クライアントおよび/またはサーバー プログラムによって割り当ておよび/または解放されます。 についての短い分析
文字列パラメータの処理は次のとおりです (同様のメソッドが文字列パラメータの処理にも使用されることに注意してください)
可変長配列については後で説明します):

· クライアント側: IN および INOUT 文字列パラメータはプログラマの責任です
そして、rpc を呼び出して解放する前に (静的または malloc 経由で) 割り当てられ、(場合によっては) 解放される必要があります。
malloc が使用されました) ユーザーのクライアント プログラムで rpc が返された後。 もちろん、のために
INOUT パラメータを使用する場合、返される文字列は、割り当てられた入力文字列よりも大きくすることはできません。

OUT 文字列パラメータは (返された文字列の長さに基づいて) 自動的に割り当てられます。
最大サイズではなく文字列) rxgen クライアント スタブ ( ファイル名.cs.c) である必要があります。
クライアントプログラムによって解放されます。 確かに、これはユーザーが
自分が割り当てていないものを解放する必要があります。}

· サーバー側: IN および INOUT 文字列パラメーターは (に基づいて) 自動的に再配置されます。
rxgen サーバー スタブによる受信文字列のサイズ (in ファイル名.ss.c) の前に
ユーザーのサーバー プロシージャに渡されます。 そのスペースは直前に自動的に解放されます
rxgen サーバー スタブが返されます。 したがって、ユーザーは IN に対して特別なことをする必要はありません。
および INOUT 文字列パラメーター。

OUT 文字列パラメータは、ユーザーのサーバー プロシージャ (つまり、null ポインタ) によって割り当てられる必要があります。
rxgen サーバー スタブによって渡されます) が終了すると自動的に解放されます。
  rxgen サーバーのスタブ。 クライアント側と同様に、OUT パラメータは次のようになります。
非正統的 (つまり、サーバー ルーチンは文字列自体を解放せずに文字列を malloc する必要があります。
これはによって行われます rxgen サーバー スタブ)。

INOUT および OUT 文字列パラメーターの場合、クライアント側とサーバー側の両方で、
引数はポインタの char (つまり char **) でなければなりません。

ポインタ
RPC でのポインタ宣言も、C でのポインタ宣言とまったく同じです (つまり、「struct
single_vldbentry *vldblist;")。 もちろん、ネットワーク経由でポインタを送信することはできませんが、
XDR ポインタを使用して、リストやツリーなどの再帰的なデータ型を送信できます (
リンクされたリストの例はすぐに説明します)。

配列
固定配列は、標準の C 配列宣言とまったく同じです (つまり、「struct UpdateEntry」
エントリ[20]") での副作用の問題はありません。 rxgen. 可変長配列には
C には明示的な構文はなく、山かっこが使用され、配列宣言は次のようになります。
実際には「構造体」にコンパイルされます。 たとえば、次のような宣言です。

const MAXBULKSIZE = 10000;
const MAXENTRIES = 100;
不透明なバルク; /* 最大 10000 アイテム */
int ホスト<>; /* 任意の数のアイテム */
typedef vldbentry blkentries<100>; /* 望ましい配列 decl */

は次の構造体にコンパイルされます。

構造体 {
u_int バルク_len; /* 項目数 */
char *bulk_val; /* 配列へのポインタ */
バルク;

「bulk」配列の場合、および同様に「blkentries<100>」配列の場合、

構造体 {
u_int blkentries_len; /* 配列内の項目数 */
vldbentry *blkentries_val; /* 配列へのポインタ */
ブランケントリー;

したがって、ユーザーは、次のような「魔法のように」生成された構造エントリに注意する必要があります。
配列内の項目の数 ( _len) と配列へのポインタ
( _val) エントリの一部は、
クライアント/サーバー プログラム。 サンプル proc は次のようになります。

typedef vldbentry blkentries ;
proc GetBlk (OUT blkentries *vlentries) = VL_GETBLK;

または、より直接的に、

GetBlk(OUT vldbentry vlentries ) = VL_GETBLK;

最初に使用する必要がないため、最新の方法が望ましいことに注意してください
typedef ステートメント (そして確かに、プログラマは typedef を避けることを好みます) を使用する必要があります。
だと、わかる rxgen 構造展開と xdr 作成を暗黙的に行います。 したがって
ユーザーは、以前と同様に「vldbentries_val」および「vldbentries_len」フィールドに注意する必要があります。
(次の例を参照してください)。

配列 I (少しでも 望ましい)

インターフェイス設定内のプロシージャ宣言:

proc ListAttributes (IN vldblistbyattributes *attributes,
INOUT blkentries *vldbentries) = VL_LISTATTRIBUTES;

サンプルクライアントコード:

blkentries エントリ、*pnt;
エントリ.blkentries_len = 10; /* 返されるエントリの最大数 */
エントリ.blkentries_val = (vldbentry *)malloc(LEN);
/* 設定する必要があります */

コード = VL_ListAttributes(&attributes, &entries);
if (!code) {
pnt = エントリ.blkentries_val;
for (i=0; i < エントリ.blkentries_len; i++, pnt++)
ディスプレイ_vldbentry(pnt);
/* 割り当てられたスペースを必ず解放してください */
free((char *)entries.blkentries_val);
}

サンプルサーバーコード:

VL_ListAttributes(属性、エントリ)
{
vldbentry *singleentry = エントリ->blkentries_val;
エントリ->blkentries_len = 0;

while (copy_to_vldbentry(&vlentry, singleentry))
singleentry++、vldbentries->entries_len++;
}

可変サイズの配列に対するこの方法はうまく機能しますが、いくつかの大きな欠点があります。
配列パラメータ (つまり、上記の vldbentries) は、次のようにする必要があるため、INOUT として宣言する必要があります。
返されると予想される配列の最大長を渡します。 さらに重要なのは、大きな(状況に応じて)
"_len" の値) 結果としてジャンク コードのチャンクがサーバーに転送されます
配列の IN(out) の副作用。 場合には簡単で便利な方法です。
返される配列のサイズは、最初から、またサイズが非常に大きい場合でも予測できます。 これ
メソッドは、の誤った使用 (および乱用) の例として含まれています。 rxgen すべきではありません
中古。

配列 II (望ましい 方法)

インターフェイス設定でのプロシージャ宣言 (上記の例 I を使用):

proc ListAttributes (IN vldblistbyattributes *attributes,
OUT blkentries *vldbentries) = VL_LISTATTRIBUTES;

サンプルクライアントコード:

blkentries エントリ、*pnt;

コード = VL_ListAttributes(&attributes, &entries);
if (!code) {
pnt = エントリ.blkentries_val;
for (i=0; i < エントリ.blkentries_len; i++, pnt++)
ディスプレイ_vldbentry(pnt);
/* (rxgen によって) 割り当てられたスペースを必ず解放してください */
free((char *)entries.blkentries_val);
}

サンプルサーバーコード:

VL_ListAttributes(属性、エントリ)
{
vldbentry *単一エントリ;
エントリ->blkentries_len = 0;
singleentry = エントリ->blkentries_val
= (vldbentry *)malloc(MAXENTRIES * sizeof(vldbentry));

while (copy_to_vldbentry(&vlentry, singleentry))
singleentry++、vldbentries->entries_len++;
}

これは、可変サイズの配列を出力パラメーターとして使用する最良の (そして最も簡単な) 方法です。
サーバー側のスタブの責任は次のとおりです。 malloc() 適切なスペース
によって自動的に解放されます rxgen スタブ; クライアント側は、によって割り当てられたスペースを解放する必要があります。
  rxgen-呼び出しスタブ。

配列 3 (リンク済み リスト)

次の 3 つの宣言を考慮します (いくつかの最適化が適用された可能性があります)。
設定ファイル:

typedef struct single_vldbentry *vldblist;
構造体 single_vldbentry {
vldbentry vlentry;
vldblist next_vldb;
};

構造体 vldb_list {
vldblist ノード。
};

そして rxgen プロシージャ宣言:

LinkedList (IN vldblistbyattributes *属性、
OUT vldb_list *linkedentries) = VL_LINKEDLIST;

サンプルクライアントコード:

vldb_list リンクされたvldbs;
vldblist vllist、vllist1;

bzero(&linkedvldbs, sizeof(vldb_list));
コード = VL_LinkedList(&attributes, &nentries, &linkedvldbs);
if (!code) {
printf("%d vldb エントリを取得しました\n", nentries);
for (vllist = linkedvldbs.node; vllist; vllist = vllist1) {
vllist1 = vllist->next_vldb;
display_entry(&vllist->vlentry);
free((char *)vllist);
}
}

サンプルサーバーコード:

VL_LinkedList(rxcall、属性、nentries、linkedvldbs);
{
vldblist vllist、*vllistptr = &linkedvldbs->node;
その間 (...) {
vllist = *vllistptr
= (single_vldbentry *)malloc (sizeof (single_vldbentry));
copy_to_vldbentry(&tentry, &vllist->vlentry);
ネントリー++;
vllistptr = &vllist->next_vldb;
};
*vllistptr = NULL;
}

リンク リストの使用には多くの利点があります。サーバーには何も渡されません (パラメーター
は OUT)、追加のオーバーヘッドは関係せず、呼び出し側は明示的に
任意の戻りサイズを用意します。 欠点は、呼び出し側が
の責任 malloc() 各エントリを(サーバー上で)解放し、(クライアント上で)解放します。
不要なコアの漏れを避けます)。 もう XNUMX つの欠点は、これは再帰呼び出しであるため、C
スタックはリスト内のノードの数に応じて直線的に増加します (したがって、
大量のデータが返されることが予想される場合は、Rx LWP スタックを増やします -- デフォルトのスタック サイズ
4Kです)。 ここでは利点が欠点を上回るはずです。

上記の XNUMX つの配列の例のコメントに注意を払うことが重要です。
特に、ユーザーがいつスペースを割り当てたり解放したりするかを参照する場合は、
可変長配列。 このメカニズムは文字列の処理と非常によく似ているため、
上記の文字列セクションを確認する必要がある場合があります。 リンクされたリストが処理されることに注意してください
多少違う...

その他
以下は、一般的なものの一部を示すランダム インターフェイス ファイルの短縮版です。
ケース。

/* R.xg スクリプト インターフェイスで使用されるすべての構造体の宣言 */

構造体 AFSFid {
署名なしの長いボリューム。
符号なしの長い Vnode。
unsigned long ユニーク。
};

typedef 長い ViceDataType;

/* TEST は、実行中のみ「HEADER」と同等になることに注意してください。
ヘッダー、*.h、ファイル */ の処理

#ifdef RPC_HDR
#define テスト「ヘッダー」
#その他
#define テスト "REST"
#endif

/* これは標準の *.xg 仕様ファイルです */

パッケージ AFS_
スプリットプレフィックス IN=BEFORE_ OUT=AFTER_;
プレフィックステスト

proc Remove(IN struct AFSFid *Did, IN string volname<64>,
OUT struct AFSStatus *ステータス) = AFS_REMOVE;

DisconnectFS AUX_disconnectFS() = AFS_DISCONNECTFS;

proc GetVolumeInfo(IN 文字列 Vid,
OUT struct VolumeInfo *情報) = AFS_GETVOLUMEINFO;

/* 構成ごとに複数のインターフェースを持つことができます */

パッケージVOTE_

/* 「マルチ」機能を使用します。 したがって、VOTE_Beacon は
マルチ Rx コールまたは通常のコールとして */

ビーコン(INロングステート、ロング投票開始、
net_version *バージョン、net_tid *tid)
マルチ = VOTE_BEACON;

パッケージ DISK_

/* 「分割」機能の使用 */

SendFile (IN ロング ファイル、ロング オフセット、
長い長さ、net_version *version)
分割 = DISK_SENDFILE;

出力 of an 実際の インタフェース の監視
によって生成された実際の出力の一部を示します。 rxgen 省略形に従って
実際のインターフェース構成。

  file

インターフェース構成ファイルの内容 (vldbint.xg):

パッケージ VL_
#include "vl_opcodes.h" /* オペコードはここに含まれます */
%#include "vl_opcodes.h" /* 他の場所に直接 */

/* 他のパッケージに影響を与えるパラメータの現在の制限
(つまり、ボリューム) */

const MAXNAMELEN = 65;
const MAXNSEVERS = 8;
const MAXTYPES = 3;

/* 個々の vldb エントリの外部 (可視) 表現 */

構造体 vldbentry {
文字名[MAXNAMELEN];
長いボリュームタイプ;
長い nServer。
長いサーバー番号[MAXNSEVERS];
長いサーバーパーティション[MAXNSEVERS];
長いサーバーフラグ[MAXNSEVERS];
u_long volumeId[MAXTYPES];
長い旗。
};

typedef struct single_vldbentry *vldblist;
構造体 single_vldbentry {
vldbentry VldbEntry;
vldblist next_vldb;
};

構造体 vldb_list {
vldblist ノード。
};

/* vldb インターフェイス呼び出し */

CreateEntry (IN ロング Volid、
vldbentry *newentry) = VLCREATEENTRY;

GetEntryByName (IN 文字列ボリューム名、
OUT vldbentry *entry) = VLGETENTRYBYNAME;

GetNewVolumeId (IN 長いバンプカウント、
OUT ロング *newvolumid) = VLGETNEWVOLUMEID;

ReplaceEntry (IN ロング Volid、
ロングボルタイプ、
vldbentry *新しいエントリ、
long ReleaseType) multi = VLREPLACEENTRY;

ListAttributes (IN VldbListByAttributes *属性、
OUT ロング * エントリ、
OUT vldbentry バルクエントリー)
= VLLIST属性;

LinkedList (IN VldbListByAttributes *属性、
OUT ロング * エントリ、
OUT vldb_list *linkedentries) = VLLINKEDLIST;

R が生成したコード (-R オプション)
すぐに時代遅れになります。 内部の Rx 関連の呼び出しの詳細については、
生成されたスタブ (すなわち、 rx_NewCall(), rx_EndCall())、何が起こるかについての詳細
特定の呼び出し内 (例: xdrrx_create()) Rx のドキュメントを参照してください。 タイピング
「rxgen vldbint.xg」により、次の XNUMX つのファイルが作成されます。 vldbint.h, vldbint.xdr.c,
vldbint.cs.cvldbint.ss.c。 これらのファイルを詳しく見ていきます。

ヘッダ file (vldbint.h)

/* 機械で生成されたファイル -- 編集しないでください */

#include "vl_opcodes.h" /* 他の場所に直接 */
#define マックスネームレン 65
#MAXNSERVERS 8 の定義
#定義 MAXTYPES 3

構造体 vldbentry {
文字名[MAXNAMELEN];
長いボリュームタイプ;
長い nServer。
長いサーバー番号[MAXNSEVERS];
長いサーバーパーティション[MAXNSEVERS];
長いサーバーフラグ[MAXNSEVERS];
u_long volumeId[MAXTYPES];
長い旗。
};
typedef 構造体 vldbentry vldbentry;
bool_t xdr_vldbentry();

typedef struct single_vldbentry *vldblist;
bool_t xdr_vldblist();

構造体 single_vldbentry {
vldbentry VldbEntry;
vldblist next_vldb;
};
typedef 構造体 single_vldbentry single_vldbentry;
bool_t xdr_single_vldbentry();

構造体 vldb_list {
vldblist ノード。
};
typedef 構造体 vldb_list vldb_list;
bool_t xdr_vldb_list();

#含む
#define multi_VL_ReplaceEntry(Volid, voltype, newentry, ReleaseType) \
multi_Body(StartVL_ReplaceEntry(multi_call, Volid, voltype,
新しいエントリ、リリースタイプ)、 EndVL_ReplaceEntry(マルチコール))

typedef structBulkentries {
u_intBulkentries_len;
vldbentry *bulkentries_val;
大量のエントリ;
bool_t xdr_bulkentries();

/* パッケージのオペコード関連の有用な統計: VL_ */
#VL_LOWEST_OPCODE 501 を定義
#VL_HIGHEST_OPCODE 506 を定義
#定義 VL_NUMBER_OPCODES 6

すべての構造体が自動的に typedef され、すべての「const」が次のように変換されることに注意してください。
「#define」。 バルクエントリなどの一部のデータ構造はプロシージャパラメータから取得されます。
(ListAttributes プロシージャから)。 したがって、スタブを作成するときは、この点に留意する必要があります。
少しずつ rxgen (つまり、 -c, -h, -Cまたは -S フラグ)。 また、側面のXNUMXつは、
「multi」オプション (「ReplaceEntry」プロシージャ内) の効果は、
上記の「multi_VL_ReplaceEntry」。

XDR ルーチン for 構造 (vldbint.xdr.c)

/* 機械で生成されたファイル -- 編集しないでください */

#含む
#include "vldbint.h"

#include "vl_opcodes.h" /* 他の場所に直接 */

ブール値
xdr_vldbentry(xdrs, objp)
XDR *xdrs;
vldbentry *objp;
{
if (!xdr_vector(xdrs, (char *)objp->name, MAXNAMELEN,
sizeof(char), xdr_char))
(FALSE) を返します。
if (!xdr_long(xdrs, &objp->volumeType))
(FALSE) を返します。
if (!xdr_long(xdrs, &objp->nServers))
(FALSE) を返します。
if (!xdr_vector(xdrs, (char *)objp->serverNumber, MAXNSERVERS,
sizeof(long)、xdr_long))
(FALSE) を返します。
if (!xdr_vector(xdrs, (char *)objp->serverPartition,
MAXNSERVERS、sizeof(long)、xdr_long))
(FALSE) を返します。
if (!xdr_vector(xdrs, (char *)objp->serverFlags, MAXNSERVERS,
sizeof(long)、xdr_long))
(FALSE) を返します。
if (!xdr_vector(xdrs, (char *)objp->volumeId, MAXTYPES,
sizeof(u_long)、xdr_u_long))
(FALSE) を返します。
if (!xdr_long(xdrs, &objp->flags))
(FALSE) を返します。
戻り値 (TRUE);
}

ブール値
xdr_vldblist(xdrs, objp)
XDR *xdrs;
vldblist *objp;
{
if (!xdr_pointer(xdrs, (char **)objp,
sizeof(struct single_vldbentry),
xdr_single_vldbentry))
(FALSE) を返します。
戻り値 (TRUE);
}

ブール値
xdr_single_vldbentry(xdrs, objp)
XDR *xdrs;
single_vldbentry *objp;
{
if (!xdr_vldbentry(xdrs, &objp->VldbEntry))
(FALSE) を返します。
if (!xdr_vldblist(xdrs, &objp->next_vldb))
(FALSE) を返します。
戻り値 (TRUE);
}

ブール値
xdr_vldb_list(xdrs, objp)
XDR *xdrs;
vldb_list *objp;
{
if (!xdr_vldblist(xdrs, &objp->node))
(FALSE) を返します。
戻り値 (TRUE);
}

ブール値
xdr_bulkentries(xdrs, objp)
XDR *xdrs;
バルクエントリー *objp;
{
if (!xdr_array(xdrs, (char **)&objp->bulkentries_val,
(u_int *)&objp->bulkentries_len、MAXVLDBLEN、
sizeof(vldbentry), xdr_vldbentry))
(FALSE) を返します。
戻り値 (TRUE);
}

なお、 xdr_bulkentries() プロシージャの副作用として自動的に生成されます
パラメータ宣言。 したがって、同一の複数の型パラメータ宣言が使用される場合、
そうすると、複数定義された xdr_* スタブが作成されます。 これがより良い代替手段であると感じました
を持つことに rxgen プログラマは、Bulkentries_1、Bulkentries_2 などの型を処理します。

クライアント側 スタブ ルーチン (vldbint.cs.c)

/* 機械で生成されたファイル -- 編集しないでください */

#含む
#含む
#含む
#include "vldbint.h"

#include "vl_opcodes.h" /* 他の場所に直接 */

int VL_CreateEntry(z_conn, Volid, newentry)
構造体 rx_connection *z_conn を登録します。
長いボリューム。
vldbentry * 新しいエントリ;
{
struct rx_call *z_call = rx_NewCall(z_conn);
静的 int z_op = 501;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &Volid))
|| (!xdr_vldbentry(&z_xdrs, newentry))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
return rx_EndCall(z_call, z_result);
}

int VL_GetEntryByName(z_conn, ボリューム名, エントリ)
構造体 rx_connection *z_conn を登録します。
char * ボリューム名;
vldbentry * エントリ;
{
struct rx_call *z_call = rx_NewCall(z_conn);
静的 int z_op = 504;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_string(&z_xdrs, &ボリューム名, 65))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

/* 応答引数のアンマーシャル */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_vldbentry(&z_xdrs, エントリ))) {
z_result = RXGEN_CC_UNMARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
return rx_EndCall(z_call, z_result);
}

int VL_GetNewVolumeId(z_conn, バンプカウント, newvolumid)
構造体 rx_connection *z_conn を登録します。
長いバンプカウント。
長い * newvolumid;
{
struct rx_call *z_call = rx_NewCall(z_conn);
静的 int z_op = 505;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &bumpcount))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

/* 応答引数のアンマーシャル */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_long(&z_xdrs, newvolumid))) {
z_result = RXGEN_CC_UNMARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
return rx_EndCall(z_call, z_result);
}

int VL_ReplaceEntry(z_conn, Volid, voltype, newentry, ReleaseType)
構造体 rx_connection *z_conn を登録します。
長い Volid、voltype、ReleaseType;
vldbentry * 新しいエントリ;
{
struct rx_call *z_call = rx_NewCall(z_conn);
静的 int z_op = 506;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &Volid))
|| (!xdr_long(&z_xdrs, &voltype))
|| (!xdr_vldbentry(&z_xdrs, newentry))
|| (!xdr_long(&z_xdrs, &ReleaseType))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
return rx_EndCall(z_call, z_result);
}

int StartVL_ReplaceEntry(z_call、Volid、voltype、newentry、ReleaseType)
構造体 rx_call *z_call を登録します。
長い Volid、voltype、ReleaseType;
vldbentry * 新しいエントリ;
{
静的 int z_op = 506;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_long(&z_xdrs, &Volid))
|| (!xdr_long(&z_xdrs, &voltype))
|| (!xdr_vldbentry(&z_xdrs, newentry))
|| (!xdr_long(&z_xdrs, &ReleaseType))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
z_result を返します。
}

int EndVL_ReplaceEntry(z_call)
構造体 rx_call *z_call を登録します。
{
int z_result;
XDR z_xdrs;

z_result = RXGEN_SUCCESS;
失敗:
z_result を返します。
}

int VL_ListAttributes(z_conn, 属性, nentries,Bulkentries_1)
構造体 rx_connection *z_conn を登録します。
VldbListByAttributes * 属性;
長い * エントリ;
バルクエントリ * バルクエントリ_1;
{
struct rx_call *z_call = rx_NewCall(z_conn);
静的 int z_op = 511;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_VldbListByAttributes(&z_xdrs, 属性))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

/* 応答引数のアンマーシャル */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_long(&z_xdrs, nentries))
|| (!xdr_bulkentries(&z_xdrs,Bulkentries_1))) {
z_result = RXGEN_CC_UNMARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
return rx_EndCall(z_call, z_result);
}

int VL_LinkedList(z_conn, 属性, nentries, linkedentries)
構造体 rx_connection *z_conn を登録します。
VldbListByAttributes * 属性;
長い * エントリ;
vldb_list * リンクされたエントリ;
{
struct rx_call *z_call = rx_NewCall(z_conn);
静的 int z_op = 512;
int z_result;
XDR z_xdrs;

xdrrx_create(&z_xdrs, z_call, XDR_ENCODE);

/* 引数を整理します */
if ((!xdr_int(&z_xdrs, &z_op))
|| (!xdr_VldbListByAttributes(&z_xdrs, 属性))) {
z_result = RXGEN_CC_MARSHAL;
失敗します。
}

/* 応答引数のアンマーシャル */
z_xdrs.x_op = XDR_DECODE;
if ((!xdr_long(&z_xdrs, nentries))
|| (!xdr_vldb_list(&z_xdrs, linkedentries))) {
z_result = RXGEN_CC_UNMARSHAL;
失敗します。
}

z_result = RXGEN_SUCCESS;
失敗:
return rx_EndCall(z_call, z_result);
}

「マルチ」機能 (「ReplaceEntry」の XNUMX つの異なるモジュール) の副作用に注意してください。
手続き)。

サーバ側 スタブ ルーチン (vldbint.ss.c)

/* 機械で生成されたファイル -- 編集しないでください */

#含む
#含む
#含む
#include "vldbint.h"

#include "vl_opcodes.h" /* 他の場所に直接 */

long _VL_CreateEntry(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
長い z_result;
長いボリューム。
vldbentry 新しいエントリ;

if ((!xdr_long(z_xdrs, &Volid))
|| (!xdr_vldbentry(z_xdrs, &newentry))) {
z_result = RXGEN_SS_UNMARSHAL;
失敗します。
}

z_result = VL_CreateEntry(z_call, Volid, &newentry);
失敗:
z_result を返します。
}

long _VL_GetEntryByName(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
長い z_result;
char *ボリューム名 = (char *)0;
vldbentry エントリ;

if ((!xdr_string(z_xdrs, &volumename, 65))) {
z_result = RXGEN_SS_UNMARSHAL;
失敗します。
}

z_result = VL_GetEntryByName(z_call, &volumename, &entry);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_vldbentry(z_xdrs, &entry)))
z_result = RXGEN_SS_MARSHAL;
失敗:
z_xdrs->x_op = XDR_FREE;
if (!xdr_string(z_xdrs, &volumename, 65)) goto failed1;
z_result を返します。
失敗1:
RXGEN_SS_XDRFREE を返します。
}

long _VL_GetNewVolumeId(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
長い z_result;
長いバンプカウント。
長い新しいボリューム。

if ((!xdr_long(z_xdrs, &bumpcount))) {
z_result = RXGEN_SS_UNMARSHAL;
失敗します。
}

z_result = VL_GetNewVolumeId(z_call, バンプカウント, &newvolumid);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_long(z_xdrs, &newvolumid)))
z_result = RXGEN_SS_MARSHAL;
失敗:
z_result を返します。
}

long _VL_ReplaceEntry(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
長い z_result;
長い Volid、voltype、ReleaseType;
vldbentry 新しいエントリ;

if ((!xdr_long(z_xdrs, &Volid))
|| (!xdr_long(z_xdrs, &voltype))
|| (!xdr_vldbentry(z_xdrs, &newentry))
|| (!xdr_long(z_xdrs, &ReleaseType))) {
z_result = RXGEN_SS_UNMARSHAL;
失敗します。
}

z_result = VL_ReplaceEntry(z_call, Volid, voltype, &newentry,
リリースタイプ);
失敗:
z_result を返します。
}

long _VL_ListAttributes(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
長い z_result;
VldbListByAttributes 属性。
長いネトリー。
バルクエントリー バルクエントリー_1;

if ((!xdr_VldbListByAttributes(z_xdrs, &attributes))) {
z_result = RXGEN_SS_UNMARSHAL;
失敗します。
}

z_result = VL_ListAttributes(z_call, &attributes, &nentries,
&bulkentries_1);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_long(z_xdrs, &nentries))
|| (!xdr_bulkentries(z_xdrs, &bulkentries_1)))
z_result = RXGEN_SS_MARSHAL;
失敗:
z_xdrs->x_op = XDR_FREE;
if (!xdr_bulkentries(z_xdrs, &bulkentries_1)) goto failed1;
z_result を返します。
失敗1:
RXGEN_SS_XDRFREE を返します。
}

long _VL_LinkedList(z_call, z_xdrs)
struct rx_call *z_call;
XDR *z_xdrs;
{
長い z_result;
VldbListByAttributes 属性。
長いネトリー。
vldb_list リンクされたエントリ;

if ((!xdr_VldbListByAttributes(z_xdrs, &attributes))) {
z_result = RXGEN_SS_UNMARSHAL;
失敗します。
}

z_result = VL_LinkedList(z_call, &attributes, &nentries,
&linkedentries);
z_xdrs->x_op = XDR_ENCODE;
if ((!xdr_long(z_xdrs, &nentries))
|| (!xdr_vldb_list(z_xdrs, &linkedentries)))
z_result = RXGEN_SS_MARSHAL;
失敗:
z_result を返します。
}

長い _VL_CreateEntry();
long _VL_GetEntryByName();
長い_VL_GetNewVolumeId();
長い _VL_ReplaceEntry();
長い _VL_ListAttributes();
長い _VL_LinkedList();

static long (*StubProcsArray0[])() = {_VL_CreateEntry,
_VL_GetEntryByName、_VL_GetNew VolumeId、_VL_ReplaceEntry、
_VL_ListAttributes、_VL_LinkedList};

VL_ExecuteRequest(z_call)
構造体 rx_call *z_call を登録します。
{
整数演算;
XDR z_xdrs;
長い z_result;

xdrrx_create(&z_xdrs, z_call, XDR_DECODE);
if (!xdr_int(&z_xdrs, &op))
z_result = RXGEN_DECODE;
else if (op < VL_LOWEST_OPCODE || op > VL_HIGHEST_OPCODE)
z_result = RXGEN_OPCODE;
ほかに
z_result = (*StubProcsArray0[op - VL_LOWEST_OPCODE])
(z_call, &z_xdrs);
z_result を返します。
}

プロシージャのオペコード シーケンスにギャップがある場合、 VL_ExecuteRequest()
ルーチンは大幅に異なっていたでしょう(それは、
それぞれの手順)。

注意事項


rxgen Sun から実装されています rpcgen 効用。 すべての標準 rpcgen's
機能は完全に維持されます。 一部のアクティブな rpcgen 適用されないオプション
〜へ rxgenの目的はここでは参照されていません(つまり、 -s, -l, -m オプション)および興味のある方
読者は参照する必要があります rpcgen詳細は(1)。

「%#include」の場合機能が使用されている場合は、何も持っていないことを確認してください
rxgen 言語機能 (%#defines など) を使用すると構文エラーが発生するため、
コンピレーション..

これは進行中のプロジェクトであるため、上記の多くは大きな変更がなければ変更または消滅する可能性があります。
警告。

onworks.net サービスを使用してオンラインで rxgen を使用する


無料のサーバーとワークステーション

Windows と Linux のアプリをダウンロード

Linuxコマンド

Ad