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.
As an Amazon Associate we earn from qualifying purchases.