theju112
theju112

Reputation: 91

Adding new entry parameter in an RPGLE program

I am modifying this highly critical RPGLE program where the changes involve adding a new entry parameter to it.

*entry        plist                                                              
              parm                    ecorp                          corp        
              parm                    edivi                          divi        
              parm                    eplvl                          parent lv   
              parm                    ewrsc                          wc rscd     
              parm                    eplnt                          plnt        
              parm                    eclvl                          child lv    
              parm                    emord                          ord         
              parm                    easst                          asst        
              parm                    emrwk                          mrwk#       
              parm                    eseqn                          seq #       
              parm                    easeq                          alt seq #   
              parm                    epprd                          alt seq #   
              parm                    eotst                          alt seq #   
              parm                    ewpqt                          alt seq #   
              parm                    ecmpc                          alt seq #   
              parm                    ewurs                          alt seq #   
              parm                    emurs                          alt seq #   
              parm                    epcdt                          alt seq #   
              parm                    E_Optn                         option          
              parm                    eeoj                           end of job      
              parm                    E_Pgm                          program         
              parm                    E_GRP                          MO GROUP        

The program entry parameter list is as above with the exception of the last parameter which I have added now. The program works fine. But what I am a bit concerned is if this would somehow impact other areas from where this program is called. i.e Caller Programs where the last entry parameter is not passed.

This new entry parameter is going to be passed from only one another program that is part of the change. There are quite a few other programs which are going to call the program passing the same parameter list as earlier.

If (%Addr(E_Grp) <> *NULL);            
  Chain (E_Grp:EWURS:ssmurs) MFMPP00;  
  If %Found();                         
    MchAllotted = *On;                 
    Leave;                             
  EndIf;                               
EndIf;                                 

The only other area in the code where this parameter is used is shown above. Here, I have ensured that before the parameter is referred, it is checked that the parameter has been passed.

I have tested and this works fine. However, considering the criticality of the application, still thought to seek expert help.

Any guidance/suggestions regarding this are welcome.

Upvotes: 1

Views: 2162

Answers (3)

Barbara Morris
Barbara Morris

Reputation: 3664

If the parameter isn't going to be modified within the program, then a safer way to use it would be to have a variable initialized to the default value, and if the parameter is passed, copy the parameter to that variable. That way, if more code is added that uses the parameter value, they won't have to remember to add the check.

... Change the name of E_GRP parameter to E_GRP_parm

dcl-s E_GRP ... INZ(whatever);

if %parms() >= %parmnum(E_GRP_parm);
   E_GRP = E_GRP_parm;
endif;

You can also use this technique with a parameter that is changed:

dcl-pi *n;
   something_parm char(10) OPTIONS(*NOPASS);
end-pi; 

dcl-s something char(10) INZ('Whatever');

// Get the value of the "someThing" parameter if it was passed
if %parms() >= %parmnum(something_parm);
   someThing = someThing_parm;
endif;
...
// Update the "someThing" parameter if it was passed
if %parms() >= %parmnum(someThing_parm);
   someThing_parm = someThing;
endif;

Upvotes: 2

Charles
Charles

Reputation: 23783

You have memory corruption bug waiting to happen...

If you've tried calling the program without the last parameter and it seems to have worked, you've just gotten lucky that the memory area had not been used...thus was zeros and your %Addr(E_Grp) <> *NULL worked as expected.

For a comparison %Addr(E_Grp) <> *NULL your calling programs have to pass the *OMIT special value for that parameter. Obviously that would require changing all the calling programs.

What you want is to not have to change the calling programs, thus what you need in the called program is for the parameter to be *NOPASS.

You should convert to called program to use a PR/PI instead of an *ENTRY PLIST. Then you can mark the last parameter as options(*NOPASS *OMIT)

Then in the called program, you can check

  1. if the parameter was passed
  2. if the passed parm was NULL (*OMIT)

Code

// check if the parm was passed
if %parms() > = %parmnum(E_GRP);
  // check if passed parm is not NULL
  if  %Addr(E_Grp) <> *NULL;
     //ok to use E_Grp
     Chain (E_Grp:EWURS:ssmurs) MFMPP00;  
     If %Found();                         
       MchAllotted = *On;                 
       Leave;                             
     endif;
  endif;
endif;

Upvotes: 6

Radinator
Radinator

Reputation: 1088

As far as I know RPG is considering the parameters from the caller as "Do what you want". Meaning if PGM01 is called by PGM02 where PGM1 accepts 3 parameters and PGM2 calls with 3 parameters everything is fine. When PGM01 wants 3 parameter and PGM02 gives 2 parameter, you can do that. But you have to take care of what happens if the third parameter is *NULL (as you do). If you call PGM01 with 4 parameters, whereas PGM01 only "wants" 3, there is no issue since PGM01 does not care about that.

But I would leave the *ENTRY style behind and instead use prototypes. There you can define that if a parameter is omittable, the parameter can be used but doesn't have to. Please read the manual for D-Spec and the PR keyword.

Upvotes: 2

Related Questions