× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



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 thread ...

Replies:

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.