In some cases, in an RPG program it may be necessary to run different logic depending on the function that called it. Usually we manage this behavior by passing an appropriate parameter to the program, but for programs that act very “in depth”, the call stack can be quite long and have multiple levels; in this case it is necessary to make sure that a parameter set by the first program is correctly propagated down to last program.
Another solution is to know if the current program has been called by another program, directly or in the call stack; in this way, depending on the caller, the appropriate logics can be performed.
And for this purpose, who comes to our aid if not the DB2 + SQL couple? In the ever-growing collection of DB2 services, in the “Application Services” section we find the STACK_INFO table function, which returns the job’s call stack.

Thanks to this function, with a simple query we can easily know if a specific program is part of the call stack:

SELECT COUNT(*)
FROM TABLE (QSYS2.STACK_INFO('*')) s
WHERE program_library_name NOT LIKE 'QSYS%'
  AND program_name = 'MYPGM'
; 

If the count returns a value greater than or equal to 1, we know that the current program has been called by MYPGM. With the COUNT scalar function we will always get a value, even if the program is not found in the stack. This query leaves off system libraries starting with QSYS.

The function has two parameters:

  • job_name: the job identifier. ‘*’ indicates the current job
  • thread_id: thread identifier (optional)

The job_name and thread_id parameters allow us to get the call stack also of jobs and processes other than the current one, which facilitates any checks on other active jobs.
Many information is returned by STACK_INFO, among the most useful we have the name of the calling procedure and the number of the specification in which the call occurred.

In case the check for caller should be performed into many programs, nothing better than encapsulating this logic in a service program procedure.
Below is the source of a service program procedure, which receives a parameter (the program to be searched for) and returns a Boolean flag indicating whether the program specified in the parameter is part of the call stack.
The complete source is available on GitHub at this link:
https://github.com/MD2706GIT/FAQ400

      //********************************************************************
      // isCalledFrom - Check if a given program is in call stack
      //
      // INPUT Parms:
      // - pPgm         - Program name            CHAR(10)
      //
      // OUTPUT Parms:
      // - Flag "1"=found "0"=not found           BOOLEAN
      //
      //********************************************************************
       dcl-proc  isCalledFrom   export;
          dcl-pi isCalledFrom   ind;
             dcl-parm pPgm   char(10)  const ;    // program name
          end-pi;

          dcl-s found        ind;

          monitor;
            found = *off;
            Exec SQL
            SET :found:indNull = (SELECT DISTINCT '1'
            FROM TABLE (QSYS2.STACK_INFO('*')) s
            WHERE program_library_name NOT LIKE 'QSYS%'
              AND program_name = :pPgm
            )
            ;
            if indNull = -1;
               found = *off;
            endif;

          on-error;
            found = *off;
          endmon;
          return found;

       end-proc;

Here a simple example of how to call the procedure:

       dcl-s found         ind ;                      
       . . .
       found    = isCalledFrom('FAQ40012B') ;       

DOCUMENTATION:
STACK_INFO :
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqudfstackinfo.htm

About author

Senior IBM i Analyst/Developer and technical writer. Former collaborator of the Italian edition of "System i News" magazine and author of several publications about tools and development practices for the IBM i platform.

Leave a Reply

%d bloggers like this: