プリプロセッサー入力に、次のストリングが含まれているとします。
%DECLARE A CHARACTER, B FIXED; %A = 'B+C'; %B = 2; X = A;
すると、次のステートメントがプリプロセッサー出力に挿入されます。
X = 2+C;
これらのプリプロセッサー・ステートメントは、デフォルトの値である RESCAN を指定して A と B を 活動化し、文字ストリング 'B+C' を A に割り当て、さらに定数 2 を B に割り当てます。
4 行目は入力テキストです。 A の現行値、つまり 'B+C' が A の代わりとしてプリプロセッサー出力の 中に挿入されます。 ただし、このストリングにはプリプロセッサー変数 B が含まれているので、プリプロセッサーは B を再走査し、B が活動化されていることを見つけます。 ですから、プリプロセッサー出力内の B は値 2 に置き換わります。 プリプロセッサー変数 B の精度は、デフォルトの精度 (5,0) なので、 実際には 2 の前に 0 が 4 つ付いています。 ストリング 'B+C' 内の B がこの値で置き換えられるときに、この値は文字ストリングに変換されるので、2 の前にブランクが 7 つ付きます。
さらに再走査が行われ、2 をこれ以上置き換えられないことがわかると、 +C から走査が再開されます。これも置き換えることはできません。
上記の例で、プリプロセッサー変数 A が次のステートメントによって 活動化されたとします。
%ACTIVATE A NORESCAN;
すると、プリプロセッサー出力は次のようになります。
X = B+C;
プリプロセッサー入力に、次のストリングが含まれているとします。
%DECLARE I FIXED, T CHARACTER; %DEACTIVATE I; %I = 15; %T = 'A(I)'; S = I*T*3; %I = I+5; %ACTIVATE I; %DEACTIVATE T; R = I*T*2
すると、プリプロセッサー出力は次のようになります (置き換えのブランクは 示していません)。
S = I*A(I)*3; R = 20*T*2;
この例は、プリプロセッサーの諸機能を使用して、次のような DO グループの実行速度を上げる方法を示したものです。
DO I=1 TO 10; Z(I)=X(I)+Y(I); END;
下記のように書けば、上記のように書くのと同じ結果になり、しかも、 コンパイル済みプログラムの実行中に増分を加えてテストする必要がなくなります。
%DECLARE I FIXED; %DO I = 1 TO 10; Z(I)=X(I)+Y(I); %END; %DEACTIVATE I;
3 行目は入力テキストなので、置き換えをする必要があるかどうかを 調べるために走査されます。 この行が最初に走査されたときは、I の値は 1 であり、しかも I は 活動化されています。 ですから、次のステートメントがプリプロセッサー出力に挿入されます。
Z( 1)=X( 1)+Y( 1);
1 の前には、それぞれブランクが 7 入ります。
I の値が増えて 10 になるまで、そのつど、入力テキストが走査され、 I があれば I の現行値で置き換えられます。 その結果、次のステートメントがプリプロセッサー出力に挿入されます。
Z( 1)=X( 1)+Y( 1);
Z( 2)=X( 2)+Y( 2);
.
.
.
Z( 10)=X( 10)+Y( 10);
I の値が 11 に達すると、制御が %DEACTIVATE ステートメントに渡ります。
下記のプリプロセッサー入力内の VALUE は、'arg1(arg2)' の形をした文字ストリングを返すプリプロセッサー関数プロシージャーです。ただし、 arg1 と arg2 は、この関数に渡される引数を表しています。
DECLARE (Z(10), Q) FIXED;
%A='Z';
%ACTIVATE A, VALUE;
Q = 6 + VALUE(A,3);
%DECLARE A CHARACTER;
%VALUE: PROC(ARG1,ARG2) RETURNS(CHAR);
DCL ARG1 CHAR, ARG2 FIXED;
RETURN(ARG1||'('||ARG2||')');
%END VALUE;
4 行目が走査されるとき、A はアクティブになっているので置き換えに対して適格です。 VALUE もアクティブなので、4 行目で VALUE が参照されると、その名前のプリプロセッサー関数プロシージャーが起動します。
ただし、引数 A と 3 が VALUE に渡される前に、A は値 Z (前の 代入ステートメントで A に割り当てられた値) で置き換えられ、 3 は対応するパラメーターの属性に合わせて固定小数点フォーマットに変換されます。 引数が渡されると、VALUE はこれらの引数と括弧の連結演算を行い、 結果の値、つまりストリング Z (3) を呼び出し点に返します。 関数参照が戻り値で置き換えられ、その結果がプリプロセッサー出力に 挿入されます。 その結果、次のようなプリプロセッサー出力が生成されます。
DECLARE (Z(10),Q) FIXED; Q = 6+Z( 3);
下記のように定義されたプリプロセッサー関数プロシージャー GEN は、 最高 99 個の入り口名 (パラメーター記述子リスト内に最高 99 個の パラメーター記述子を持つ) を指定する GENERIC 宣言を生成することができます。 この例では、4 個だけが生成されます。
%DCL GEN ENTRY;
DCL A GEN (A,2,5,FIXED);
%GEN: PROC(NAME,LOW,HIGH,ATTR) RETURNS (CHAR);
DCL (NAME, SUFFIX, ATTR, STRING) CHAR, (LOW, HIGH, I, J) FIXED;
STRING='GENERIC(';
DO I=LOW TO HIGH; /* ENTRY NAME LOOP*/
IF I>9 THEN
SUFFIX=SUBSTR(I, 7, 2);
/* 2 DIGIT SUFFIX*/
ELSE SUFFIX=SUBSTR(I, 8, 1);
/* 1 DIGIT SUFFIX*/
STRING=STRING||NAME||SUFFIX||' WHEN (';
DO J=1 TO I; /* DESCRIPTOR LIST*/
STRING=STRING||ATTR;
IF J<I /* ATTRIBUTE SEPARATOR*/
THEN STRING=STRING||',';
ELSE STRING=STRING||')';
/* LIST SEPARATOR */
END;
IF I<HIGH THEN /* ENTRY NAME SEPARATOR*/
STRING=STRING||',';
ELSE STRING=STRING||')';
/* END OF LIST /*
END;
RETURN (STRING)
% END;
次のようなプリプロセッサー出力が作成されます。
DCL A GENERIC(A2 WHEN (FIXED,FIXED),
A3 WHEN (FIXED, FIXED, FIXED),
A4 WHEN (FIXED, FIXED, FIXED, FIXED),
A5 WHEN (FIXED, FIXED, FIXED, FIXED, FIXED));
この例では、下記のフォーマットのステートメントと同じ働きをする プリプロセッサー・プロシージャーを示します。
SEARCH TABLE(array) FOR(value) USING(variable) AND(variable);
このステートメントは、配列添え字として指定した (またはデフォルトの) 変数 を使用して、指定した値を求めて 2 次元配列を探索するための ステートメントです。 このステートメントが実行されると、指定した値がどのエレメントに入っているかが 配列添え字変数によって示されます。 指定した値がどのエレメントにも入っていない場合は、両方の添え字変数が -22222 にセットされます。
このステートメントと同じ働きをするプリプロセッサー・プロシージャーは、 次のとおりです。
%SEARCH:
PROC(TABLE,FOR,USING,AND) STATEMENT RETURNS(CHARACTER);
DECLARE(TABLE,FOR,USING,AND,LABL, DO1,DO2) CHARACTER,
(PARMSET,COUNTER) BUILTIN;
IF PARMSET(TABLE) & PARMSET(FOR) THEN;
ELSE SERR:DO;
NOTE ('MISSING OR INVALID ARGUMENT(S)'||'FOR ''SEARCH''',4);
RETURN ('/*INVALID SEARCH STATEMENT*/');
END;
IF ¬PARMSET(USING) THEN
USING='I';
IF ¬PARMSET(AND) THEN
AND='J';
IF USING = AND THEN
GO TO SERR;
LABL='SL'||COUNTER;
DO1=LABL||': DO '||USING||'=LBOUND('||TABLE||',1)
TO HBOUND('||TABLE||',1);';
DO2='DO '||AND||'=LBOUND('||TABLE||',2)
TO HBOUND ('||TABLE||',2);';
RETURN(DO1||DO2||'SELECT('||TABLE
||'('||USING||','||AND||'));
WHEN('||FOR||') LEAVE '||LABL||';
OTHER;
END '||LABL||';
IF '||AND||' > H BOUND('||TABLE||',2) THEN
'||USING||','||AND||.' = -22222;');
%END SEARCH;
この例では、PARMSET 組み込み関数を使用して、このプロシージャーが 呼び出されたときにどのパラメーターがセットされるかを判別しています。 USING がセットされていない場合、配列添え字付き変数 I のデフォルトが使用されます。 AND がセットされていないと、J が使用されます。 TABLE または FOR がセットされていないか、または呼び出しの結果として 両方の添え字が同じ変数になった場合は、プリプロセッサー診断メッセージが 出され、コメントがプリプロセッサー出力に返されます。
COUNTER 組み込み関数は、このプロシージャーから返されるプリプロセッサー 出力に固有のラベルを付けるために使われています。
このプロシージャーを呼び出すときには、キーワード引数、定位置引数、 または両者の組み合わせのどれでも指定することができます。 次のようにプロシージャーを呼び出すと、同じ結果が生成されます。
SEARCH TABLE(LIST.NAME) FOR('J.DOE') USING(I) AND(J);
SEARCH TABLE(LIST.NAME) FOR('J.DOE');
SEARCH(LIST.NAME) FOR('J.DOE');
SEARCH(LIST.NAME,'J.DOE');
SEARCH(,'J.DOE') TABLE(LIST.NAME);
どの方法で呼び出した場合も、返されたプリプロセッサー出力は 次のようになります。
SL00001:
DO I=LBOUND(LIST.NAME,1) TO HBOUND(LIST.NAME,1);
DO J=LBOUND(LIST.NAME,2) TO HBOUND(LIST.NAME,2);
SELECT(LIST.NAME(I,J));
WHEN('J.DOE') LEAVE SL00001;
OTHER;
END SL00001;
IF J > HBOUND(LIST.NAME,2) THEN
I,J = -22222;
ラベル SL00001 は、最初の呼び出しの場合にだけ返されます。 それ以後、このプロシージャーを呼び出すたびに、新しい固有のラベルが 返されます。