External Call Procedure

Since function keys and program options have been externalized, the next logical step is externalizing subprogram calls.

**FREE
       ctl-Opt DEBUG(*YES) OPTION(*SRCSTMT : *NODEBUGIO)
          DFTACTGRP(*NO) ACTGRP('QILE') Main(SC0321RP) ;

       Dcl-DS OBJECT    extname('SCOBJSPF') based(DtaPtr)  end-DS;

       Dcl-PR  MaintPgm         extpgm(SUBPGM) ;
          *n            char(10);
          *n            char(10);
          *n            char(1) ;
          *n            char(7) ;
       End-PR ;

       Dcl-PR  WorkSource            extpgm(SUBPGM) ;
          *n            char(10);
          *n            char(10);
       End-PR ;

       Dcl-PR  WorkObject            extpgm(SUBPGM) ;
          *n            char(10);
          *n            char(10);
       End-PR ;

       Dcl-PR NoParms                extpgm(SUBPGM)  end-PR ;

     //*----------- Define Global Variables 

       Dcl-S dtaPtr    pointer               ;
       Dcl-S parm01    char(10)              ;
       Dcl-S parm02    char(10)              ;
       Dcl-S errID     char(7)               ;
       Dcl-S Action    char(1)               ;
       Dcl-S SubPgm    char(10)              ;
       Dcl-S PLName    char(10)              ;

     //*------------ End of work fields 

       Dcl-Proc SC0321RP ;
         Dcl-PI SC0321RP             extPgm('SC0321RP') ;
           PgmNam         char(10)      ; // program to call
           LstNam         char(10)      ; // parameter list to use
           ModeIn         char(1)       ; // Mode (add, change, update, etc.)
           dataIn         pointer       ; // Data to use for call
           sizeIn         int(10)       ; // size of data string
           rtnID          char(7)       ; // Message ID (returned)
         END-PI;

            subPgm = PgmNam ;
            Action = ModeIn ;
            PLName = LstNam ;
            dtaPtr = dataIn ;
            CallProgram()  ;
            rtnID = ErrID  ;

            Return         ;
       End-Proc ;
        //*====================================
        Dcl-Proc callProgram;
         Dcl-PI callProgram              end-PI;

           setParameters();

           MONITOR;

              SELECT;
                 WHEN PLName = 'WORKSOURCE';
                    WorkSource( exombr : exobsr );

                 WHEN PLName = 'WORKOBJECT';
                    WorkObject( exobnm : exobtp );

                 WHEN PLName = 'PLIST1';
                    maintPGM( parm01 : parm02 : action : ErrID );

                 OTHER;
                    NoParms();
              ENDSL;
           ON-ERROR;
              errID = 'MIS0012';
           ENDMON;

          Return ;

        END-Proc callProgram ;

        //*======================================
        Dcl-Proc setParameters;
         Dcl-PI setParameters              end-PI;
           errID = *blanks;
           IF Action = 'A';
              parm01 = *blanks;
              parm02 = *blanks;
           Else ;
              parm01 = exobnm ;
              parm02 = exobtp ;
           ENDIF;
          Return ;
        END-Proc setParameters ;

This PROGRAM performs the same function as the @CALLS subroutine. Ideally, it would be made a service program. The exported procedure would function as a generic call operation for a group of related programs or a group of tables sharing a common key structure.

SoftCode Applications Continued

Complex Macro Instructions

The macro instruction field of the soft coded program options and function keys is 45 bytes long. This instruction may contain several different types of operations. And in SoftCode, the macro instruction may take several different formats. An ampersand '&' in byte 1 identifies a CL command. The Soft coded function editor will pass this command on to the generic command executive program to be processed. But a more complex form of the macro can be used. (See the previous page for an external defintion of the complex macro subfields.)

    000000000111111111122222222223333333334444444
    123456789012345678901234567890123456789012345
    <---><--------><--------><----------------->
    CALL SC0195RP  PLIST2    *RESERVED          A
    |    |         |                            |
    |    |         |                            |___Action Code
    |    |         |                           
    |    |         |                   
    |    |         |         
    |    |         |________________________________PARM list
    |    |__________________________________________Program name
    |_______________________________________________Operation code

    1-05 operation code
    6-15 program
   16-25 program data structure name
   26-44 RESERVED
   45-45 Action code:   A = Add
                        C = Change
                        D = Delete
                        V = View (display only)
				S = Sort

Fig. G31

The following D specs contain several externally defined data structures commonly associated with the SOFTCODE development process. This subroutine is an example of using the format of the complex macro instruction to format dynamic calls based on the information provided in the macro instruction. The call becomes dynamic--the parameter list to use is populated with program variables. The prototype (see example) references a variable name instead of a literal. This means programs named on the function table or option table can be replaced with newer versions without changing the calling program. (As long as the signature hasn't changed.)

     D FunctionKey   E DS                  EXTNAME(SCKEYSPF) qualified          Function keys
     D PGMDS         ESDS                  EXTNAME(SCPSTSPF)                    Pgm status map
     D DSPDS         E DS                  EXTNAME(SCDSPFPF)                    Display INFDS
     D MACDS         E DS                  EXTNAME(SCFUNCPF) INZ                Key map
     D OPTDS         E DS                  EXTNAME(SCOPTNPF) INZ                Option map
     D FUNCT         E DS                  EXTNAME(SCMACRPF) INZ                Macro map
.
.
.
     D WithParms       PR                  extpgm(SUBPGM)   [1]
     D  p$user                       10

     D WithParms2      PR                  extpgm(SUBPGM)   [2]
     D  p$user                       10
     D  p$mode                        1

     D NoParms         PR                  extpgm(SUBPGM)   [3]
.
.
.
        BEGSR @CALLS;                                                                               
           EXSR @SETPM;                                                                             
           MONITOR;                                                                                 
           SELECT;                                                                                  
              WHEN CALLPM = 'PLIST1';                                                               
                 CALLP WithParms(p$USER);                                                           
              WHEN CALLPM = 'PLIST2';  [4]                                                             
                 CALLP WithParms2(p$USER:p$mode);                                                   
              OTHER;                                                                                
                 CALLP NoParms();                                                                   
           ENDSL;                                                                                   
           ON-ERROR;                                                                                
              P$ERR = 'MIS0012';                                                                    
           ENDMON;                                                                                  
           EXSR @RETPM;                                                                             
        ENDSR;
.
.
.
Fig. R31                

The next page illustrates the function key database entries for a program named SC0320RP.

Dynamic Calls

Making use of the complex macro format can make program changes a matter of updating a record. The Procedure prototypes ([1], [2], and [3] in Fig. R31) are coded using a variable SUBPGM, instead of referencing an object name specified by a the use of a literal.


Call Example

Refer the sample code (Fig. R31) The @CALLS subroutine reacts to the complex macro instruction. The program to call, in this case SC0195RP (Fig. G31), requires two variables. Based on the PLIST2 entry, [4], the program will be called with the correct number of parameters. Other function entries for the calling program may only require one parameter, or perhaps no parameters. The subroutine will make call the specific call using the argument indicated on the macro instruction.

Since the name of the program is a variable, any program that shares a common argument with one of the defined protorypes can may be inserted, deleted, or updated by maintaining the the function or option table. For example if a new program named SC0197RP replaced SC0195RP, the only change necessary to call the new object would be to update the record on the function key database (SCFUNCPF). Adding a new subprogram to the functions of this program takes, literally, seconds. Since programs can be added without re-compiling rpg code or the DDS, this eliminates the need for regression testing of the calling program.