Appendix C.  REXX Goodies.

TSTREX Goodie

While you are coding procedures, you will often have a need to test whether REXX reacts the way you expect.  Running the exec you are writing is often not possible as it is either not completed or too long to execute... 

You can of course write a small procedure that contains the statement(s) to test.  This is fine, especially to test a whole routine, but there is better if you have to test only a few statements...

TSTREX goodie

This goodie is an improved version of the original REXTRY(footnote 1) tool provided by the author of REXX, Mike Cowlishaw.  Both tools will prompt you for REXX statements and execute them.
You can execute almost everything (e.g. DO loops) as long as you can type it on the input area (some 140 chars).  REXTRY is in fact a procedure that uses INTERPRET to interpret the commands you enter at the console.  You will therefore often have to use SAY commands to see the results.

You can use REXTRY:

These are examples of commands you can use while executing REXTRY

    a=10
    b=20
    c=a*b
    say c

or, in one shot:

    a=10;b=20;c=a*b;say c

This is how you can use it as a calculator :

    say 104203*1.195

or to test a loop:

    do i=1 to 10;say i**2;end

or a test for parsing :

    parse value 'PROFILE XEDIT A (WIDTH 120) MYPAR' with . ')' options;say options

The TSTREX goodie further improves REXTRY in following areas:

If you want, you could try to practice TSTREX now and try to find the answer to following questions:

  1. Is a header stacked when issuing Q DISK R/W (STACK ?
  2. And is it with Q DISK RUBBISH (STACK ?
  3. Or with Q DISK fm  when fm is not accessed ?
  4. How do you get rid of the stacked data (name 2 alternatives) ?

OS/2 REXX has equivalent tools: REXXTRY (note 2 X characters) for normal line mode procedures and PMREXX for procedures using OS/2 Presentation Manager features or if you want to switch interactive trace on or off on the fly (equivalent to TS | TE in CMS).  For more information, see the online HELP of OS/2.

DOREXX XEDIT

This goodie is the best choice when you have to execute only one statement from within XEDIT.  For example:

  DOREXX msg 1024*1024
  DOREXX msg datatype('','W')   /* see if REXX considers "null" as numeric */
  DOREXX parse value '1234567890' with A 2 B +4 c; msg a ? b ? c

Note: DOREXX can also be used to execute the REXX statement displayed at the current line: if you issue DOREXX without parameters, then it interprets the current line.

CKRX Goodie

When you issue the command CKRX from the XEDIT command line, while you are editing a procedure, the goodie will run the procedure with the trace Scan option, and, if errors are detected, the scan will be presented in another Xedit screen.  This is an example:

     1 *-* /**T EXEC A1**/Trace Scan
       *-* /* Procedure T */
     2 *-* address command
     3 +++ bfm='T ;todayb=date('B
DMSREX462E Error 15, line 3: Invalid hexadecimal or binary string

The message is misleading here, as the real reason for the error is that there is a quote missing in the statement bfm='T.  As a consequence, ;todayb=date( is considered to be part of a constant string, and hence, the subsequent B makes is look like a binary string.  Anyway, without CKRX, the error would only appear when the procedure is running life.

EXECCALL Goodie

When you develop an application such as a REXX procedure, it is normal that you have to test this application frequently.  And you want to do this as easy and quickly as possible.

That's exactly the domain that the EXECCALL goodie wants to address.

EXECCALL includes intelligence in order to recognize what you want to test.  Originally it was meant for testing EXEC and XEDIT macros, but now EXECCALL also recognizes FILELISTs, PACKAGEs, HELP files, SCRIPT sources (Document Composition Facility), and CMS Communications Directories (SCOMDIR and UCOMDIR).

EXECCALL is meant to be executed from XEDIT's environment.  The procedure will first save your file if it is changed, and then execute it. When execution is finished, you're back in XEDIT and you can continue your development or correct any errors you discovered while testing your procedure.

EXECCALL can be executed from XEDIT's command line, but it is by far more convenient to assign the function to a PF-key in XEDIT.

Command format

 ++--EXECCALL---+-----+-+---------------------+--+--------------+-+
                +-.TS-+ +--.MACRO boot-macro--+  +--parameters--+
                        +--.EXEC boot-exec----+

Where:

.TS
tells EXECCALL to run your procedure using Interactive Trace Mode  (it will issue set exectrac on for you, before launching your EXEC).

parameters
are the parameters you want to pass to the procedure you want to test.  If you assigned EXECCALL to a PF-key, then, before pressing the key, you should type the parameters in XEDIT's command line.  The parameter-string can contain "run-time variables" taking the form of .&1, .&2, ... .&n, or .&* or .&  For more information about the "run-time variables" see the usage examples below.

.EXEC boot-exec
allows you to call a "bootstrap" exec that will call the exec/macro you are editing.  For example: FILELIST is a procedure delivered with the system.  But it also makes use of a specialized XEDIT profile, called PROFFLST XEDIT.  If you want to update this profile, and you want to test it, then you have to call FILELIST as the bootstrap procedure.  The command would thus be execcall .exec filelist

.MACRO boot-macro
allows you to call a "bootstrap" XEDIT macro that will call the exec/macro you are editing.

Usage notes


Usage examples

We suppose that you're editing procedure MYEXEC EXEC.

  1. the simplest example :
       - SET PF10 EXECCALL
       - press PF10
         ==> EXECCALL issues : EXEC MYEXEC
    
  2. another simple example :
       - SET PF10 EXECCALL
       - type myparms in XEDITs command line & press PF10
         ==> EXECCALL issues : EXEC MYEXEC myparms
    

    or with enabling interactive trace :

       - SET PF22 EXECCALL .TS
       - type myparms in XEDITs command line & press PF10
         ==> EXECCALL issues : SET EXECTRAC ON ;  EXEC MYEXEC myparms
    
  3. a little bit less simple now :
       - SET PF10 EXECCALL testparms
       - press PF10
         ==> EXECCALL issues : EXEC MYEXEC testparms
    

    but with the same PF10 :

       - type myparms in XEDITs command line & press PF10
         ==> EXECCALL issues : EXEC MYEXEC myparms
    
  4. a complex example with "run-time variables" :
       - SET PF10 EXECCALL testp .&1 (opt .&2 rest
       - type myparms myoption in XEDITs command line & press PF10
         ==> EXECCALL issues : EXEC MYEXEC testp myparm (opt myoption rest
    
  5. a complex example with "run-time variables" & "bootstrap EXEC" :
       - XEDIT SOME XEDIT       (xedit my SOME macro to be called by MYEXEC)
       - SET PF10 EXECCALL .EXEC MYEXEC testp .&1 (opt .&2 rest
       - type myparms myoption in XEDITs command line & press PF10
         ==> EXECCALL issues : EXEC MYEXEC testp myparm (opt myoption rest
    

Note: valid run-time variables are :

.&n
replaced by word "n" of CMDline parms
.&*
replaced by complete CMDline parms
.&
replaced by "what's left" after last .&n

BENCH Goodie

The BENCH goodie allows you to measure the performance of a procedure.

The format of the command is:

>>--BENCH--+--------------------------------------+-cmd_to_measure--><
           +-(-! Bench Options !--+-----------+-)-+
                                  +-,-comment-+

Bench options:
!-+----------------------------------------------------------------------------+--!
  ! +-Times--1-+ +-Run-1----+
  +-+-Times--n-+-+-Run-n----+-+---------------+-+----+-+----------+-+--------+-+
                 !-Run-=----! +-Address-envir-+ +-HT-+ +-EXECLOAD-+ +-FORGET-+
                 +-Run-Next-+

where:
Times specifies the number of times the command_to_measure is to be run.  Default is 1.
Run identifies the benchmark run to allow for comparison with other runs.  The default is 1, but you can specify
  • Run n specific run number
  • Run Next auto increment number
  • Run = reuse last benchmark number again
  • Address To (re-)define the addressing environment of the procedure to be benchmarked (e.g. Address ISPEXEC).  Default is CMS.
    HT To suppress the CMS line output
    EXECLOAD To force the procedure to be loaded in storage before the benchmark runs (in order to eliminate the I/O for loading from the I/O count).
    FORGET To forget any information stored in GLOBALV by BENCH.
    comment To associate a comment to the run.  It will be displayed in the run results.

    BENCH uses the information provided by the CP INDICATE command to calculate the resource consumptions for the procedure.

    For example, to compare the performance of procedures TEST1 and TEST2, issue the following commands:

      BENCH (Times 100 Run 1 EXECLOAD Run with EXECIO) TEST1
      BENCH (Times 100 Run 2 EXECLOAD Run with PIPES) TEST2
    

    The output may look like this:

     R   V.cpu   T.cpu   SIO    IO  Servce  Elaps Page Page ! Comment/Command
     U    time    time         time   time   time  rds wrts !
     N  (Secs)  (Secs)   nbr (Secs) (Secs) (Secs)           !
    --------------------------------------------------------+----------------------
     1 0.30013 0.31015     0  0.000 0.3101  0.320    0    0  EXEC TEST1 Run with EXECIO
     2 0.21012 0.22013     0  0.000 0.2201  0.230    0    0  EXEC TEST2 Run with PIPES
    

    Where:
    Vtime The virtual CPU time in seconds.
    Ttime The total CPU time in seconds.
    SIO The number of Virtual I/O operations.  Note that if the procedure performs I/O through SFS, SQL or any other server, these I/O operations will not be seen and reported.
    IO time The estimated execution time taking the I/O into account.  I/O service times have a broad range of values, as these depend on the technology, whether caching is active or not, etc.  This figure gives you an indication of the I/O part of the application.  We use 25 msec per I/O.
    Service time Is an approximation of the total internal response time (ITR).
    Elapsed time The duration of the procedure as seen by the user.  This is highly dependent on the load of the system and should therefore normally be ignored.
    Page Number of page reads and writes.

    The consumption of the BENCH procedure itself is of course not included in the results.  In order to exclude the CMS overhead associated to loading of your procedure, you may want to EXECLOAD it before launching the benchmark, or to add the EXECLOAD option to let BENCH do this for you.

    For more examples, see the documents discussing the solutions for the coding exercises.

    BENCH2 is yet another goodie that can be used to measure only parts of procedures.  Is basically used as follows:

      /* My procedure */
      address command
      'EXEC BENCH2 INIT'                 /* initialize BENCH2 environment */
      /* do some processing you want to measure */
      ...
      'EXEC BENCH2 SHOW'                  /* what did we consume till now */
      /* do other stuff */
      'EXEC BENCH2 SHOW'             /* what did we consume for this step */
      /* this is last alternative we want to test */
      'EXEC BENCH2 LAST'                /* show final results and cleanup */
      exit
    

    More information can be found in the prologue of BENCH2 EXEC.


    Footnotes:

      Why was there only one X in REXTRY ?  Well, before REXX got included in VM/SP Release 3, the interpreter was internally available in IBM under the name REX.  For legal reasons, as REX was already a registered trademark, IBM added a second X when making the product general available.
    Back to text