XTRAN Example — Analyze Constant/Expression PL/I PROCEDURE Arguments
PL/I normally passes arguments to PROCEDURE
s "by reference";
that is, what is passed is the address of the argument. However, if a
calling argument is a constant or an expression, PL/I passes it "by
copy": The PL/I compiler generates code to create a local copy of the
constant or expression value and passes the copy's address as the argument.
When XTRAN translates PL/I to C/C++, it reflects this behavior: It normally generates code to pass an argument's address, but if the argument is a constant or expression, it generates code to declare a local copy and pass its address.
However, the chances are that if PL/I code passes a constant or expression
as an argument, then the called PROCEDURE
doesn't modify the
corresponding parameter. Even if it does, it modifies only the copy whose
address was passed to it. Therefore, in the translated C/C++ we can
safely pass the parameter by value. In
fact, XTRAN extends the PL/I language by adding a new
declaration attribute, XTR_BYVAL
, which
tells XTRAN to translate the
PROCEDURE
parameter and all corresponding calling arguments as
"pass by value".
The knowledge of which PROCEDURE
parameters actually have
matching arguments that are constants or expressions is scattered throughout
all of the PL/I modules to be translated.
XTRAN's powerful PL/I analysis capability to the rescue!
The following example uses a set of XTRAN rules
("meta-language") that analyzes all arguments of all PROCEDURE
calls in the code it is given and creates a data base of constant and
expression argument occurrences, capturing the following information for each
such occurrence:
PROCEDURE
name, qualified ifexternal
,static
, inferred, or nested- Argument number (1-n)
- Source file name and line number
We run this analysis on each module to be translated; the rules append the occurrence information to the data base file we're creating. When we have all the data, we use another set of rules that creates a report of the data, eliminating duplicates and sorting occurrences appropriately.
We can then modify the appropriate PROCEDURE
parameter
declarations in the PL/I code to be translated, adding XTR_BYVAL
where appropriate. Click
to see an actual
translation example using this technique for the code below.
The following input to, and output from, XTRAN is untouched except for line numbers added to the input for reference.
Process Flowchart
Here is a flowchart for this process, in which the elements are color coded:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
code - PURPLE for text data files
Input to XTRAN (demcpa-a.pli):
1 DCL extprc1 ENTRY (FIXED (15) BIN, FLOAT (5) BIN, 2 FIXED (31) BIN) EXT; 3 DCL extprc2 ENTRY (CHAR (*), FIXED (31) DEC, FIXED (15) BIN) EXT; 4 5 % DCL (ppint1, ppint2) FIXED; 6 % ppint1 = 1; 7 % ppint2 = 2; 8 % DCL (ppchr1, ppchr2) CHAR; 9 % ppchr1 = '''abc'''; 10 % ppchr2 = '''xy'''; 11 % DCL ppexpr FIXED; 12 % ppexpr = ppint1 + 1; 13 14 prc: PROCEDURE; 15 DCL (int1, int2) FIXED (31) BIN; 16 DCL (flt1, flt2) FLOAT (5) DEC; 17 DCL (chr1, chr2) CHAR (5); 18 19 nstprc: PROCEDURE (arg1, arg2); /*nstprc: PROCEDURE...;*/ 20 DCL arg1 FIXED (31) BIN XTR_BYVAL; 21 DCL (arg2, i) FIXED (31) BIN; 22 i = extprc1(1, 2.0, i); /*const args 1 & 2*/ 23 END nstprc; 24 extprc1(int1, flt1, i); /*no const args*/ 25 extprc1(1, flt1, int1); /*const arg 1*/ 26 extprc1(int1 + 1, flt1, int1); /*expr arg 1*/ 27 extprc1(ppexpr, flt1, int1); /*expr arg 1*/ 28 extprc1(int1, 1.0, int1); /*const arg 2*/ 29 extprc1(ppint1, flt2, int1); /*const arg 1*/ 30 extprc2(chr1, int2, int1); /*no const args*/ 31 extprc2('abc', int2, int1); /*const arg 1*/ 32 extprc2(chr1, 2, int1); /*const arg 2*/ 33 extprc2('a' | 'bc', 2, int1); /*expr arg 1, const arg 2*/ 34 extprc2(ppchr1, chr2, int1); /*const arg 1*/ 35 extprc2('abc', ppchr2, int1); /*const arg numbers 1,2*/ 36 nstprc(int1, int2); /*no const args*/ 37 nstprc(1, int2); /*const arg 1*/ 38 end prc;
Output from XTRAN:
Constant/Expression PROCEDURE Argument Numbers Legend: [X] means declared "external" [S] means declared "static" [N] means nested declaration [I] means inferred declaration extprc1[X] Argument 1 demcpa-a.pli: 22,25,26,27,29 Argument 2 demcpa-a.pli: 22,28 extprc2[X] Argument 1 demcpa-a.pli: 31,33,34,35 Argument 2 demcpa-a.pli: 32,33,35 nstprc[N] Argument 1 demcpa-a.pli: 37