Hi Frank,

Thanks Scott. I appreciate the feedback. I wasn't aware of %PARMS() &
OPTION(*NOPASS) until you and Michael informed me.

I won't be using a local data area now. They can be a bigger pain than what
I had previously thought.


Just to be a little more complete, and a little more clear:

OPTIONS(*NOPASS) is part of prototype support added in V3R2 (1996) and this support is older than that.

%PARMS is part of RPG IV support in V3R1 (1994) and this support is older than that.

However, the technique itself is much older. It was available prior to either of the above enhancements. I used it in RPG/400... you had to use the PSDS to the the parameter count instead of %PARMS, which was slightly more work -- but otherwise, the technique was exactly the same. I suspect (but can't confirm) that this support has existed since RPG III was first made available for the S/38.

The technique involves simply checking to see how many parameters were passed (either via %PARMS or the PSDS). And then only using your optional parameters if they were passed.

Here's an example from the RPG/400 days:

IPSDS SDS
I 37 390PARMS
C*
C *ENTRY PLIST
C PARM PEFYR 2
C PARM PESDAT 6
C PARM PEEDAT 6
C PARM PEDBUG 1
C*
C PARMS IFGE 4
C MOVE PEDBUG DEBUG 1
C ELSE
C MOVE 'N' DEBUG
C END

The idea here was that I was testing a program that accepted 3 parameters (fiscal year, start date and end date). For the sake of my test, I wanted to add a 'debug' parameter. When this parameter is passed and set to 'Y', I was going to skip the updating of a certain file. When the parameter isn't passed, the program behaved exactly as before.

As you can see in the above code, I have a field named PARMS in my PSDS -- it will contain the number of parameters passed. If I have 4 (or more) parameters passed, that's when I want to use my debugging parameter. If it's not passed, however, I have to be careful NOT to try to use my PEDBUG parameter, otherwise I'll end up with problems.

Easy enough to do, as you can see... I have a non-parameter variable named DEBUG. If the 4th parameter is passed, I move it's value to DEBUG. If not, I default DEBUG to N.

When I want to do my update, I can do this:

C DEBUG IFEQ 'Y'
C UPDATREGIONF
C END

Obviously, my example about debugging is just that -- one example. There are many things you might use an optional parameter for -- debugging is just one of them.

At some point later (I don't remember the timing) they added a *PARMS keyword to RPG/400 so you don't have to hard-code the from/to positions in the PSDS. So you'd change the above code to the following:

IPSDS SDS
I *PARMS PARMS

Though, honestly, I never found much use for the *PARMS reserved word... Coding the from/to positions just isn't that hard :)

The above techniques (both the from/to position, and *PARMS) still work in RPG IV to this day.. just slightly different syntax (as with any DS in RPG IV):

D PSDS SDS
D PARMS *PARMS
C*
C *ENTRY PLIST
C PARM PEFYR 2
C PARM PESDAT 6
C PARM PEEDAT 6
C PARM PEDBUG 1
C*
C PARMS IFGE 4
C MOVE PEDBUG DEBUG 1
C ELSE
C MOVE 'N' DEBUG
C ENDIF

But the great thing about RPG IV is that it gives us %PARMS so we no longer really need to define a PSDS. We can just use %PARMS directly. This would be slightly modernized V3R1 syntax -- in my opinion, a TON easier to understand:

D peFiscYear s 2a
D peStrDate s 6a
D peEndDate s 6a
D peDebug s 1a
D Debug s like(peDebug)
D inz('N')

C *ENTRY PLIST
C PARM peFiscYear
C PARM peStrDate
C PARM peEndDate
C PARM peDebug

C if %parms >= 4
C eval Debug = peDebug
C endif

V3R2 brought us prototypes... so we no longer need to use *ENTRY PLIST. (Though, frankly, folks still did... prototypes for programs didn't get widespread use until free format came out and dropped support for *ENTRY PLIST and CALL/PARM... but the support was originally available in V3R2)

In a copy book, you'd have this:

D MYPGM PR ExtPgm('MYPGM')
D peFiscYear 2a const
D peStrDate 6a const
D peEndDate 6a const
D peDebug 1a const options(*nopass)


Then in the program, you'd do this:

/COPY THE_COPYBOOK
D MYPGM PI
D peFiscYear 2a const
D peStrDate 6a const
D peEndDate 6a const
D peDebug 1a const options(*nopass)

D Debug s like(peDebug)
D inz('N')

C if %parms >= 4
C eval Debug = peDebug
C endif

It's more self-documenting, because you can clearly see that the first three parameters are intended to be passed all of the time. The last parameter is intended to be optional, because it has options(*nopass). But, it's still doing the same thing... the PR/PI just replaces the *ENTRY PLIST.

If you call the program via the prototype, the prototype will enforce that the first 3 parms MUST be passed... but honestly, on the PI side of things, the *nopass doesn't really accomplish anything. You still have to check %PARMS. Plus, if the program is called without the prototype (for example, via CL's CALL command) it'll still accept the call, even if not all of the parameters are passed. So it's really identical to what you had with CALL/PARM, other than being a little more self-documenting.

And, of course, in modern RPG you'd use free format -- but that doesn't change things too much.

/COPY THE_COPYBOOK
D MYPGM PI
D peFiscYear 2a const
D peStrDate 6a const
D peEndDate 6a const
D peDebug 1a const options(*nopass)

D Debug s like(peDebug)
D inz('N')
/free
if %parms() >= 4;
Debug = peDebug;
endif

But... I guess my point is... even though you might refer to this as "options(*nopass) support" or "%PARMS support" the technique has been around forever. It's just evolved a little bit.


This thread ...

Replies:

Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].