0 pts.
 Determining Source Files for RPGLE programs.
RPG
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

Answer Wiki:
Actually the DSPOBJD does show the source used but you must have the detail set to *Service DSPOBJD OBJ(OBJ NAME) OBJTYPE(*PGM) DETAIL(*SERVICE) This works interactively at least haven't tried in batch or from a called program yet. I don't see why it wouldn't work though. =================================================================== Since ILE programs aren't compiled, they have no source information in their object descriptions. That's why DETAIL(*SERVICE) doesn't show source. Modules are compiled. To see source related to the program, you need to look at the modules that are bound together to make up the program. DSPPGM will display the module list and each module can be displayed to see source info. To process the info see the <a href="http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/apis/qbnlpgmi.htm">List ILE Program Information (QBNLPGMI) API</a>. Call the API to list the modules into a user space. Loop through the list to process each module entry. Each entry includes source file and member names. A *MODULE object is created from source, so DSPOBJD will show source file information. Tom
Last Wiki Answer Submitted:  October 23, 2010  10:22 am  by  TomLiotta   110,135 pts.
All Answer Wiki Contributors:  TomLiotta   110,135 pts. , TomCarpenter   0 pts.
To see all answers submitted to the Answer Wiki: View Answer History.


Discuss This Question:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _


 

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

endpgm

The 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

 110,135 pts.

 

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

 110,135 pts.

 

Sample printed output from the program:

Program    Library    Module     Mod Lib    Src File   Src Lib    Member

BITAND     TOML       BITAND     QTEMP      QRPGLESRC  TOML       BITAND
BLDFLST    TOML       BLDFLST    QTEMP      QWEBCLSRC  TOML       BLDFLST
BLDMBRLST  TOML       BLDMBRLST  QTEMP      QWEBCLSRC  TOML       BLDMBRLST
BLDOBJLST  TOML       BLDOBJLST  QTEMP      QWEBCLSRC  TOML       BLDOBJLST
TSTBITOR   TOML       TSTBITOR   TOML       QCLTSRC    TOML       TSTBITOR
TSTBITOR   TOML       NOMAIN     TOML       QRPGLESRC  TOML       NOMAIN
TSTDAYWK   TOML       TSTDAYWK   TOML       QCLTSRC    TOML       TSTDAYWK
TSTDAYWK   TOML       DAYWK      TOML       QCLTSRC    TOML       DAYWK
TSTEVAL    TOML       TSTCEVAL   TOML       QCLTSRC    TOML       TSTCEVAL
TSTEVAL    TOML       TSTEVAL    TOML       QRPGLESRC  TOML       TSTEVAL
TSTEXPONNT TOML       TSTEXPONNT TOML       QCLTSRC    TOML       TSTEXPONNT
TSTEXPONNT TOML       EXPONENTL  TOML       QRPGLESRC  TOML       EXPONENTL

Tom

 110,135 pts.

 

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

 110,135 pts.