XTRAN Example — Module/Procedure Cross-Reference of PL/M

The following example uses an XTRAN rules file comprising 176 non-comment lines of XTRAN's rules language ("meta-code") to analyze all declarations of, and calls to, procedures in code, and output that information in the form of delimiter separated values (DSV).  This example uses PL/M code, but the XTRAN rules are not specific to PL/M; they are language-independent, and can therefore be used to analyze any language that allows declaration of, and calls to, procedures or functions.

We then use another XTRAN rules file comprising 259 non-comment lines of XTRAN's rules language to process the DSV module/function data accumulated across modules and create a module/function cross-reference, both directions.  Because this process reads and manipulates only DSV data, we use a rules-only version of XTRAN.

The DSV output from the code mining rules for this example can also be interactively queried, using existing XTRAN rules.

How can such powerful and generalized code analysis and reporting be automated in only 429 total code lines of XTRAN rules?  Because there is so much capability already available as part of XTRAN's rules language.  These rules take advantage of the following functionality:

The input to and output from XTRAN are untouched, except for the addition of line numbers to the input files for reference.


Process Flowchart

Here is a flowchart for this process, in which the elements are color coded:

process flowchart

Input to XTRAN:

File deman1.plm:

 1 proc2: PROCEDURE EXTERNAL;           /*external func decl*/
 2      END proc2;
 3
 4 proc1: PROCEDURE;
 5
 6      proc1a: PROCEDURE;              /*nested func decl*/
 7          CALL proc1a;                /*recursive call*/
 8          CALL proc1;                 /*2nd-order recursive call*/
 9          CALL proc2;                 /*call to external func*/
10          END proc1a;
11
12      CALL proc1;                     /*recursive call*/
13      CALL proc2;                     /*call to external func*/
14      CALL proc2;                     /*duplicate call*/
15      END proc1;

File deman2.plm:

 1 proc1: PROCEDURE EXTERNAL;           /*external func decl*/
 2      END proc1;
 3
 4 proc3: PROCEDURE EXTERNAL;           /*external func decl*/
 5      END proc3;
 6
 7 proc2: PROCEDURE;
 8      CALL proc1;                     /*call to external func*/
 9      CALL proc2;                     /*recursive call*/
10      CALL proc3;                     /*call to external func*/
11      CALL proc3;                     /*duplicate call*/
12      END proc2;


Output from XTRAN:


               PROCEDURE/Function Cross-Reference

Legend:
        C => call
        D => declaration
        E => external globaldeclaration
        I => internal global declaration
        N => nested declaration
        R => recursive call
        S => "static" declaration


Declarations & calls for each procedure/function, by source file:


proc1()
    deman1.plm. . . . . . . . . . . . 4:D, 8:R, 12:R
    deman2.plm. . . . . . . . . . . . 1:E, 8:C
proc1a()
    deman1.plm. . . . . . . . . . . . 6:N, 7:R
proc2()
    deman1.plm. . . . . . . . . . . . 1:E, 9:C, 13:C, 14:C
    deman2.plm. . . . . . . . . . . . 7:D, 9:R
proc3()
    deman2.plm. . . . . . . . . . . . 4:E, 10:C, 11:C

Procedure/function declarations & calls in each source file,
  by procedure/function name:


deman1.plm
    proc1() . . . 4:D, 8:R, 12:R
    proc1a(). . . 6:N, 7:R
    proc2() . . . 1:E, 9:C, 13:C, 14:C
deman2.plm
    proc1() . . . 1:E, 8:C
    proc2() . . . 7:D, 9:R
    proc3() . . . 4:E, 10:C, 11:C