|
Hello,
STDERR1: /* Standard error handling routine */ IF &ERRORSW SNDPGMMSG MSGID(CPF9999) + MSGF(QCPFMSG) MSGTYPE(*ESCAPE) /* Func chk */
[SNIP -- cut most of code for brevity]You don't appear to be using STDERR at all, you're just sending back an escape message. Confused the heck out of me at first. You see, in C, Java, Perl, shell scripts, QShell, CGI, rexec, etc, STDERR refers to a data stream where error messages are written. Until I saw your code, I didn't understand that you were just re-sending an escape message that had been sent to your CL program.
FWIW, I have a similar CL routine, but mine uses APIs. They work really well, and I think the code is actually a bit simpler than your example. Here's what I do:
ERROR: CALL PGM(QMHMOVPM) PARM( ' ' + '*DIAG' + x'00000001' + '*PGMBDY ' + x'00000001' + x'0000000800000000' ) CALL PGM(QMHRSNEM) PARM( ' ' + x'0000000800000000' )This part of the program is called by a MONMSG at the very top. The neat thing about it is that it doesn't care which message file the message came from, and it doesn't have to send back a particular message id. When it recieves an escape message, it uses QMHMOVPM to move all of the diagnostic messages back 1 call stack level before the start of the program (*PGMBDY = program boundary), then re-sends the escape message with the QMHRSNEM (resend escape message) API, and my caller gets the exact same escape and diagnostic messages that were sent to me! No loops or RCVMSG or temporary variables needed!
Converting this to RPG is quite easy because it's all API calls, and RPG can call them easily enough.
D QMHRSNEM PR ExtPgm('QMHRSNEM') D MsgKey 4A const D ErrorCode 8000A options(*varsize) D QMHMOVPM PR ExtPgm('QMHMOVPM') D MsgKey 4A const D MsgTypes 10A dim(4) options(*varsize) D const D NumMsgTypes 10I 0 const D ToStack 10A const D ToStackCnt 10I 0 const D ErrorCode 8000A options(*varsize) D ErrorNull DS qualified D BytesProv 10I 0 inz(0) D BytesAvail 10I 0 inz(0) . . monitor; // do something that might cause an error... on-error; QMHMOVPM(*BLANKS:'*DIAG':1:'*PGMBDY':1:ErrorNull); QMHRSNEM(*BLANKS:ErrorNull); endmon;Of course, I put the prototypes in a copybook so that I don't have to re-write them for every program.
One of the irritations of RPG is that it can't monitor for a particular message ID. For example, if I call QCMDEXC, I have to monitor for all errors that can occur, or for none of them. I can't monitor for just one CPF message like I can in CL. I use the preceding APIs as a workaround for this problem. When I receive an error message that wasn't expected, I simply re-send it.
For example, if I'm deleting a file in QTEMP, I might want to ignore the error that occurs when the file isn't found. After all, I'm deleting it, if it's not found, then I don't need to do anything more! But, I don't want to ignore EVERY error that can happen. For example, if I don't have authority to delete it, I'd rather have an *ESCAPE message rather than just ignoring it. So I'll code something like this:
D PSDS SDS qualified D MsgID 7A overlay(PSDS:40) D QCMDEXC PR extpgm('QCMDEXC') D command 32702A const options(*varsize) D length 15P 5 const D igc 3A const options(*nopass) D cmd s 200A varying . . monitor; cmd = 'DLTF FILE(QTEMP/TEMPFILE)'; QCMDEXC(cmd: %len(cmd)); on-error; if (PSDS.MsgID <> 'CPF2105'); QMHMOVPM(*BLANKS:'*DIAG':1:'*PGMBDY':1:ErrorNull); QMHRSNEM(*BLANKS:ErrorNull); endif; endmon; Make sense?
As an Amazon Associate we earn from qualifying purchases.
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.