How can I retrieve or print non-interactively what source file an RPGLE module was compiled from? I know how to find this information interactively using the DSPPGM command. The DSPOBJD command does not show any value for an RPGLE program.
Software/Hardware used:
ASKED:
April 15, 2005 3:08 PM
UPDATED:
November 1, 2010 4:05 AM
Here’s a basic ILE CL module that will list modules of all programs in a given library into a user space. It then loops through the space one entry at a time, extracts program/module information and prints a line for each including sourcefile/library/member.
It requires at least V5R3 as written, but the V5R3 features can be replaced with pre-V5R3 techniques to make it work on much older releases. It can be updated for V5R4 to take advantages of pointers and data structures.
Compile it as a module. Create a program from it, specifying the QC2LE binding directory to bring printf in.Use ACTGRP(*NEW) to close the spooled file easier.
/* + Compile module mylib/LSTPGMMOD. Then: + CRTPGM PGM( mylib/LSTPGMMOD ) + BNDDIR( QC2LE ) + ACTGRP( *NEW ) + */ pgm ( + &pLib + ) dcl &pLib *char 10 dcl &qObj *char 20 dcl &qUsrSpc *char 20 value( 'LSTPGMMOD QTEMP' ) dcl &Pgm *char 10 value( ' ' ) dcl &PgmLib *char 10 value( ' ' ) dcl &Mod *char 10 value( ' ' ) dcl &ModLib *char 10 value( ' ' ) dcl &SrcF *char 10 value( ' ' ) dcl &SrcFLib *char 10 value( ' ' ) dcl &SrcMbr *char 10 value( ' ' ) dcl &ModCrt *char 13 value( ' ' ) dcl &SrcChg *char 13 value( ' ' ) /* General fields for retrieve *USRSPC header... */ dcl &offslst *int dcl &nbrlste *int dcl &sizlste *int dcl &NbrLE *int dcl &us_hdr *char 150 dcl &ModEnt *char 512 dcl &rc *int value( 0 ) dcl &nl *char 1 value( x'15' ) dcl &ff *char 1 value( x'0C' ) dcl &nul *char 1 value( x'00' ) dcl &PagHdr *char 134 dcl &MsgTxt *char 134 dcl &lines *int value( 3 ) /* General fields for retrieve *USRSPC header... */ /* Create a *USRSPC... */ call QUSCRTUS ( + &qusrspc + 'PGMMOD ' + x'00004000' + X'00' + '*ALL ' + 'List *PGM module info ' + '*YES ' + x'0000000000000000' + ) /* List *ALL program's modules into *USRSPC... */ chgvar &qObj ( '*ALL ' *cat &pLib ) call QBNLPGMI ( + &qusrspc + 'PGML0100' + &qObj + x'0000000000000000' + ) /* Retrieve *USRSPC header for offset, count and size of entries... */ call QUSRTVUS ( + &qusrspc + x'00000001' + x'00000096' + &us_hdr + ) /* */ /* Get the offset to the list within the space, the number */ /* of list entries and size of each entry from the header. */ /* */ chgvar &offslst %bin( &us_hdr 125 4 ) chgvar &nbrlste %bin( &us_hdr 133 4 ) chgvar &sizlste %bin( &us_hdr 137 4 ) /* If no entries, then get out of here... */ if ( &nbrlste *eq 0 ) do sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( 'No modules found.' ) goto End_Mod enddo /* Set the offset to the list within the space... */ chgvar &offslst ( &offslst + 1 ) chgvar &NBRLE &nbrlste /* Set up report; print first heading... */ ovrprtf stdout qsysprt + dfrwrt( *NO ) + splfname( PGMMODLST ) + ovrscope( *ACTGRPDFN ) + opnscope( *ACTGRPDFN ) chgvar &PagHdr ( + 'Program Library Module + Mod Lib Src File Src Lib + Member' *cat + &NL *cat + ' ' *cat + &NL *cat + &nul + ) callprc 'printf' ( + &PagHdr + ) + rtnval( &rc ) /* Loop through the list, printing the info... */ dountil (&NbrLE *lt 1 ) call QUSRTVUS ( + &qusrspc + &offslst + &sizlste + &ModENT + ) /* Get the module, program and library from the list... */ chgvar &Pgm %sst( &ModENT 1 10 ) chgvar &PgmLib %sst( &ModENT 11 10 ) chgvar &Mod %sst( &ModENT 21 10 ) chgvar &ModLib %sst( &ModENT 31 10 ) chgvar &SrcF %sst( &ModENT 41 10 ) chgvar &SrcFLib %sst( &ModENT 51 10 ) chgvar &SrcMbr %sst( &ModENT 61 10 ) chgvar &ModCrt %sst( &ModENT 81 13 ) chgvar &SrcChg %sst( &ModENT 94 13 ) sndpgmmsg msgid( CPF9897 ) msgf( QCPFMSG ) + msgdta( + 'Found' *bcat &ModLib *tcat '/' *cat + &Mod + ) + topgmq( *EXT ) msgtype( *STATUS ) chgvar &MsgTxt ( + &Pgm *cat + ' ' *cat + &PgmLib *cat + ' ' *cat + &Mod *cat + ' ' *cat + &ModLib *cat + ' ' *cat + &SrcF *cat + ' ' *cat + &SrcFLib *cat + ' ' *cat + &SrcMbr *cat + &NL *cat + &nul + ) callprc 'printf' ( + &MsgTxt + ) + rtnval( &rc ) chgvar &lines ( &lines + 1 ) if ( &lines *gt 55 ) do callprc 'printf' ( &ff ) rtnval( &rc ) callprc 'printf' ( + &PagHdr + ) + rtnval( &rc ) chgvar &lines ( 3 ) enddo /* Decrement our loop counter and loop back if more... */ chgvar &offslst ( &offslst + &sizlste ) chgvar &NbrLE ( &NbrLE - 1 ) enddo End_Mod: /* Clear override and delete the *USRSPC... */ dltovr STDOUT lvl( *ACTGRPDFN ) call QUSDLTUS ( + &qusrspc + x'0000000000000000' + ) return endpgmThe printed report is very basic. It should be reasonably easy to see how it can be improved.
Of course, it can all be converted to RPG, COBOL, C, whatever. The APIs work the same anywhere.
Tom
One minor correction — the DLTOVR at the end should technically be moved to before the End_Mod label. It won’t matter unless the &pLib parameter names a library that causes an empty list in the user space, but it’s good practice to keep coding correct.
Tom
Sample printed output from the program:
Tom
As often happens with this editor, the posted CL code has its apostrophes converted to leading- and trailing-quote marks. Make sure they are all properly converted back to apostrophes if you copy the code.
Tom