Search code examples
ibm-midrangerpglerpg

How to read Source files like normal PF/LF


I'm currently working on a programm that transfers physical files from productive environment to my test environment. To accomplish this I want to

  • read the first 50 lines of a given sourc code file,
  • extract the files being used and
  • copy them via CL programm with CPYF

A co-worker told me to use CL an OVRDBF the QRPGSRC, define the QRPGSRC in my F-Specs and use them like every other PF (READ/CHAIN on the member name). This looked a bit messy, so I searched for another solution: using keyworks in the F-Specs: https://www.google.de/search?q=ibm+rpg+EXTMBR

So I created 4 PF-SRC with CRTSRCPF in TSTLIB:

CRTLIB LIB(TSTLIB) TYPE(TEST)
CRTSRCPF FILE(TSTLIB/QCLSRC)
CRTSRCPF FILE(TSTLIB/QDDSSRC)
CRTSRCPF FILE(TSTLIB/QRPGLESRC)
CRTSRCPF FILE(TSTLIB/QRPGSRC)

and copied a existing sourc code file from my own libary MYLIB/QRPGSRC to TSTLIB/QRPGSRC. Then created a new ILE RPG programm in MYLIB/QRPGLESRC where I defined:

FQRPGSRC   IF   E           K DISK

When compiling I get 2 errors (#1 has severety 30, #2 is at 40: RNF2121 and RNF2109') telling me

  • "Record-format name in externally-described file already defined; record format ignored."

and

  • "All Record Formats for externally-described file ignored or dropped due to error; File ignored.".

As I am reading some tutorials: I can easily access them by using the name of the source code file als record name. But according to the error message there is only one record name and this is: QRPGSRC.

Adding keywords like:

FQRPGSRC   IF   E           K DISK    extfile('TSTLIB/TST001R')

didn't help very much. Now the errors remain but in the compile output some kind of header appears which shows me the "RPG-Name" and the "External name" of the file (QRPGSRC) and the record format:

*--------------------------------------------------------------------------------------------*
*                               RPG-Name         External Name                               *
* Filename   . . . . . . . . :  QRPGSRC          SYSLIB/QRPGSRC                              *
* Record format  . . . . . . :  (Not used)       QRPGSRC                                     *
*--------------------------------------------------------------------------------------------* 

Why TF is here SYSLIB when specified extfile('TSTLIB/TST001R')?? When RENAMEing QRPGSRC to QRPGSRCR there are no compiling errors anymore (except not using the defined file(s) ).

FQRPGSRC   IF   E           K DISK    extfile('TSTLIB/TST001R')
F                                     rename(QRPGSRC:QRPGSRCR) 

So my question: What do I have to do to be able to read a PF-SRC like a normal LF/PF so that I can READ/CHAIN on a line in a source code file located in a given PF-SRC?


Solution

  • You are almost there, but a few things.

    1. Source physical files are not keyed, so the K is incorrect, and if you chain, it would be with a relative record number. READ is your best bet for this type of file.
    2. Current free form RPG can have file declarations local to sub-procedures. So you will not always find file specifications in the first 50 lines of the file, and even if you are only reading RPGIII files, they have a 50 file limit which likely would take more than 50 lines if you include extension records, comments, and your H specs.
    3. RPGIV has no limit on the number of file specifications.

    Given that this probably isn't the best way to determine the file dependencies of a program. To answer your specific question:

    FQRPGSRC   IF   E             DISK    rename(QRPGSRC:QRPGSRCR)
    

    is likely your best bet in fixed format. But I like to promote more modern methods, so in free format it would look more like this:

    **free
    ctl-opt DftActGrp(*No) ActGrp(MyNamedAG)                            
            DatFmt(*ISO)                                           
            Option(*SrcStmt: *NoDebugIo: *NoUnref);                
    
    dcl-f qrpgsrc qualified;                                       
    
    dcl-ds src       LikeRec(qrpgsrc.qrpgsrc);                     
    
    dcl-s ix         Int(5) Inz(0);                                
    dcl-s FullyFree  Ind Inz(*OFF);                                
    
    dcl-c LC         'abcdefghijklmnopqrstuvwxyz';                 
    dcl-c UC         'ABCDEFGHIJKLMNOPQRSTUVWXYZ';                 
    
    for ix = 1 to 50;                                              
      read qrpgsrc.qrpgsrc src;                                    
      if %eof();                                                   
        leave;                                                     
      endif;                                                       
    
      // Is this a fully free form program?                        
      if ix = 1;                                                   
        FullyFree = (%xlate(UC: LC: %trim(src.srcdta)) = '**free');
      endif;                                                       
    
      // Do something here                                         
    endfor;
    return;                                      
    

    You are going to want to front this with a CLP or something to override the source file to the appropriate library, and choose a member to process. This could be in a loop as well to retrieve all the members, calling your program once per member.

    The best way to determine program dependencies is to use the DSPPGMREF command as indicated in a comment to the question.