XTRAN Example — Module/Function Cross-Reference of Fortran
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, SUBROUTINE
s and FUNCTION
s in Fortran
code, and output that information in the form of delimiter separated
values (DSV). This example uses Fortran code, but
the XTRAN rules are not specific to Fortran;
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 436 total 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:
- Text file input and output
- Text manipulation
- Text formatting
- Delimited list manipulation
- Regular expression matching
- Environment variable manipulation
- Content-addressable data bases
- "Per statement" recursive iterator
- "Per expression" recursive iterator
- Access to XTRAN's Internal Representation (XIR)
- XIR's language-independent properties
- Creating new meta-functions written in meta-code, which we call user meta-functions
- Meta-variable and meta-function pointers
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:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
code - PURPLE for text data files
Input to XTRAN:
File module1.for:
1 EXTERNAL extfnc, extsub 2 3 INTEGER FUNCTION intf1() 4 intf1 = 1 5 RETURN 6 END 7 8 SUBROUTINE ints1(a, b) 9 CALL extsub() 10 i = undfnc(j) 11 i = extfnc() 12 i = intf1() 13 RETURN 14 END 15 16 SUBROUTINE intf2 17 i = undfnc(j) 18 i = i + 1 19 i = intf1() 20 CALL ints1(i, j) 21 CALL extsub() 22 i = intf1() 23 RETURN 24 END
File module2.for:
1 EXTERNAL extfnc, extsub 2 3 SUBROUTINE ints2(a, b) 4 CALL extsub() 5 i = undfnc(j) 6 INCLUDE 'module3' 7 i = extfnc() 8 INCLUDE 'module3/NOLIST' 9 i = intf2(a, b) 10 i = intf1() 11 RETURN 12 END
File module3.for:
1 CALL extsub()
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: extfnc() module1.for. . . . . . . . . . . . . 1:E, 11:C module2.for. . . . . . . . . . . . . 1:E, 7:C extsub() module1.for. . . . . . . . . . . . . 1:E, 9:C, 21:C module2.for. . . . . . . . . . . . . 1:E, 4:C module3.for. . . . . . . . . . . . . 1:C intf1() module1.for. . . . . . . . . . . . . 3:D, 12:C, 19:C, 22:C module2.for. . . . . . . . . . . . . 10:C intf2() module1.for. . . . . . . . . . . . . 16:D module2.for. . . . . . . . . . . . . 9:C ints1() module1.for. . . . . . . . . . . . . 8:D, 20:C ints2() module2.for. . . . . . . . . . . . . 3:D undfnc() module1.for. . . . . . . . . . . . . 10:C, 17:C module2.for. . . . . . . . . . . . . 5:C Procedure/function declarations & calls in each source file, by procedure/function name: module1.for extfnc(). . . 1:E, 11:C extsub(). . . 1:E, 9:C, 21:C intf1() . . . 3:D, 12:C, 19:C, 22:C intf2() . . . 16:D ints1() . . . 8:D, 20:C undfnc(). . . 10:C, 17:C module2.for extfnc(). . . 1:E, 7:C extsub(). . . 1:E, 4:C intf1() . . . 10:C intf2() . . . 9:C ints2() . . . 3:D undfnc(). . . 5:C module3.for extsub(). . . 1:C