XTRAN Example — Impose Included Files on Existing PL/ix Code
Scenario 1 — Re-engineering. As programming manager, you decide to centralize declarations of a variety of functions and data names in one or more included files, for increased ease of maintenance. But declarations of those functions and data names are scattered throughout your system. How do you impose use of the included files and delete all of the now-redundant declarations in the code?
Scenario 2: — Translation. You are using XTRAN to translate legacy code to a new language and platform. You have decided to provide a run-time library comprising target-language versions of the old language's built-in functions that don't have target-language equivalents, and you have created one or more included files that declare all of those "legacy" functions. But the old language allowed programmers to declare those built-in functions in user code, and those declarations are scattered throughout the legacy code. How do you ensure that each translated module that uses any of the legacy functions contains an appropriate "include" statement for your included file, and how do you delete the redundant user declarations of the translated built-in functions and data?
XTRAN's rules language ("meta-code") has a facility designed precisely for this purpose. You specify, in an XTRAN rule:
- The code tree whose contents are to be done; this is usually the "target" code, but it could be a user-created code tree.
- The computer language to be done, since a code tree may contain any supported language, or even a mixture of languages.
- A list of included file names, excluding paths, to be imposed. (XTRAN has a separate facility for specifying a series of paths it is to search to find included files.) Also, optionally for each included file name, how to style a generated "include" statement and a comment for that statement.
XTRAN first parses each named included file, if it hasn't already, so it knows what names each file declares. XTRAN then searches the contents of the named code tree for declaration statements that declare function or data names also declared in any of the named included files. For each such declaration statement XTRAN finds:
- XTRAN suppresses rendering of the declaration in the source code that will get the generated "include" statement. If the declaration statement declares more than one name, XTRAN suppresses only the ones that are declared in any of the named included files.
- If the code tree doesn't already contain an "include" statement for the included file that declares a suppressed name, XTRAN adds such a statement at the beginning of the code tree, so it will be rendered when XTRAN renders the code.
The result is to impose use of the named included files on the code, and to delete all declaration statements made redundant by that imposition.
For scenario 1 above, you would specify, in each XTRAN re-engineering run, that XTRAN is to perform the action on the re-engineered code before rendering it.
For scenario 2 above, you would specify, in each XTRAN translation run, that XTRAN is to perform the action after translating the code but before rendering it.
This XTRAN facility is available for all computer languages XTRAN accommodates.
Example, using translation from IBM's PL/ix to C++ — suppose you tell XTRAN to impose use of the following included files on a body of code:
file1.include
, which declaresfunc1a()
,func1b()
, anddata1
file2.include
, which declaresfunc2()
You also tell XTRAN, for each included file, how to
style any %INCLUDE
statement it may generate for the file,
including a comment for the statement.
Process Flowchart
Here are flowcharts for both scenarios, in which the elements are color coded:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
code
Input to XTRAN:
DCL func1a ENTRY RETURNS (INTEGER) EXTREF; !DCL func1a ENTRY RETURNS (INTEGER) EXTREF; DCL func2 ENTRY (INTEGER) EXTREF; !DCL func2 ENTRY (INTEGER) EXTREF; DCL func3 ENTRY EXTREF; !DCL func3 ENTRY EXTREF; DCL (data1, data2) INTEGER EXTREF; !DCL (data1, data2) INTEGER EXTREF; prc: PROCEDURE; DCL data3 INTEGER; !DCL data3 INTEGER; data1 = func1a; !data1 = func1a; data2 = data1; !data2 = data1; func2(data3); !func2(data3); func3; !func3; END prc;
Output from XTRAN:
#include "file2.h" //2nd demo include #include <file1.h> //1st demo include extern int32 data2; //DCL (data1, data2) INTEGER EXTREF; extern void func3(void); //DCL func3 ENTRY EXTREF; void prc(void) { int32 data3; //DCL data3 INTEGER; data1 = func1a(); //data1 = func1a; data2 = data1; //data2 = data1; func2(data3); //func2(data3); func3(); //func3; }