On 12 Apr 2013 16:30, CRPence wrote:
<<SNIP>>
I do not recall, but I think the most common way utilized to more
conspicuously force the MCH3601 error before any processing, was to
have the first request for each parm### processing issue the request
CHGVAR &RTNVAR### &RTNVAR### just as Vern had noted in an earlier
reply. <<SNIP>>

I probably also should have noted that the technique described, of using the MONMSG MSGID(MCH3601) [with RCVMSG MSGTYPE(*EXCP)] to deal with the *NULL addressing for the parameter variable, is compatible all the way back to the S/38. So I went on a quest for something better [near the end of this message]. Along the way...

FWiW I searched to find if there was some apparent /convention/ for handling the condition. In some examples I had located, a CHGVAR from the return variable into a local variable was used to detect the condition early, and others used local variables to do all of the work earlier in the program and then only in the end of the program do they set the return values into parameter variables from the local variables where the monitor would be in effect. I also did see a couple doing the CHGVAR &V &V, but the more I looked at that request, the more I disliked it.

Here is an example using a global monitor to ignore the condition, but then cleaning up all of the messages upon a normal exit:
Subject; Tool - Retrieve Message Queue Attributes with Command: RTVMQGQA by API QMHRMQAT
http://archive.midrange.com/midrange-l/200712/msg01228.html

Here is a discussion thread on the same topic of RTNVAL(*YES), plus use of a CLLE for which the CL CALL does not get CPD0172 and thus for which there is a similar usage for the same MCH3601 monitor:
Subject: CL Parameter
http://archive.midrange.com/rpg400-l/200207/threads.html#00033

And a discussion thread on optional parameters for CLLE but also RTNVAL(*YES):
http://archive.midrange.com/midrange-l/200904/threads.html#00555

So I figured... There are almost certainly better ways, having since become available, to accomplish the same thing in a CLP or CLLE.? For example just as with RPG using its %ADDR to perform the test without having to deal with an exception, the CL eventually added a builtin with the same name [also as %ADDRESS]. So very likely the effectively identical technique used for a PARM in RPG can be used in a CLP.? Although probably not for this case [per being invoked by a command], there should be the parameter operational descriptor information as a possibility, to be obtained when using a CLLE; e.g. Test for Omitted Argument (CEETSTA) API.

So anyhow... I was wondering if perhaps the following can be used to avoid the MCH3601. Although the parameter variable is declared as automatic storage, there is a chance that trying to address the value using the %ADDR would yield a *NULL pointer result instead of the MCH3601. I seem to recall playing around with something like this sometime after the *PTR type became available, but I do not recall what was the effect:

Pgm Parm(&RtnVal001 &RtnVal002)
/* parameter declarations */
Dcl &RtnVal001 *char 10
Dcl &RtnVal002 *char 10
/* pseudo-constant null pointer variable; for a CLP */
Dcl &NullPtr *PTR STG(*AUTO) ADDRESS(*NULL)
/* In a CLP ; the docs say this is still required */
If cond(%addr(&RtnVal001) *eq &NullPtr) Then(*n)
Else Do
/* processing for RtnVal001 can occur here */
EndDo
/* In a CLLE ; the docs say the *NULL as spcval is OK */
If cond(%addr(&RtnVal001) *eq *NULL) Then(*n)
Else Do
/* processing for RtnVal001 can occur here */
EndDo

Reference for difference between CLP and CLLE noted above:
http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/topic/cl/if.htm
"...
Condition (COND)
...
To test if a pointer has a null value, the CL pointer variable can be compared to the special value *NULL if the CL source is being compiled with the Create CL Module (CRTCLMOD) or Create Bound CL Program (CRTBNDCL) command. If the CL source is being compiled with the Create CL Program (CRTCLPGM) command, compare the CL pointer variable to another CL pointer variable that was declared with ADDRESS(*NULL) and has not been changed.
..."

Then after some more searching the web... I found the following source at the following link with the apparent intended "Subject: Number of Parameters in CL program". There the author later claims the code "rocks as expected", which I infer means the code is functional :-) Whether using the CHGVAR is required first as shown, as contrasted with my code above which just uses the expression in the COND(), is not clear. But per use of the special value *NULL in the COND(), the following code would be valid only for a CLLE rather than a CLP; i.e. use the pseudo-constant null pointer variable to compare against, if using CLP. From this example, I am guessing that my above code probably would also be functional as written:
http://www.code400.com/forum/showthread.php/8263-Number-of-Parametesrs-in-CL-program

pgm parm(&Parm1 &Parm2)
dcl &ptrParm type(*ptr)
chgvar var(&ptrParm) value(%addr(&Parm1))
if cond(&ptrParm = *NULL ) then(do)
/* Parm1 not passed ? */
enddo
chgvar var(&ptrParm) value(%addr(&Parm2))
if cond(&ptrParm = *NULL ) then(do)
/* Parm2 not passed ? */
enddo


As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:

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

This mailing list archive is Copyright 1997-2024 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].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.