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




I have a service program that is processing various types of data input and returning a formatted string. If the procedure being called encounters an error, I send back a return code to the caller. I am enhancing that to send a message to QHIST and the users job log.

When you send a message, the system automatically logs which program/module/procedure the message came from. (Do a dspjoblog, select any message, press F1 on that message, and press F9 to get the procedure details.)

So, if you send the message directly from the subprocedure in question, there's no need for you to calculate it's name. The system will put it in there for you.

However, since there are a lot of parms to the Send Program Message (QMHSNDPM) API, people often will stick it in a subprocedure or a separate CL program to simplify logic in the caller. In that situation, the "sender" that gets logged from the message will be the "message sender" routine rather than the one that called it. In that situation, it might be a good idea to find out the subprocedure name and store it in the message data.

One of the parms I am passing to my generic logging routine is the name of the procedure the error occured in. Currently, I am hard coding it, but would like to be able to have a variable that I can pass instead.

Your "generic message logging routine" sounds like what I'm describing above. So now you'll need a "generic find out my name" routine :) The way you do that is very similar to the way you log messages.

As I said above, the system logs the program/module/procedure name that sends a message. It also logs the same info for the receiver. So, to find out your name, you can send a program message to your subprocedure. Then, read that message back and see who received it.

To do that from a separate subprocedure (i.e. a "generic" routine) you'll need to tell it which callstack entry to send the message to so that you get the right subprocedure. You can do that by specifying a "count" from the original. 1=the caller, 2=the caller's caller, etc.

Here's some sample code that demonstrates this:

     H DFTACTGRP(*NO)

     D GetCaller       PR           256A
     D   StackCnt                    10I 0 value
     D   Program                     10A   options(*nopass:*omit)
     D   Module                      10A   options(*nopass:*omit)

     D testProc        PR
     D myProc          PR

     c                   callp     testProc
     c                   eval      *inlr = *on

     P testProc        B
     D testProc        PI
     c                   callp     myProc
     P                 e

     P MyProc          B
     D MyProc          PI

     D msg             s             52A
     D pgm             s             10A
     D proc            s            256A
     D module          s             10A

     C                   eval      msg = 'I am ' + getCaller(1)
     c     msg           dsply

     c                   eval      proc = getCaller(2:pgm:module)
     c                   eval      msg = 'Called from ' + %trim(proc)
     c                                         + ' in ' + %trim(module)
     c                                         + ' in ' + %trim(pgm)
     c                   dsply                   msg

     P                 e


      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
      * GetCaller():  Get the name of a procedure on the call stack
      *
      *     StackCnt = (input) Number of call stack entries to skip
      *                  when counting.
      *                    1 = Skip the getCaller() subprocedure
      *                    2 = Skip the procedure that called getCaller()
      *                    3 = Skip the procedure before the one that
      *                             called getCaller(), etc.
      *
      *     Program = (output/optional) name of program that received
      *                   the message
      *
      *      Module = (output/optional) name of module that received
      *                   the message
      *
      *  returns the name of the subprocedure
      *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     P GetCaller       B
     D GetCaller       PI           256A
     D   StackCnt                    10I 0 value
     D   Program                     10A   options(*nopass:*omit)
     D   Module                      10A   options(*nopass:*omit)

      *
      * Receive Program Message API
      *
     D QMHRCVPM        PR                  ExtPgm('QMHRCVPM')
     D   MsgInfo                  32767A   options(*varsize)
     D   MsgInfoLen                  10I 0 const
     D   Format                       8A   const
     D   StackEntry                  10A   const
     D   StackCount                  10I 0 const
     D   MsgType                     10A   const
     D   MsgKey                       4A   const
     D   WaitTime                    10I 0 const
     D   MsgAction                   10A   const
     D   ErrorCode                 8000A   options(*varsize)

      *
      * Send Program Message API
      *
     D QMHSNDPM        PR                  ExtPgm('QMHSNDPM')
     D   MessageID                    7A   const
     D   QualMsgF                    20A   const
     D   MsgData                  32767A   const options(*varsize)
     D   MsgDtaLen                   10I 0 const
     D   MsgType                     10A   const
     D   CallStkEnt                  10A   const
     D   CallStkCnt                  10I 0 const
     D   MessageKey                   4A
     D   ErrorCode                 8000A   options(*varsize)

     D RCVM0300        DS                  qualified
     D  Space                     32767A
     D  MsgDtaLen                    10I 0 overlay(Space:81)
     D  MsgLen                       10I 0 overlay(Space:89)
     D  MsgHlpLen                    10I 0 overlay(Space:97)
     D  VarStart                      1A   overlay(Space:112)

     D SndRcvInfo      DS                  qualified
     D                                     based(p_SndRcvInfo)
     D   Program                     10A   overlay(SndRcvInfo:355)
     D   Module                      10A   overlay(SndRcvInfo:365)
     D   Procedure                  256A   overlay(SndRcvInfo:375)

     D ErrorCode       ds                  qualified
     D   BytesProv                   10I 0 inz(0)
     D   BytesAvail                  10I 0 inz(0)

     D MsgKey          s              4A

      /free

          QMHSNDPM( ''
                  : ''
                  : 'TEST'
                  : %len('TEST')
                  : '*RQS'
                  : '*'
                  : StackCnt
                  : MsgKey
                  : ErrorCode  );

          QMHRCVPM( RCVM0300
                  : %size(RCVM0300)
                  : 'RCVM0300'
                  : '*'
                  : StackCnt
                  : '*RQS'
                  : MsgKey
                  : 0
                  : '*REMOVE'
                  : ErrorCode );

             p_SndRcvInfo = %addr(RCVM0300.VarStart)
                          + RCVM0300.MsgDtaLen
                          + RCVM0300.MsgLen
                          + RCVM0300.MsgHlpLen;

             if (%parms>=2 and %addr(Program)<>*NULL);
                 Program = SndRcvInfo.Program;
             endif;

             if (%parms>=3 and %addr(Module)<>*NULL);
                 Module = SndRcvInfo.Module;
             endif;

             return SndRcvInfo.Procedure;
      /end-free
     P                 E


As an Amazon Associate we earn from qualifying purchases.

This thread ...

Follow-Ups:
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.