简体   繁体   中英

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 RENAME ing 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?

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.

If your system is anything like most I've seen, there are hundreds of files created via query, sql, save files, workfiles, etc., that you may, or may not need. This method allows you to pull all files on the system, and manipulate/analyze at will.

I would perform a DSPOBJD (prompt with F4) and provide the following parameters: DSPOBJD OBJ(*LIBL [or specific library]/*ALL) OBJTYPE(*FILE) DETAIL(*SERVICE) OUTPUT(*OUTFILE) OUTFILE(YOURLIB/LASTUSED).

This creates a file in your library that you can manipulate... run an SQL to delete all with Days Used Count (ODUCNT) = 0 [or your choice], and anything with Object Attribute <> 'PF'. This leaves just physical files.

Then you can choose objects used within the last x-days, but you must convert the date last used date (ODUDAT) to YYMMDD format first... update nwilson/lastused set ODUDAT = SUBSTR(ODUDAT,5,2) concat substr(ODUDAT,1,4) WHERE ODUDAT <> ' '.

This will allow you to compare *DAYS, etc. and build dynamic statements to copy to your dev library.

For automated process you have to do dsppgmref and prtsqlinf.

Generally production database structure changes slowly a few changes each year so I concentrate on obfuscation of production data into test. IE change the personally identifiable info like phone#s while I'm copying it.

    set HOMEPHONE = '555-555-' 
    || cast( cast( rand(49782) * 10000  as integer) || '0000' as char(4))
WHERE homephone <> ' ';      

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM