A whole data structure may be passed to any Char(*) parameter, which is how the
standard error-code (QUSEC) idiom is written. It works in both source formats - a free-format DCL-DS passed to a prototyped EXTPGM parameter, or a
fixed-format D-spec data structure named on a PARM line of a CALL:
dcl-ds qusec qualified;
bytesprv int(10) inz(256);
bytesavl int(10) inz(0);
excid char(7);
rsv char(1);
exdta char(240);
end-ds;
clrdtaq('TESTQ ' : 'OTHERLIB ' : ' ' : 0 : '' : qusec);
// qusec.excid now holds the message identifier, qusec.bytesavl its length
The parameter carries the structure's storage bytes, so a binary subfield arrives as the four bytes the caller stored rather than as its displayed digits. Passing the structure by reference (the default) writes the API's result back into its subfields, so both binary and character subfields read as the API left them. Set bytes provided non-zero to have failures returned in the structure; leave it zero and the failure escapes instead.
QMHSNDPM and SND-MSG reach the same queue, so a message subfile paints
messages sent either way. The call stack entry and counter parameters are
accepted and not acted on: they select which call-stack entry owns the message
elsewhere, but here every program has its own queue, so the only queue a program
can reach is its own.
This is what makes the display-correct-redisplay loop writable - send the
errors, WRITE the control format, let the operator correct them, remove the
messages, and repaint:
C EVAL RMVOPT = '*ALL'
C CALL 'QMHRMVPM'
C PARM STKE
C PARM STKCNT
C PARM BLNKKY
C PARM RMVOPT
C PARM ERRC0