midrange.com code scratchpad
Name:
Dennis Lovelady
Scriptlanguage:
Plain Text
Tabwidth:
4
Date:
04/29/2010 01:43:54 pm
IP:
Logged
Description:
Return call stack
Code:
  1.        /////////////////////////////////////////////////////////////////////
  2.        // Copyright (c) 2010 Dennis E. Lovelady
  3.        // All rights reseved.
  4.        //
  5.        // Redistribution and use in source and binary forms, with or without
  6.        // modification, are permitted provided that the following conditions
  7.        // are met:
  8.        // 1. Redistributions of source code must retain the above copyright
  9.        //    notice, this list of conditions and the following disclaimer.
  10.        // 2. Redistributions in binary form must reproduce the above
  11.        //    notice, this list of conditions and the following disclaimer in
  12.        //    the documentation and/or other materials provided with the
  13.        //    distribution.
  14.        //
  15.        // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
  16.        // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  17.        // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  18.        // PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
  19.        // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20.        // SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT
  21.        // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  22.        // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  23.        // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24.        // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  25.        // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26.        // POSSIBILITY OF SUCH DAMAGE.
  27.        /////////////////////////////////////////////////////////////////////
  28.  
  29.      H Option(*SRCSTMT: *NoShowCpy) NoMain BndDir('QC2LE')
  30.  
  31.        ////////////////////////////////////////////////////////////////////
  32.        // Retrieve call stack for debugging purposes
  33.        // --
  34.        // This procedure will retrieve and return the call stack suitable
  35.        // for reporting the condition of the call stack at the time it is
  36.        // called.  The intended purpose is to allow such information to be
  37.        // placed in the job log for analysis of issues and similar
  38.        // situations.  An example use of this would be to place reference
  39.        // to it within an error handling routine, which might then
  40.        // write the call stack information (as a *DIAG message) to the job
  41.        // log just prior to issuing an escape message or similar.
  42.        // --
  43.        // The output can be trimmed such that the top of the call stack
  44.        // and the last (n) entries don't appear.  (For example, if the
  45.        // output should not contain the name of this procedure nor the
  46.        // errorHandler procedure from which it is called.
  47.        // The entries are separated by a pair of colon characters (::) so
  48.        // that the output might look like this:
  49.        //   QUOCMD/x01E1::TSTCALLSTK/2700::TSTCALLSTK(showCallStack)/9600
  50.        // If preferred, the output may be shown in bottom-to-top fashion:
  51.        //   TSTCALLSTK(showCallStack)/9600::TSTCALLSTK/2700::QUOCMD/x01E1
  52.        ////////////////////////////////////////////////////////////////////
  53.  
  54.      D/COPY QSYSINC/QRPGLESRC,QWVRCSTK
  55.  
  56.      D showCallStack   PR         65535    ExtProc('showCallStack') Varying
  57.      D  topToSkip                    10I 0 Value Options(*NoPass)
  58.      D  bottomToSkip                 10I 0 Value Options(*NoPass)
  59.      D  bottomToTop                    N   Value Options(*NoPass)
  60.  
  61.  
  62.      P showCallStack   B                   Export
  63.      D showCallStack   PI         65535    Varying
  64.      D  parmSkipTop                  10I 0 Value Options(*NoPass)
  65.      D  parmSkipBotm                 10I 0 Value Options(*NoPass)
  66.      D  parmOrder                      N   Value Options(*NoPass)
  67.  
  68.  
  69.      D RtvCallStack    PR                  ExtPgm('QWVRCSTK')
  70.      D  receiver                           Const like(myReceiver)
  71.      D  rcvrSize                     10I 0 Const
  72.      D  rcvFormat                     8    Const
  73.      D  jobIDinfo                          Const likeDS(rqsJob)
  74.      D  jobInfoFmt                    8    Const
  75.      D  myUSEC                             Like(errorStruct)
  76.  
  77.  
  78.  
  79.      D convertHexChar  PR                  ExtProc('cvthc')
  80.      D  ptrCharReturn                  *   Value
  81.      D  ptrHexSrc                      *   Value
  82.      D  hexLength                    10I 0 Value
  83.  
  84.  
  85.      D errorStruct     DS                  Inz Qualified
  86.      D  QUSBPRV                      10I 0 Inz(%Size(errorStruct))
  87.      D  QUSBAVL                      10I 0
  88.      D  QUSEI                         7
  89.      D                                1
  90.      D  QUSED01                    4096
  91.      D  bytesProvided                      Overlay(QUSBPRV)
  92.      D                                     Like(errorStruct.QUSBPRV)
  93.      D  bytesAvailable...
  94.      D                                     Overlay(QUSBAVL)
  95.      D                                     Like(errorStruct.QUSBAVL)
  96.      D  messageID                          Overlay(QUSEI)
  97.      D                                     Like(errorStruct.QUSEI)
  98.      D  messageData                        Overlay(QUSED01)
  99.      D                                     Like(errorStruct.QUSED01)
  100.  
  101.  
  102.      D entryList       S          65535    Varying
  103.  
  104.      D topToSkip       S             10I 0 Inz(0)
  105.      D bottomToSkip    S             10I 0 Inz(0)
  106.      D bottomToTop     S               N   Inz(*Off)
  107.  
  108.      D entryString     S           4096    Varying Dim(256)
  109.      D procName        S           4096    Varying
  110.      D stmtIDs         S             10    Dim(8) Based(pStmtIDs)
  111.      D procNameArea    S           4096    Based(pProcNameArea)
  112.      D I               S             10U 0
  113.      D J               S             10U 0
  114.      D stmtID          S             10    Varying
  115.      D hexInt          S              8
  116.      D incr            S             10I 0
  117.      D start           S             10I 0
  118.      D stop            S             10I 0
  119.  
  120.      D pReceiver       S               *   Inz(%Addr(myReceiver))
  121.      D myReceiver      S          65535
  122.      D hdr             DS                  LikeDS(QWVK0100) Based(pReceiver)
  123.      D pEntry          S               *
  124.      D entry           DS                  LikeDS(QWVCSTKE) Based(pEntry)
  125.  
  126.  
  127.      D rqsJob          DS                  Qualified Inz
  128.      D  jobname                      10    Inz('*')
  129.      D  jobuser                      10    Inz(*Blanks)
  130.      D  jobNumber                     6    Inz(*Blanks)
  131.      D  intJobID                     16    Inz(*Blanks)
  132.      D                                2    Inz(X'0000')
  133.      D  threadIndic                  10I 0 Inz(2)
  134.      D  threadID                      8    Inz(X'0000000000000000')
  135.  
  136.       /Free
  137.  
  138.        Reset errorStruct ;
  139.        errorStruct.bytesProvided = %Size(errorStruct) ;
  140.        If %Parms >= 1 ;
  141.           topToSkip = parmSkipTop ;
  142.           If %Parms >= 2 ;
  143.              bottomToSkip = parmSkipBotm ;
  144.              If %Parms >= 3 ;
  145.                 bottomToTop = parmOrder ;
  146.              EndIF ;
  147.           EndIF ;
  148.        EndIF ;
  149.  
  150.        Clear entryList ;       // Clear the field to be returned to caller
  151.  
  152.        // Retrieve the call stack information via IBM API
  153.  
  154.        rtvCalLStack(myReceiver: %Size(myReceiver)
  155.                   : 'CSTK0100'
  156.                   : rqsJob: 'JIDF0100'
  157.                   : errorStruct) ;
  158.  
  159.        // Position our header's pointer to the receiver area.
  160.  
  161.        pEntry = pReceiver + hdr.QWVEO ;      // First entry
  162.        For I = 1 to hdr.QWVERTN ;            // For each call stack entry
  163.           If entry.QWVPL = *Zero ;           // No procedure name
  164.              %Len(procName) = *Zero ;        // Clear our copy
  165.           Else ;
  166.              pProcNameArea = pEntry + entry.QWVPD ;
  167.              procName = %Subst(procNameArea: 1: entry.QWVPL) ;
  168.           EndIF ;
  169.           pStmtIDs = pEntry + entry.QWVSD ;  // Point to the Stmt IDs
  170.           entryString(I) = %Trim(entry.QWVPGMN) ;
  171.           If %Len(procName) > *Zero and procName <> entry.QWVPGMN ;
  172.              entryString(I) += '(' + %Trim(procName) + ')' ;
  173.           EndIF ;
  174.           If entry.QWVSRTN > *Zero ;            // If stmt IDs present
  175.              For J = 1 to entry.QWVSRTN ;       // For each stmt ID
  176.                 stmtID = %Trim(stmtIDs(J)) ;
  177.                 DoW %Subst(stmtID: 1: 1) = '0' and %Len(stmtID) > 1 ;
  178.                    stmtID = %Subst(stmtID: 2) ;
  179.                 EndDO ;
  180.                 entryString(I) += '/' + %Trim(stmtID) ;
  181.              EndFOR ;
  182.           ElseIF entry.QWVCTION > *Zero ;       // MI instruction #
  183.              convertHexChar(%Addr(hexInt): %Addr(entry.QWVCTION)
  184.                           : %Size(hexInt)) ;
  185.              If %Subst(hexInt: 1: 4) = '0000' ;
  186.                  entryString(I) += '/x' + %Subst(hexInt: 5) ;
  187.              Else ;
  188.                  entryString(I) += '/x' + hexInt ;
  189.              EndIF ;
  190.           EndIF ;
  191.           If %Len(entryList) > *Zero ;
  192.              entryList += '::' ;
  193.           EndIF ;
  194.           // Finished with this entry.  Since we have the length of this
  195.           // entry in entry.QWVEL, we will add this value to current
  196.           // pEntry to get next pEntry.
  197.           pEntry += entry.QWVEL ;            // Length this entry; -> Next
  198.        EndFOR ;
  199.  
  200.        // Well, that was fun.  Now let's order our output as requested,
  201.        // and return all except any entries that the caller wanted skipped.
  202.  
  203.        Clear entryList ;
  204.        If bottomToTop ;                     // Same sequence as IBM API
  205.           incr = 1 ;                        // We'll INCREMENT our array idx
  206.           start = bottomToSkip + 1 ;        // Starting at ...
  207.           stop = hdr.QWVERTN - topToSkip ;  // Last entry to use
  208.        Else ;                               // Oldest first
  209.           incr = -1 ;                       // We'll DECREMENT our index
  210.           start = hdr.QWVERTN - topToSkip ; // Starting at...
  211.           stop = bottomToSkip + 1 ;         // Last entry to use
  212.        EndIF ;
  213.        I = start ;                          // Ready ... go!
  214.        For J = 1 to %Abs(stop - start) + 1 ;
  215.           If        %Scan('_QRNP_PEP_': entryString(I)) = 0
  216.                 and %Scan('_CL_PEP': entryString(I)) = 0 ;
  217.              If %Len(entryList) > *Zero and %Len(entryString(I)) > 0 ;
  218.                 entryList += '::' ;
  219.              EndIF ;
  220.              entryList += entryString(I) ;
  221.           EndIF ;
  222.           I += incr ;
  223.        EndFOR ;
  224.  
  225.        Return entryList ;
  226.  
  227.        *INLR = *On ;
  228.        Return ;
  229.  
  230.       /End-free
  231.  
  232.      P                 E
  233.  
  234.  
  235.  
  236.  
  237.      H Option(*SRCSTMT: *NoShowCpy) BNDDIR('LUVBNDDIR') DftActGrp(*NO)
  238.  
  239.  
  240.      D showCallStack   PR         65535    ExtProc('showCallStack') Varying
  241.      D  topToSkip                    10I 0 Value Options(*NoPass)
  242.      D  bottomToSkip                 10I 0 Value Options(*NoPass)
  243.      D  bottomToTop                    N   Value Options(*NoPass)
  244.  
  245.  
  246.      D subProc         PR         65535    ExtProc('mySub') Varying
  247.      D  skipTop                      10I 0 Value
  248.      D  skipBottom                   10I 0 Value
  249.      D  oldestOnTop                    N   Value
  250.  
  251.  
  252.      D stack           S            512    Varying
  253.  
  254.  
  255.      D QUILNGTX        PR                  ExtPgm('QUILNGTX')
  256.      D   text                     65535a   const options(*varsize)
  257.      D   length                      10i 0 const
  258.      D   msgid                        7a   const
  259.      D   qualmsgf                    20a   const
  260.      D   errorCode                   20i 0 const
  261.  
  262.  
  263.      D Qp0zInitEnv     pr            10i 0 extproc('Qp0zInitEnv')
  264.  
  265.  
  266.       /Free
  267.  
  268.  
  269.        Qp0zInitEnv() ;
  270.        stack = subProc(2: 0: *Off) ;
  271.        QUILNGTX(stack: %len(stack): *blanks: *blanks: 0);
  272.        stack = subProc(2: 1: *On) ;
  273.        QUILNGTX(stack: %len(stack): *blanks: *blanks: 0);
  274.        stack = showCallStack() ;
  275.        QUILNGTX(stack: %len(stack): *blanks: *blanks: 0);
  276.        *INLR = *On ;
  277.        Return ;
  278.  
  279.       /End-free
  280.  
  281.      P subProc         B
  282.      D subProc         PI         65535    Varying
  283.      D  skipTop                      10I 0 Value
  284.      D  skipBottom                   10I 0 Value
  285.      D  oldestOnTop                    N   Value
  286.  
  287.       /Free
  288.        Return showCallStack(skipTop: skipBottom: oldestOnTop) ;
  289.       /End-free
  290.  
  291.      P                 E
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
© 2004-2019 by midrange.com generated in 0.008s valid xhtml & css