Hi,

Today a programmer has to use %parms() to check whether a parameter with OPTIONS(*NOPASS) has been passed to a procedure or not. If also *OMIT is present he also needs to call CEETSTA to make sure the parameter has not been omitted. The disadvantage of %parms() is that the programmer has to hard code the position of the parameter in the procedure interface. The disadvantage of CEETSTA is that it returns the result in a parameter and hence cannot be used in an expression.

In addition all a programmer usually wants to know is whether a parameter is present (= can be accessed) or not. He usually does not need to know if a parameter is absence because it has not been passed or because it has been omitted. Today it is quite uncomfortable to combine %parms() and CEETSTA.

The idea is to introduce the following new BIFs to RPG to ease a programmer’s live:

%passed(parameterName)

%passed returns TRUE if a parameter has been passed to a procedure or not. It returns FALSE if a parameter has not been passed to the procedure. The argument of %passed is the name of the parameter as specified in the procedure interface. The following code is equivalent to %passed:

isPassed = (%parms() >= positionOfParameter)

%omitted(parameterName)

%omitted returns TRUE if a parameter has been omitted. It returns FALSE if the parameter has not been omitted. %omitted works the same as CEETSTA but is more robust, easier to read and can be used in an expression. The following code is equivalent to %omitted:

CEETSTA(isPresent: position: *);
isOmitted = (isPresent = 0);

%present(parameterName)

%present returns TRUE if a parameter values has been passed to a procedure and can be accessed inside the procedure. It returns FALSE if the parameter has not been passed or has been omitted. The following code is equivalent to %present:

isPresent = (%passed(parameterPosition) and not %omitted(parameterPosition))

Code Comparison

The following example shows how to check whether a *NOPASS parameter has been passed or not.

Procedure interface:

*
D newApiErrCode...
D PI likeds(errCode_t )
D i_monMsg N const options(*nopass)
*

Old style:

// Process optional parameter values ...
// ... monitor messages
if (%parms() >= 1);
monMsg = i_monMsg;
else;
monMsg = cFalse;
endif;

A bit better with a constant:

*
* Parameter positions
D p_monMsg C const(1)
if (%parms() >= p_monMsg);
monMsg = i_monMsg;
else;
monMsg = cFalse;
endif;

New style with %present():

if (%present(i_monMsg));
monMsg = i_monMsg;
else;
monMsg = cFalse;
endif;

The following example shows how to check whether a *NOPASS and *OMIT parameter is present or not.

Procedure interface:

*
D newMsg...
D PI likeds(msg_t )
D i_ID const like(msg_t.id )
D options(*omit: *nopass)
D i_data 512A const varying
D options(*omit: *nopass)
D i_type const like(msg_t.type )
D options(*omit: *nopass)
D i_file const like(msg_t.file )
D options(*omit: *nopass)
D i_lib const like(msg_t.lib )
D options(*omit: *nopass)
*

Old style:

// Process optional parameter values ...
// ... ID
if (%parms() >= p_ID);
CEETSTA(isPresent: p_ID: *omit);
else;
isPresent = 0;
endif;
if (isPresent = 1);
ID = i_ID;
else;
ID = 'CPF9897';
endif;

New style:

if (%present(i_ID));
ID = i_ID;
else;
ID = 'CPF9897';
endif;

The following example shows how to check whether a *NOPASS and *OMIT output parameter is present or not.

Procedure interface:

*
D rtvMsgText...
D PI 4096A varying
D i_msg const likeds(msg_t )
D o_msg likeds(msg_t )
D options(*nopass: *omit)
*

Info: 'msg' is initialized with cMSG_ID_OK (actually *BLANKS). In case of errors it contains the message ID as well as other message information. 'o_msg' is used the same way as the error code parameter of several IBM APIs. If it has been passed, the procedure returns the error message. If it has been omitted, the error message is ignored. If it has not been passed, an escape message is sent.

Old style:

// Process optional/omittable message parameter
if (%parms() >= p_msg);
CEETSTA(isPresent: p_msg: *omit);
if (isPresent = 1);
o_msg = msg;
endif;
else;
if (msg.ID > cMSG_ID_OK);
msg.type = cMSG_ESCAPE;
sndPgmMsg(msg: cMSG_PRV);
endif;
endif;
return msgText;

New style 1 (preferred style):

// Process optional/omittable message parameter
if (%present(o_msg));
o_msg = msg;
else;
if (not %omitted(o_msg) and msg.ID > cMSG_ID_OK);
msg.type = cMSG_ESCAPE;
sndPgmMsg(msg: cMSG_PRV);
endif;
endif;
return msgText;

New style 2 (without %omitted):

// Process optional/omittable message parameter
if (%passed(o_msg)); // passed but probably omitted
if (%present(o_msg)); // present! Hence not omitted
o_msg = msg;
endif
else;
if (msg.ID > cMSG_ID_OK);
msg.type = cMSG_ESCAPE;
sndPgmMsg(msg: cMSG_PRV);
endif;
endif;
return msgText;

Comments

As you can see, a programmer most likely will use %present to check whether a specific value is available or not. One of the two remaining BIFs %passed and %omitted may not really be necessary, because it can be replaced by a combination of the remaining two BIFs (see: last two samples).

Nevertheless I would like to see all three of them in order to let the programmer decide which one fits best in a particular situation.

Please let me know what you are thinking about it. Any comments are greatly appreciated.

Regards,

Thomas Raddatz