rpglecopybook

difference between RPG copybook and program


Could you give me some idea as to looking at file how can I differentiate between RPG copybook and program?

For example, in c, if you have main in the file, you know that it can be used as program.

Thanks in advance.


Solution

  • That's an interesting question...it is usually pretty obvious.

    I suppose the quick answer is that copy books won't contain different types of specifications. An RPG IV program can have H, F, D, I, C, O, and P specifications , or their free-form equivalents. (The specification type is determined by the letter in column 6 of fixed format source). The order is important and you can't intermix the types. If you're looking at source that has only one type of specifications, it's probably designed as a copybook. Since the executable code is contained in C (Calculation) and/or P (Procedure) specs, a source without any C or P specs is a copybook. While it's usually bad practice to have C or P Specs in a copybook, RPG does allow it and I've seen it done. But again, the only thing in the copy book would be C or P specs.

    EDIT You could have a copybook with for instance F & D specs, but the only place it could be included is at the end of a program's F specs prior to any D specs. You could have a copybook that makes use of compiler directives /IF DEFINED to control what part of the copybook is included where.

    EDIT2 Turns out IBM added the ability to intermix F & D specs in version 7.1 and higher. A source member with just F & D specs would be a copybook So the short answer becomes, a source member with both definition (H, F, D, I, O) specs and executable (C & P) specs is designed to be compiled.

    The longer answer, an RPG program also has a "main". Originally, the only option was what's known now as "cycle-main". IE. the "main" procedure is the implicitly generated "cycle" code that is built into RPG programs.

    Then along came RPG IV and ILE. IBM added a control specification keyword, NOMAIN.

    H NOMAIN
      //or in freeform
      ctl-opt nomain;
    

    This resulted in a non-executable module without a "main" procedure; the code normally generated by the compiler for the "cycle" is left out. The resulting *MODULE object would need to be bound into a *PGM object with another *MODULE that provide a main procedure.

    Or it could be bound with zero or more other *MODULE objects into a *SRVPGM object; *SRVPGM are just collections of procedures. Think of them like Windows DLLs.

    Then IBM added the option of having a "linear-main" RPG IV program.

    H MAIN(MYMAIN)
      // or freeform
      ctl-opt main(MYMAIN);
    

    Thus the main procedure is whichever procedure you designate. The generated "cycle" code is again left out of the executable.

    So the existence of either the NOMAIN or MAIN keywords would indicate that a source member is designed to be compiled; assuming there's more too the source. It's possible there's a "standard options" include file that would include one of those.

    The lack of those two keywords would indicate you're dealing with either a cycle main or an include file.

    If it's a cycle main program and it takes parameters as input, you'll be able to see the entry parameter list

      //Fixed format, old school RPG III, IV
    C     *ENTRY        PLIST                                       
    C                   PARM                    LCMPNO            2 
    C                   PARM                    LNTACT            1
    
     // fixed format, RPG IV using a "Procedure Interface (PI) to replace *ENTRY PLIST
    D CheckDate       PI               
    D  lDateIs                       4a
    
      // free format RPG IV
    dcl-pi CheckDate;
      lDateIs   char(4);
    end-pi;
    

    Note that a key difference in the source between a "cycle-main" program that uses the PI instead of *ENTRY PLIST and a linear main is that a linear main procedure is surrounded by an explicit procedure definition.

      // linear main
    h main(CHECKDATE)
    p CheckDate       b
    d CheckDate       PI               
    d  lDateIs                       4a
      //do something
      *INLR = *ON
      return;
    p CheckDate       e
    
       //cycle main with PI
    d  lDateIs                       4a
      //do something
      *INLR = *ON
      return;