Preprocessor examples
This topic provides a few preprocessor examples.
Example 1
Assume that the preprocessor input contains the following statements:
%DECLARE A CHARACTER, B FIXED;
%A = 'B+C';
%B = 2;
X = A;The following string is inserted into the preprocessor output:
X = 2+C;The preprocessor statements activate A and B with the default RESCAN, assign the character string 'B+C' to A, and assign the constant 2 to B.
The fourth line is input text. The current value of A, which is 'B+C', replaces A in the preprocessor output. But this string contains the preprocessor variable B. Upon rescanning B, the preprocessor finds that it has been activated. Hence, the value 2 replaces B in the preprocessor output. The preprocessor variable B has a default precision of (5,0) and, therefore, actually contains 2 preceded by four zeros. When this value replaces B in the string 'B+C' it is converted to a character string and becomes 2 preceded by seven blanks.
Further rescanning shows that 2 cannot be replaced; scanning resumes with +C, which, again, cannot be replaced.
If, in the preceding example, the
preprocessor variable A was activated by the statement %ACTIVATE
A NORESCAN;, the preprocessor output would be as follows:
X = B+C;Example 2
Assume that the preprocessor input contains the following statements:
%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*2The preprocessor output would be as follows. Replacement blanks are not shown.
S = I*A(I)*3;
R = 20*T*2;Example 3
This example illustrates how preprocessor facilities can be used to speed up the execution of a DO-group.
Here is a DO-group example:
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;I has the value 1 and has been
activated. Therefore, the following string is inserted into the preprocessor
output: Z( 1)=X( 1)+Y( 1);Each 1 is preceded by seven blanks.
I, up to and including 10, the input text is scanned
and each occurrence of I is replaced by its current
value. As a result, the following string is inserted into the preprocessor
output: Z( 1)=X( 1)+Y( 1);
Z( 2)=X( 2)+Y( 2);
.
.
.
Z( 10)=X( 10)+Y( 10);When the value
of I reaches 11, control falls through to the %DEACTIVATE
statement.
Example 4
In the following preprocessor input, VALUE is a preprocessor function procedure that returns a character string of the form 'arg1(arg2)', where arg1 and arg2 represent the arguments that are passed to the function:
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;When the scan encounters the fourth line, A is active and is thus eligible for replacement. Because VALUE is also active, the reference to it in the fourth line invokes the preprocessor function procedure of that name.
However, before the arguments A and 3 are passed to VALUE, A is replaced by its value Z (assigned to A in a previous assignment statement), and 3 is converted to fixed-point to conform to the attribute of its corresponding parameter. VALUE then performs a concatenation of these arguments and the parentheses and returns the concatenated value, that is, the string Z (3), to the point of invocation. The returned value replaces the function reference and the result is inserted into the preprocessor output. Thus, the preprocessor output generated is as follows:
DECLARE (Z(10),Q) FIXED;
Q = 6+Z( 3);Example 5
The preprocessor function procedure GEN defined as follows can generate a GENERIC declaration for up to 99 entry names with up to 99 parameter descriptors in the parameter descriptor lists. Only four are generated in this example.
%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;The preprocessor output produced is as follows:
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));Example 6
SEARCH TABLE(array) FOR(value)
USING(variable) AND(variable);This statement searches a specified two-dimensional array for a specified value, using specified or default variables for the array subscripts. After execution of the statement, the array subscript variables identify an element that contains the specified value. If no element contains the specified value, both subscript variables are set to -22222.
The preprocessor procedure that implements this statement is as follows:
%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;END;
END '||LABL||';
IF '||AND||' > HBOUND('||TABLE||',2) THEN '
||USING||','||AND||' = -22222;');
%END SEARCH;
The PARMSET built-in function is used
to determine which parameters are set when the procedure is invoked.
If USING is not set, the default array subscript variable I is
used. If AND is not set, J is used. If TABLE or FOR
is not set, or if the invocation results in the same variable being
used for both subscripts, a preprocessor diagnostic message is issued
and a comment is returned in the preprocessor output.
The COUNTER built-in function is used to generate unique labels for the preprocessor output returned by the procedure.
The procedure can be invoked with keyword arguments, positional arguments, or a combination of both. The following invocations of the procedure produce identical results:
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);The preprocessor output returned by any of these invocations is as follows:
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;The label SL00001 is returned only for the first invocation. A new unique label is returned for each subsequent invocation.