ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

program to retrieve call stack

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • program to retrieve call stack

    Code:
         **-- Program description:  ----------------------------------------------**---------------------
         **
         **   This program was intended to ease the process of retrieving the
         **   current job's call stack.  The information returned are the program
         **   names and program library names that are displayed by the DSPJOB or
         **   WRKJOB command's call stack panel.  Running the command DSPJOB
         **   OPTION( *PGMSTK ) will show the information referred to above.
         **
         **   
         **
         **
         **-- Parameters:
         **
         **    PxEntNbr    BOTH       The maximum number of call stack entries
         **                           to return in the output array.  A maximum
         **                           of 128 call stack entries can be returned.
         **
         **                           On return this parameter specifies the
         **                           actual number of call stack entries loaded
         **                           in the second parameter.
         **
         **    PxStkEnt    OUTPUT     The retrieved call stack entries are returned
         **                           in this parameter. Both the program name and
         **                           program library is returned for each call
         **                           stack entry as illustrated below:
         **
         **                           1           21          41
         **                           |  entry 1  |  entry 2  |  entry 3  | --
         **
         **                           1     11    21    31    41    51
         **                           | pgm | lib | pgm | lib | pgm | lib | --
         **
         **                           The call stack entries are returned in
         **                           descending call level order.
         **
         **                           This means that the name of the caller of
         **                           this program will be returned in the first
         **                           entry, and the name of the first program
         **                           that was called in this job is found in
         **                           the last entry returned.
         **
         **
         **-- Compilation specification:
         **
         **   CrtBndRpg   Pgm( <library>/callstack )
         **               SrcFile( <library>/QRPGLESRC )
         **
         **
         **-- Header specification:  ---------------------------------------------**
         H Option( *SrcStmt )
         **-- System information:  -----------------------------------------------**
         D PgmSts         SDs
         D  PsPgmNam         *Proc
         **-- Global variables:  -------------------------------------------------**
         D EntNbr          s             10i 0
         D Eix             s             10i 0
         **-- API error data structure:  -----------------------------------------**
         D ApiError        Ds
         D  AeBytPrv                     10i 0 Inz( %Size( ApiError ))
         D  AeBytAvl                     10i 0
         D  AeExcpId                      7a
         D                                1a
         D  AeExcpDta                   128a
         **-- Retrieve call stack API parameters:  -------------------------------**
         D CsRcvVar        Ds
         D  CsBytRtn                     10i 0
         D  CsBytAvl                     10i 0
         D  CsNbrStkE                    10i 0
         D  CsOfsStkE                    10i 0
         D  CsNbrEntRtn                  10i 0
         D  CsThrId                       8a
         D  CsInfSts                      1a
         D  CsCalStk                  32767a
         **
         D CsCalStkE       Ds                  Based( pCalStkE )
         D  CsStkEntLen                  10i 0
         D  CsOfsStmIds                  10i 0
         D  CsNbrStmIds                  10i 0
         D  CsOfsPrcNam                  10i 0
         D  CsLenPrcNam                  10i 0
         D  CsRqsLvl                     10i 0
         D  CsPgmNam                     10a
         D  CsPgmLib                     10a
         D  CsMiInst                     10i 0
         D  CsModNam                     10a
         D  CsModLib                     10a
         D  CsCtlBdy                      1a
         D  CsRsv                         3a
         D  CsActGrpNbr                  10u 0
         D  CsActGrpNam                  10a
         D  CsAddInf                   4096a
         **
         D  CsStmIds                     10a   Dim( 256 )
         D  CsPrcNam                    512a
         **
         D CsJobId         Ds
         D  JiJobNam                     10a   Inz( '*' )
         D  JiUsrNam                     10a
         D  JiJobNbr                      6a
         D  JiIntId                      16a
         D  JiRsv                         2a   Inz( *Allx'00' )
         D  JiThrInd                     10i 0 Inz( 1 )
         D  JiThrId                       8a   Inz( *Allx'00' )
         **
         D RtvCalStk       Pr                  ExtPgm( 'QWVRCSTK' )
         D  RcRcvVar                  32767a
         D  RcRcvVarLen                  10i 0 Const
         D  RcRcvInfFmt                   8a   Const
         D  RcJobId                      56a   Const
         D  RcJobIdFmt                    8a   Const
         D  RcError                   32767a          Options( *VarSize )
         **-- Parameters:  -------------------------------------------------------**
         D PxEntNbr        s              5p 0 inz(10)
         D PxStkEnt        s             20a   Dim( 128 )
         **
         **
         **-- Mainline:  ---------------------------------------------------------**
         **
          /free
                    if  PxEntNbr  > *Zero;
    
                     RtvCalStk( CsRcvVar
                                : %Size( CsRcvVar )
                                : 'CSTK0100'
                                : CsJobId
                                : 'JIDF0100'
                                : ApiError
                                          );
    
                     if  AeBytAvl = *Zero;
                      pCalStkE = %Addr( CsRcvVar ) + CsOfsStkE;
    
                      for EntNbr = 1  to CsNbrEntRtn;
    
                       if CsPgmNam  <> PsPgmNam;
                        Eix +=1;
                        PxStkEnt(Eix) = CsPgmNam + CsPgmLib;
                       endif;
    
                       if  EntNbr = PxEntNbr or
                           EntNbr = CsNbrEntRtn  or
                           EntNbr = %Elem( PxStkEnt );
                        leave;
                       endif;
    
                       pCalStkE += CsStkEntLen;
                      endfor;
    
                     endif;
                    endif;
    
                    PxEntNbr = Eix;
    
                    *InLr =  *On;
                    Return;
          /end-free
         **
    All my answers were extracted from the "Big Dummy's Guide to the As400"
    and I take no responsibility for any of them.

    www.code400.com

  • #2
    Re: program to retrieve call stack

    i'm so proud of you...there's no "B" data types!!!
    I'm not anti-social, I just don't like people -Tommy Holden

    Comment


    • #3
      Re: program to retrieve call stack

      Originally posted by tomholden View Post
      i'm so proud of you...there's no "B" data types!!!
      And nice use of pointer based data structures! SWEET!
      Michael Catalani
      IS Director, eCommerce & Web Development
      Acceptance Insurance Corporation
      www.AcceptanceInsurance.com
      www.ProvatoSys.com

      Comment


      • #4
        Re: program to retrieve call stack

        Good job!

        Yet there's another way to retrieve the call stack of the current thread or the initial thread of another job, by MI instruction MATINVS (Materialize Invocation Stack). Here's an example, t101.rpgle.
        Code:
             /**
              * @file t101.rpgle
              *
              * Test of _MATINVS2.
              * Meterialize the call stack of the current thread.
              */
             h dftactgrp(*no)
        
              /copy mih52
             d dsp_proc_name   pr
             d     susptr                      *
             d len             s             10i 0
             d ptr             s               *
             d pos             s               *
             d tmpl            ds                  likeds(matinvs_tmpl_t)
             d                                     based(ptr)
             d inve            ds                  likeds(invocation_entry_t)
             d                                     based(pos)
             d i               s             10i 0
        
              /free
                   ptr = %alloc(min_matinvs_tmpl_length);
                   tmpl.bytes_in = min_matinvs_tmpl_length;
                   matinvs2(tmpl);
        
                   len = tmpl.bytes_out;
                   ptr = %realloc(ptr : len);
                   tmpl.bytes_in = len;
                   matinvs2(tmpl);
        
                   // check each call stack entry
                   pos = ptr + min_matinvs_tmpl_length;
                   for i = 1 to tmpl.entries;
                       dsply 'invocation entry: ' '' inve.inv_num;
                       dsp_proc_name(inve.suspend_ptr);
        
                       pos += invocation_entry_length;
                   endfor;
        
                   dealloc ptr;
                   *inlr = *on;
              /end-free
        
             p dsp_proc_name   b
        
             d dsp_proc_name   pi
             d     susptr                      *
        
             d tmpl            ds                  likeds(matptrif_tmpl_t)
             d                                     based(ptr)
             d ptr             s               *
             d ptrd            ds                  likeds(matptrif_susptr_desc_t)
             d                                     based(pos)
             d pos             s               *
             d mask            s              4a
             d proc_name       s             30a
        
              /free
        
                   ptr = %alloc(matptrif_susptr_tmpl_length);
                   propb( ptr : x'00'
                        : matptrif_susptr_tmpl_length);
                   tmpl.bytes_in = matptrif_susptr_tmpl_length;
        
                   // init pointer description
                   pos = ptr + matptrif_ptrd_offset;
                   ptrd.proc_name_length_in = 30;
                   ptrd.proc_name_ptr = %addr(proc_name);
        
                   // materialize pointer desc
                   mask = x'12200000';
                     // bit 3 = 1; program name
                     // bit 6 = 1; module name
                     // bit 10 = 1; procedure name
                   matptrif( tmpl : susptr : mask );
        
                   // output pgm name, module name, and procedure name
                   dsply '    Program name' '' ptrd.pgm_name;
                   dsply '    Module name' '' ptrd.mod_name;
        
                   if ptrd.proc_name_length_out > ptrd.proc_name_length_in;
                       %subst(proc_name : 29 : 2) = ' <';
                   endif;
                   dsply '    Prodecure name' '' proc_name;
        
              /end-free
             p dsp_proc_name   e
        Prototype of MATINVS' system built-in _MATINVS2 and related instruction template structures can be found in mih52.rpgleinc.

        HTH!
        Last edited by junleili-cn; August 10, 2010, 04:26 PM.
        Regards!
        Junlei Li

        Comment


        • #5
          Re: program to retrieve call stack

          Thanks Tom/Michael.... It came from an original scott K. program I just /free'd it and removed some stuff. so i cant take credit for any of it
          Junlei - Thanks for posting....nice job

          Jamie
          All my answers were extracted from the "Big Dummy's Guide to the As400"
          and I take no responsibility for any of them.

          www.code400.com

          Comment


          • #6
            Re: program to retrieve call stack

            This seems interesting... how do you get the call stack of another job as the code seems to retrieve only the stack from the current one. Also, is it possible to get all the details like the statement number of the program, activation group, etc...? Thanks.

            Originally posted by junleili-cn View Post
            Good job!

            Yet there's another way to retrieve the call stack of the current thread or the initial thread of another job, by MI instruction MATINVS (Materialize Invocation Stack). Here's an example, t101.rpgle.
            Code:
                 /**
                  * @file t101.rpgle
                  *
                  * Test of _MATINVS2.
                  * Meterialize the call stack of the current thread.
                  */
                 h dftactgrp(*no)
            
                  /copy mih52
                 d dsp_proc_name   pr
                 d     susptr                      *
                 d len             s             10i 0
                 d ptr             s               *
                 d pos             s               *
                 d tmpl            ds                  likeds(matinvs_tmpl_t)
                 d                                     based(ptr)
                 d inve            ds                  likeds(invocation_entry_t)
                 d                                     based(pos)
                 d i               s             10i 0
            
                  /free
                       ptr = %alloc(min_matinvs_tmpl_length);
                       tmpl.bytes_in = min_matinvs_tmpl_length;
                       matinvs2(tmpl);
            
                       len = tmpl.bytes_out;
                       ptr = %realloc(ptr : len);
                       tmpl.bytes_in = len;
                       matinvs2(tmpl);
            
                       // check each call stack entry
                       pos = ptr + min_matinvs_tmpl_length;
                       for i = 1 to tmpl.entries;
                           dsply 'invocation entry: ' '' inve.inv_num;
                           dsp_proc_name(inve.suspend_ptr);
            
                           pos += invocation_entry_length;
                       endfor;
            
                       dealloc ptr;
                       *inlr = *on;
                  /end-free
            
                 p dsp_proc_name   b
            
                 d dsp_proc_name   pi
                 d     susptr                      *
            
                 d tmpl            ds                  likeds(matptrif_tmpl_t)
                 d                                     based(ptr)
                 d ptr             s               *
                 d ptrd            ds                  likeds(matptrif_susptr_desc_t)
                 d                                     based(pos)
                 d pos             s               *
                 d mask            s              4a
                 d proc_name       s             30a
            
                  /free
            
                       ptr = %alloc(matptrif_susptr_tmpl_length);
                       propb( ptr : x'00'
                            : matptrif_susptr_tmpl_length);
                       tmpl.bytes_in = matptrif_susptr_tmpl_length;
            
                       // init pointer description
                       pos = ptr + matptrif_ptrd_offset;
                       ptrd.proc_name_length_in = 30;
                       ptrd.proc_name_ptr = %addr(proc_name);
            
                       // materialize pointer desc
                       mask = x'12200000';
                         // bit 3 = 1; program name
                         // bit 6 = 1; module name
                         // bit 10 = 1; procedure name
                       matptrif( tmpl : susptr : mask );
            
                       // output pgm name, module name, and procedure name
                       dsply '    Program name' '' ptrd.pgm_name;
                       dsply '    Module name' '' ptrd.mod_name;
            
                       if ptrd.proc_name_length_out > ptrd.proc_name_length_in;
                           %subst(proc_name : 29 : 2) = ' <';
                       endif;
                       dsply '    Prodecure name' '' proc_name;
            
                  /end-free
                 p dsp_proc_name   e
            Prototype of MATINVS' system built-in _MATINVS2 and related instruction template structures can be found in mih52.rpgleinc.

            HTH!

            Comment

            Working...
            X