Forums >> Programming >> RPG Programming >>
Adding a New Procedure to our Module or Service Program




Posted:
bvstone

Adding a New Procedure to our Module or Service Program

 
Adding a New Procedure to our Module or Service Program

Now comes the time when we will add a new procedure (function) to our module, and then service program.

I always start with the module source itself (instead of the prototype source).  This is because during the creation of the new procedure things may change and that could change the prototype definition.  Here's an example:

     H NOMAIN
      ****************************************************************
      * Prototypes                                                   *
      ****************************************************************
      /COPY QCOPYSRC,P.MATH
      *//////////////////////////////////////////////////////////////*
      * #math_getSumInt - Return the sum of two integers             *
      *//////////////////////////////////////////////////////////////*
     P #math_getSumInt...
     P                 B                   EXPORT
      *--------------------------------------------------------------*
     D #math_getSumInt...
     D                 PI            10i 0
     D  Augend                       10i 0 Const
     D  Addend                       10i 0 Const
      *--------------------------------------------------------------*
      /free

       return (Augend + Addend);

      /end-free
     P #math_getSumInt...
     P                 E
      *//////////////////////////////////////////////////////////////*
      * #math_getDiffInt - Return the difference of two integers     *
      *//////////////////////////////////////////////////////////////*
     P #math_getDiffInt...
     P                 B                   EXPORT
      *--------------------------------------------------------------*
     D #math_getDiffInt...
     D                 PI            10i 0
     D  Minuend                      10i 0 Const
     D  Subtrahend                   10i 0 Const
      *--------------------------------------------------------------*
      /free

       return (Minuend - Subtrahend);

      /end-free
     P #math_getDiffInt...
     P                 E                       

You'll see that in our updated module source we have added a new procedure named #math_getDiffInt which will return the difference of two numbers.

The next step will be updating our /COPY member (P.MATH) with the prototype of our new subprocedure.  I find it's easiest to copy the top portion of the procedure source and simply remove everything except the comments (if needed) and the Procedure Interface (PI) section, then changing the PI to PR.

      *//////////////////////////////////////////////////////////////*
      * #math_getSumInt - Return the sum of two integers             *
      *//////////////////////////////////////////////////////////////*
     D #math_getSumInt...
     D                 PR            10i 0
     D  Augend                       10i 0 Const
     D  Addend                       10i 0 Const
      *//////////////////////////////////////////////////////////////*
      * #math_getDiffInt - Return the difference of two integers     *
      *//////////////////////////////////////////////////////////////*
     D #math_getDiffInt...
     D                 PR            10i 0
     D  Minuend                      10i 0 Const
     D  Subtrahend                   10i 0 Const                

As you can see, the PI section of the module source and the PR section of the prototype are nearly identical.  By copying the PI section for our prototype, this helps cut down on possible keying errors.

Now that we have our new procedure we need to recreate the F.MATH module:

CRTRPGMOD MODULE(ILESAMPLE/F.MATH) SRCFILE(ILESAMPLE/QMODSRC)

Now that we have a new module you may be wondering, is that going to affect anything that is using the F.MATH module or service program?  At this point, the answer is no.  Right now we simply have an updated F.MATH module that includes the new procedure.  

If we wanted our programs to be able to use it, as before, we have two options.  To bind by copy (using the new module) or bind by reference (by updating the service program).

Any program that is using the bind by copy (module) option simply needs to be recompiled so it can grab a new copy of the F.MATH module.  Simple enough, right?  

But, any program that is using bind by reference (service program) needs a couple extra steps before the new procedure is available:  

  • Update our binder language to export the new procedure (Binder Language articles part 1 and part 2)
  • Recreate (or update) our F.MATH service program so that it is using the new version of the F.MATH module
  • Compile our program

When we update our binder language we want to make sure that when we do, we keep the old signature in tact so that any programs that use the updated F.MATH service program will continue to function.  Remember that when we create a program that uses a service program, that program makes note of the current signature of that service program.  

The other option (which we'll call the "brute force" method) would be to recreate the service program with only one signature (the new one that won't match any signature referenced by a program using the service program) and then recompiling every program that uses the service program to force it to get the latest signature.  (whew.. that was a mouthful!)  While this is an option, it isn't always the best, so lets focus on the method that will keep everything working.

Step One - Update The Binder Language

We want to update our binder language so that our newest version of our F.MATH service program will export our new procedure. 

             STRPGMEXP  SIGNATURE('v2.0')                          
             EXPORT     SYMBOL(#math_getSumInt)                    
             EXPORT     SYMBOL(#math_getDiffInt)                   
             ENDPGMEXP                                             
                                                                   
             STRPGMEXP  PGMLVL(*PRV) SIGNATURE('v1.0')             
             EXPORT     SYMBOL(#math_getSumInt)                    
             ENDPGMEXP                                             

The first thing we'll notice is that we have two export blocks now.  The old on (v1.0) also has been changed so that the program level (PGMLVL) keyword is *PRV which will tell the system that this signature is from a previous version of the service program.  The default for this keyword is *CURRENT.  Remember, the current signature is the one any program created will reference.  The previous signature(s) is/are there only for programs that haven't been recompiled since the update.

Step Two - Update the Service Program

When updating our service program we have two options:  delete the old one and create the new one using the Create Service Program (CRTSRVPGM) command or use the Update Service Program (UPDSRVPGM) command.

Following is the command to use for the UPDSRVPGM command:

UPDSRVPGM SRVPGM(ILESAMPLE/F.MATH) MODULE(ILESAMPLE/F.MATH) EXPORT(*SRCFILE) SRCFILE(ILESAMPLE/QSRVSRC) SRCMBR(*SRVPGM)

Once this is done the first thing we'll notice is the service program now has two signatures (but, only one *CURRENT signature)

                     Display Service Program Information 
                                                                Display 1 of 1
Service program  . . . . . . . . . . . . :   F.MATH     
  Library  . . . . . . . . . . . . . . . :     ILESAMPLE  
Owner  . . . . . . . . . . . . . . . . . :   BVSTONE    
Service program attribute  . . . . . . . :   RPGLE      
Detail . . . . . . . . . . . . . . . . . :   *SIGNATURE 

                                 Signatures: 

v2.0             
v1.0            
 

Step Three - Create a New Program

We had our test program MATHTEST before, but for the sake of understanding signatures I wanted to do things a little differently.  So, copy your MATHTEST source to a new program named MATHTEST2 and update it so it looks like the following:

H DFTACTGRP(*NO) BNDDIR('MYBNDDIR')                                                
 ****************************************************************                  
 * Prototypes                                                                      
 ****************************************************************                  
 /COPY QCOPYSRC,P.MATH                                                             
 ****************************************************************                  
D Sum             S             10i 0                                              
D Diff            S             10i 0                                              
 ****************************************************************                  
 /free                                                                             
                                                                                   
  Sum = #math_getSumInt(20:21);                                                    
  Diff = #math_getDiffInt(44:25);                                                  
                                                                                   
  *INLR = *ON;                                                                     
 /end-free                                                                         

Once done we can create our new program.

CRTBNDRPG PGM(ILESAMPLE/MATHTEST2) SRCFILE(ILESAMPLE/QRPGLESRC)

At this point we have the following:

  • A service program with 2 signatures (v1.0 and v2.0)
  • A program named MATHTEST that uses the F.MATH service program and referencing signature v1.0 (and still works without recompiling)
  • A program named MATHTEST2 that uses the F.MATH service program and references the current signature of v2.0

Next we will purposely cause a signature error just so that we are aware of what could happen if things are done wrong. 

 


Last edited 04/23/2015 at 09:28:49


Reply




Copyright 1983-2017 BVSTools
GreenBoard(v3) Powered by the eRPG SDK, MAILTOOL Plus!, GreenTools for Google Apps, jQuery, jQuery UI, BlockUI, CKEditor and running on the IBM i (AKA AS/400, iSeries, System i).