05
Tue, Nov
5 New Articles

Interactive RPG/400 Source Level Debugger

RPG
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Build your own integrated debugger using REXX

The AS/400 provides a baseline of debugging functions that is considered standard across many platforms. OS/400 allows us to suspend program execution when a particular statement is executed or a particular variable is altered and, again, resume execution of the program. We can display the flow of a program with trace listings of statements executed. Contents of variables can be examined and, if you choose, modified. Through the use of the AS/400 debugging commands (see my "Debugging Simplified" page 20 of this issue) we have a window into the actual processing of faulty programs to assist us in investigating and resolving the cause of program failure.

But the AS/400 lacks the integrated debugging environment that programmers on other platforms have the benefit of. Typically, an integrated debugging environment uses a source level debugger that combines the viewing of program source code with the simple invocation of the standard debugging functions. AS/400 programmers, on the other hand, must mimic this process with a source listing or SEU session while they use an interactive session to enter lengthy and cumbersome commands.

The Solution

OS/400 does, however, provide all the hooks and switches required to develop an integrated debugging environment. In fact, several third-party software firms are already marketing source level debuggers for the AS/400. But why not develop your own? Well, how about the time and effort involved to create screens and programs sophisticated enough to handle source level debugging. The solution--use REXX. REXX, which uses the Extended Program Monitor's (EPM) screen processor, does most of the screen input/output for you; display files are not used. EPM's screen I/O was originally developed for use with AS/400 BASIC, Pascal and C and supports the SAA standard use of F3, F9, F21, Roll-up, and Roll-down keys--no programming required. REXX can be used to read and write to the EPM screen with simple commands such as SAY and PULL. Users can then roll back and forth through the session output, retrieve previously entered commands with F9 or exit with F3 in a fashion similar to the command entry screen.

Using REXX, I have developed a working model of a source level debugger. This article will cover how RexxDebugger, as I called my debugger, works as well as providing some tips for its use. I call RexxDebugger a model of a debugger only because it is easily modified for your own requirements and, using it as a prototype, you will gain an insight into how to write your own debugger in CLP and a HLL.

Let's Try It Out

Before jumping into a discussion of the inner workings of RexxDebugger, let's try it out. Create the objects in Figures 1-7 (beginning on page 50) according to the instructions at the bottom of each figure. To set up the RexxDebugger environment, we run the Start RexxDebugger (STRREXDBG) command. You must enter the qualified name of the RPG program being debugged in the PGM parameter. The UPDPROD parameter determines whether production files can be updated; it defaults to *YES.

8 contains a simple RPG program (ORDLST) we suspect has a bug. Let's debug it with RexxDebugger. The ORDLST program as listed cannot be compiled but we are going to pretend that it is. Just follow the test as if you were at a workstation and use the figures as reference. First, we execute the STRREXDBG command as follows:

Figure 8 contains a simple RPG program (ORDLST) we suspect has a bug. Let's debug it with RexxDebugger. The ORDLST program as listed cannot be compiled but we are going to pretend that it is. Just follow the test as if you were at a workstation and use the figures as reference. First, we execute the STRREXDBG command as follows:

STRREXDBG PGM(ORDLST)

Next, we simply call the program with the following command:

CALL PGM(ORDLST)

Before any statements are processed, RexxDebugger gains control of the screen and, after the REXX interpreter flashes "REXX interpreter starting" for a few seconds, the following prompt is displayed:

 Start of terminal session. Program initialization. Set breakpoints. > Ready for RexxDebugger command. Type HELP for assistance. ________________________________________________________________________ F3=End of File F9=Retrieve F21=Extend line 

Suppose we want to find out in what statements ORDDTL appears. We can scan the source member in its entirety by running RexxDebugger's FIND command, as follows:

 Start of terminal session. Program initialization. Set breakpoints. > Ready for RexxDebugger command. Type HELP for assistance. find orddtl Start of terminal session. 100 FORDDTL IF E K DISK 1900 C ORDKEY SETLLRORDDTL 2100 C ORDKEY READERORDDTL 91 Press ENTER to end terminal session. F3=End of File F9=Retrieve F21=Extend line 

The text line "Press ENTER to end terminal session" is from the REXX interpreter telling us that a REXX procedure has completed; press Enter every time you see this prompt. With the results of the find, we now know that the Order Detail file (ORDDTL) is processed at statements 100, 1900 and 2100.

Let's now list the source member starting at statement 2100. Run the RexxDebugger GOTO 21 command (which moves the pointer to statement 2100), followed by the LIST 10 command (which lists 10 lines of code, starting at statement 2100):

 100 FORDDTL IF E K DISK 1900 C ORDKEY SETLLRORDDTL 2100 C ORDKEY READERORDDTL 91 Press ENTER to end terminal session. End of terminal session. > Ready for RexxDebugger command. Type HELP for assistance. goto 21 > Ready for RexxDebugger command. Type HELP for assistance. list 10 Start of terminal session. 002100 C ORDKEY READERORDDTL 91 002200 C *IN91 IFEQ '0' 002300 C ORDQTY MULT PRICE CHRGE 92 002400 C EXCPTLINOUT 002500 C END 002600 C END 002700 * 002800 C SETON LR 002900 C RETRN 003000 * Press ENTER to end terminal session. F3=End of File F9=Retrieve F21=Extend line 

As you can see, the EPM screen handler puts lines at the bottom of the screen and, as the screen fills up, rolls lines to the top of the screen. Similar to the command entry screen, the EPM screen allows you to roll back and forth through prior screens for information that has rolled off the top of the screen.

To find out why no detail records are being processed, we can set break points at the SETLL command and at the IFEQ statement following the read. To do this, cursor up to line 1900, press F9 to retrieve and press Enter. RexxDebugger then adds a break point for the retrieved statement number. To set a break point at line 2200, again, cursor to that line, hit F9, and press Enter. You'll see the following:

 list 10 Start of terminal session. 002100 C ORDKEY READERORDDTL 91 002200 C *IN91 IFEQ '0' 002300 C ORDQTY MULT PRICE CHRGE 92 002400 C EXCPTLINOUT 002500 C END 002600 C END 002700 * 002800 C SETON LR 002900 C RETRN 003000 * Press ENTER to end terminal session. End of terminal session. > Ready for RexxDebugger command. Type HELP for assistance. 1900 C ORDKEY SETLLRORDDTL Break point added at statement:1900 > Ready for RexxDebugger command. Type HELP for assistance. 002200 C *IN91 IFEQ '0' Break point added at statement:2200 > Ready for RexxDebugger command. Type HELP for assistance. _______________________________________________________________________ F3=End of File F9=Retrieve F21=Extend line 

Now it's possible to display program variables. Let's look at ORDNO and PARTNO by running RexxDebugger's DISP command: DISP ORDNO PARTNO

 > Ready for RexxDebugger command. Type HELP for assistance. 1900 C ORDKEY SETLLRORDDTL Break point added at statement:1900 > Ready for RexxDebugger command. Type HELP for assistance. 002200 C *IN91 IFEQ '0' Break point added at statement:2200 > Ready for RexxDebugger command. Type HELP for assistance. Press ENTER to end terminal session. End of terminal session. Start of terminal session. Break point hit at source line number 1900 > Ready for RexxDebugger command. Type HELP for assistance. disp ordno partno Start of terminal session. ORDNO ' 12345' PARTNO ' ' Press ENTER to end terminal session. End of terminal session. > Ready for RexxDebugger command. Type HELP for assistance. _______________________________________________________________________ F3=End of File F9=Retrieve F21=Extend line 

Here, then, is the problem: the part number is blank and the subsequent Read Equal will fail. The program should set PARTNO to a valid value for that order before positioning the file or it should use only the order number as the key. Let's test our theory by modifying PARTNO to be a good number now, since statement 1900 will not execute until after ORDLST resumes. Type the following RexxDebugger command: CHANGE PARTNO 54321. After RexxDebugger accepts the change command, press Enter to resume execution of the buggy program. When the program hits line 2200, RexxDebugger, again, gains control and informs you of what statement number you are at. Looking at: "Break Point hit at source line number 2200," we realize that we have forgotten what statement 2200 was. Rolling back the EPM, we can see the section of code and decide to list the value for *IN91, the READE end of file indicator, and two of the order detail fields with: DISPLAY *IN91 ORDQTY PRICE. RexxDebugger then displays:

 PARTNO ' ' Press ENTER to end terminal session. End of terminal session. > Ready for RexxDebugger command. Type HELP for assistance. change partno 54321 > Ready for RexxDebugger command. Type HELP for assistance. Press ENTER to end terminal session. End of terminal session. Start of terminal session. Break point hit at source line number 2200 > Ready for RexxDebugger command. Type HELP for assistance. disp *in91 ordqty price Start of terminal session. *IN91 '0' ORDQTY ' 12' PRICE ' 2.98' Press ENTER to end terminal session. End of terminal session. > Ready for RexxDebugger command. Type HELP for assistance. _______________________________________________________________________ F3=End of File F9=Retrieve F21=Extend line 

Hey, we've got a hit, and we've proved our theory about setting PARTNO before the SETLL. Let's remove the break points with the REMOVE *ALL, and allow the program to continue without pause by pressing Enter until RexxDebugger returns control.

So, How Does It Work?

The big hook into the RexxDebugger utility is in the REX001CL CL (2) program where it sets the first break point to be at program initialization time (*INIT). The CL Add Breakpoint (ADDBKP) command has a parameter, BKPPGM, which allows you to specify the name of a program to receive control when a break point is hit. For our purposes, that program is the CL program-- REX001CLA (3). REX001CLA accepts the parameters that OS/400 passes, informing us of the breaking (sic) program, the recursion level, the break point statement number and the machine instruction number. REX001CLA then retrieves the source file name, and source and object library of the program and, after concatenating them into one field, passes them to the REXX procedure--REX001RX (4).

The big hook into the RexxDebugger utility is in the REX001CL CL (Figure 2) program where it sets the first break point to be at program initialization time (*INIT). The CL Add Breakpoint (ADDBKP) command has a parameter, BKPPGM, which allows you to specify the name of a program to receive control when a break point is hit. For our purposes, that program is the CL program-- REX001CLA (Figure 3). REX001CLA accepts the parameters that OS/400 passes, informing us of the breaking (sic) program, the recursion level, the break point statement number and the machine instruction number. REX001CLA then retrieves the source file name, and source and object library of the program and, after concatenating them into one field, passes them to the REXX procedure--REX001RX (Figure 4).

The REXX procedure, REX001RX, is the powerhouse of our debugging utility and yet, it is fairly short. REX001RX begins by parsing the passed parameters, displaying the break point statement number and setting the program source relative record number equal to the break point. Next, REX001RX prompts us for the RexxDebugger debugging commands. These commands are processed until we enter the QUIT command or resume execution of the program by pressing Enter without the entry of a command.

The command processing portion of RexxDebugger is controlled with the REXX case construct: SELECT, WHEN and OTHERWISE. Each iteration of the main processing loop prompts us with the REXX SAY command and receives our response with the PULL command. Whatever we type, or retrieve with F9, drops through the SELECT statement until a WHEN clause is true. Each of these WHEN clauses use the REXX WORD function to parse the first word of the input value, IN, and compare it to one of the RexxDebugger commands (see the RexxDebugger Command Help display at the beginning of this article for a list of available commands). If none of the WHEN clauses is true, then the OTHERWISE clause executes sending the invalid entry message to the EPM.

For brevity, and also because REXX code is very easy to read, I will explain only the more interesting sections of RexxDebugger's code: LIST, FIND, DISPLAY, GOTO and F9 for ADDBKP. The LIST RexxDebugger command displays source statements on the EPM session screen. With REXX, we have a problem reading from a source file because REXX does not directly support file processing. But, the EPM does support redirection of the standard input file, STDIN. To do this piping, RexxDebugger invokes a second REXX procedure, REX001RXB (6) passing the member name, source file, source library, the relative position of the file and the number of lines to list. REX001RXB starts by overriding the standard input file to the source member, positioning the file at the passed relative record number. The routine then reads the source file with the PARSE command and lists the records out to the EPM with the SAY command.

For brevity, and also because REXX code is very easy to read, I will explain only the more interesting sections of RexxDebugger's code: LIST, FIND, DISPLAY, GOTO and F9 for ADDBKP. The LIST RexxDebugger command displays source statements on the EPM session screen. With REXX, we have a problem reading from a source file because REXX does not directly support file processing. But, the EPM does support redirection of the standard input file, STDIN. To do this piping, RexxDebugger invokes a second REXX procedure, REX001RXB (Figure 6) passing the member name, source file, source library, the relative position of the file and the number of lines to list. REX001RXB starts by overriding the standard input file to the source member, positioning the file at the passed relative record number. The routine then reads the source file with the PARSE command and lists the records out to the EPM with the SAY command.

The REX001RX procedure's variable, SRCRRN (source relative record number), bears some consideration because it is heavily used. When OS/400 hands over control to RexxDebugger, it passes the statement number of the break point. RexxDebugger receives the statement number as SRCRRN. When the LIST command is used, it will list statements starting at the break point number. The GOTO command, however, allows you to change this variable so that subsequent use of LIST will display source from a different statement number. For smooth operation, the sequence numbers of your program should be resequenced after each modification and before recompilation; otherwise, the SRCRRN will be off by the number of source statements with decimal values.

The RexxDebugger FIND command--the sister operation to LIST--will display all the occurrences of the string entered. After entry of the FIND, RexxDebugger invokes OS/400's FNDSTRPDM command to print the matching statements and then start another REXX procedure, REX001RXA (5). REX001RXA copies the spool file output from FNDSTRPDM to a work file, PRT132, and then overrides EPM's standard input file to PRT132. REX001RXA reads through all the spool file records parsing out and listing to the EPM all the occurrences of the string. Try that in RPG or CL.

The RexxDebugger FIND command--the sister operation to LIST--will display all the occurrences of the string entered. After entry of the FIND, RexxDebugger invokes OS/400's FNDSTRPDM command to print the matching statements and then start another REXX procedure, REX001RXA (Figure 5). REX001RXA copies the spool file output from FNDSTRPDM to a work file, PRT132, and then overrides EPM's standard input file to PRT132. REX001RXA reads through all the spool file records parsing out and listing to the EPM all the occurrences of the string. Try that in RPG or CL.

To display the value of variables, RexxDebugger uses another REXX procedure that operates similar to REX001RXA's copying and parsing of a spool file. The section of code that processes the RexxDebugger DISPLAY command into the AS/400 DSPPGMVAR command builds the DSPPGMVAR command by looping through the words in the input string, IN, until no more variable names are in the string or the limit of 10 is reached. As each variable is parsed from IN, it is concatenated to the RexxDebugger command variable DSPVAR. When DSPVAR is constructed, its value contains the OS/400 command DSPPGMVAR with variables. DSPPGMVAR is executed by REXX on the RexxDebugger statement line where DSPVAR appears (roughly comparable to QCMDEXC). This dynamic creation of command statements adds inherent power to the ability of the REXX interpreter.

As we learned earlier, the adding of break points is easily done by retrieving RPG source statements previously listed to the EPM with the F9 key and pressing Enter. The SELECT statement of RexxDebugger knows that an Add Break Point request has been entered WHEN the first word of the input string is a number. You can also add a break point by typing in a valid statement number and pressing Enter. The input statement number is then converted from a string variable to a numeric variable by assigning itself, multiplied by one to the variable STMT. The OS/400 Add Break Point (ADDBKP) command is then processed; note that the break point program parameter of ADDBKP is set to the CL program, REX001CLA so that RexxDebugger will again receive control when the new break point is hit.

There are several other RexxDebugger commands that we have not mentioned as they are fairly self-explanatory and are covered in RexxDebugger's help section. The BROWSE command, for instance, can be used as a high-speed method of viewing and scanning long source members since--due to the nature of an interpreter--the REXX FIND procedure is a little slow. The STEP command is another useful RexxDebugger function; it allows you to enter a statement range to break on. Every statement number, evenly divisible by 100, between the entered range will then be added as a break point.

RexxDebugger's Downfall

REXX, because it is interpretive, is slow. Additionally, to read from different files, RexxDebugger requires the invocation of other REXX procedures. Another problem is that RexxDebugger requires resequencing of source members after modification and before recompilation because the debugger retrieves statements by relative record number. Your EPM screen also gets cluttered with commands, source and EPM messages.

Nevertheless, if you consider the time required to do the variety of functions directly available from within RexxDebugger, you might discover the comparable AS/400 functions take even more time. More time to flip between the multitude of screens, print new source listings, invoke SEU and scribble notes. RexxDebugger, by integrating the debugging process, streamlines the effort.

But then, if top speed is a requirement, I did say RexxDebugger was just a working model. RexxDebugger can be converted to an HLL with subfile processing, split screens and windows; although, you will miss the string handling capabilities of REXX. Or, you might also consider purchasing one of the third party debugging products available.

For Best Use...

In the meantime, until you write or purchase a faster integrated debugger, there a few tips on making the best use of RexxDebugger. First of all, think in terms of code fragments. List sections of pertinent code to the EPM, not long portions. Also, to get started, use the browse option to quickly scan for those pertinent sections of code and then return to RexxDebugger, GOTO the statement number of interest and LIST the number of lines of interest. Have some fun customizing RexxDebugger, too; if you find yourself going to the command entry screen and doing the same function--add it to RexxDebugger.

Editor's Note: RexxDebugger works for RPG programs only, although it will work for CL programs with slight modifications. In most other languages, the compiler assigns statement numbers that are different from the source line numbers--COBOL and PL/I are two such languages. Because RexxDebugger depends on their equality to do its work, RexxDebugger cannot be used for such programming languages.

 Sidebar: RexxDebugger Commands =================== REXX DEBUGGER HELP ========================== BROWSE: Displays the physical file member of the source being debugged (DSPPFM). Useful for lengthy source members. CHANGE variable value: Changes the value of a variable. CLEAR: Clears the screen. DISPLAY variable1-10: Displays up to 10 program variables. ENTER: Resumes program execution. FIND string: Searches for and displays all occurrences of a string with no embedded spaces. GOTO rrn: Set source relative record number (see LIST). LIST number: List source lines from last breakpoint, last statement listed, or from rrn set with GOTO. QCMD: The "backdoor" to the Command Entry panel. QUIT: Aborts program. REMOVE breakpoint: Removes a previously set breakpoint. STEP fromstmt tostmt: Set breakpoints on all statements between two statement numbers. To set a breakpoint, move cursor to line LISTed and press F9 or enter entire 6-digit statement number, including all leading zeros and omitting the decimal point. > Ready for RexxDebugger command. Type HELP for assistance. _______________________________________________________________________ F3=End of File F9=Retrieve F21=Extend line 
Interactive RPG/400 Source Level Debugger

Figure 1 Command STRREXDBG

 STRREXDBG: CMD PROMPT('Start REXX Debugger') PARM KWD(PGM) TYPE(Q1) MIN(1) PROMPT('Program') PARM KWD(UPDPROD) TYPE(*CHAR) LEN(4) RSTD(*YES) + DFT(*YES) VALUES(*YES *NO) PROMPT('Update + production files') Q1: QUAL TYPE(*NAME) LEN(10) MIN(1) QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + SPCVAL((*LIBL)) PROMPT('Library') 
Interactive RPG/400 Source Level Debugger

Figure 2 CL program REX001CL

 REX001CL: + PGM PARM(&QPGM &UPDPROD) DCL VAR(&PGM) TYPE(*CHAR) LEN(10) DCL VAR(&PGMLIB) TYPE(*CHAR) LEN(10) DCL VAR(&QPGM) TYPE(*CHAR) LEN(20) DCL VAR(&UPDPROD) TYPE(*CHAR) LEN(4) CHGVAR VAR(&PGM) VALUE(%SST(&QPGM 1 10)) CHGVAR VAR(&PGMLIB) VALUE(%SST(&QPGM 11 10)) CHKOBJ OBJ(&PGMLIB/&PGM) OBJTYPE(*PGM) MONMSG MSGID(CPF9801) EXEC(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Program' *BCAT + &PGM *BCAT 'not found in' *BCAT &PGMLIB) MSGTYPE(*ESCAPE) RETURN ENDDO MONMSG MSGID(CPF9810) EXEC(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Program + library' *BCAT &PGMLIB *BCAT 'not found') MSGTYPE(*ESCAPE) RETURN ENDDO STRDBG PGM(&PGMLIB/&PGM) UPDPROD(&UPDPROD) ADDBKP STMT(*INIT) BKPPGM(*CURLIB/REX001CLA) OVRPRTF FILE(QPUOPRTF) HOLD(*YES) OVRPRTF FILE(QPDBGDSP) HOLD(*YES) CRTPF FILE(QTEMP/PRT132) RCDLEN(132) MONMSG MSGID(CPF0000) ENDPGM 
Interactive RPG/400 Source Level Debugger

Figure 3 CL program REX001CLA

 REX001CLA: + PGM PARM(&PGM &RECURS &STMT &MI) DCL VAR(&MI) TYPE(*CHAR) LEN(5) DCL VAR(&OBJLIB) TYPE(*CHAR) LEN(10) DCL VAR(&PGM) TYPE(*CHAR) LEN(10) DCL VAR(&RECURS) TYPE(*CHAR) LEN(5) DCL VAR(&REXPRM) TYPE(*CHAR) LEN(60) DCL VAR(&SRCF) TYPE(*CHAR) LEN(10) DCL VAR(&SRCFLIB) TYPE(*CHAR) LEN(10) DCL VAR(&STMT) TYPE(*CHAR) LEN(10) RTVOBJD OBJ(&PGM) OBJTYPE(*PGM) RTNLIB(&OBJLIB) SRCF(&SRCF) + SRCFLIB(&SRCFLIB) CHGVAR VAR(%SST(&REXPRM 1 10)) VALUE(&PGM) CHGVAR VAR(%SST(&REXPRM 12 10)) VALUE(&OBJLIB) CHGVAR VAR(%SST(&REXPRM 23 10)) VALUE(&SRCFLIB) CHGVAR VAR(%SST(&REXPRM 34 10)) VALUE(&SRCF) CHGVAR VAR(%SST(&REXPRM 45 10)) VALUE(&STMT) STRREXPRC SRCMBR(REX001RX) SRCFILE(MAGAZINE/PROPOSED) PARM(&REXPRM) ENDPGM 
Interactive RPG/400 Source Level Debugger

Figure 4 REXX procedure REX001RX

 arg pgm olib slib sfil bkp if datatype(bkp) = 'CHAR' then do rrn = 1 say 'Program initialization. Set brakpoints.' end else do rrn = trunc(bkp/100) say 'Breakpoint hit at source line number' bkp end do until word(in,1) = 'QUIT' say '> Ready for RexxDebugger command. Type HELP for assistance.' pull in select when word(in,1) = '' then return when word(in,1) = 'BROWSE' then 'dsppfm file('slib'/'sfil') mbr('pgm')' when word(in,1) = 'CHANGE' then 'chgpgmvar pgmvar('word(in,2)') value('word(in,3)')' when word(in,1) = 'CLEAR' then do 21 say ' ' end when word(in,1) = 'DISPLAY' then do dspvar = 'dsppgmvar pgmvar(' do loop = 2 to 11 if word(in,loop) = '' then leave dspvar = dspvar || '(' || word(in,loop) || ') ' end dspvar = dspvar || ') output(*print)' dspvar 'strrexprc srcmbr(rex001rxc) srcfile(magazine/proposed)' end when word(in,1) = 'FIND' then do find = substr(in,6,24) 'fndstrpdm string('find') file('slib'/'sfil') ', 'mbr('pgm') option(*none) prtrcds(*all)' 'strrexprc srcmbr(rex001rxa) srcfile(magazine/proposed)' find = '' end when word(in,1) = 'GOTO' then rrn = word(in,2) when word(in,1) = 'HELP' then call display_help when word(in,1) = 'LIST' then do list = word(in,2) if list = '' then list = 10 'strrexprc srcmbr(rex001rxb) parm('''pgm slib sfil rrn , list''') srcfile(magazine/proposed)' rrn = rrn + list end when word(in,1) = 'QCMD' then 'call qcmd' when word(in,1) = 'QUIT' then do say 'Aborting REXX Debugger.' 'rmvbkp *all' 'addbkp stmt(*init) bkppgm(rex001cla)' say 'Breakpoints removed except for *INIT.' return end when word(in,1) = 'REMOVE' then do rmvbkp = 'rmvbkp stmt(' do loop = 2 to 11 if word(in,loop) = '' then leave rmvbkp = rmvbkp || '(' || word(in,loop) || ') ' end rmvbkp = rmvbkp || ') ' rmvbkp say rmvbkp end when word(in,1) = 'STEP' then do fromstmt = word(in,2) * 1 tostmt = word(in,3) * 1 stmt = fromstmt do loop = fromstmt to tostmt by 10 'addbkp stmt('stmt') bkppgm(rex001cla)' stmt = stmt * 10 end end when datatype(word(in,1)) = 'NUM' then do stmt = word(in,1) * 1 'addbkp stmt('stmt') bkppgm(rex001cla)' say 'Breakpoint added at statement: 'stmt'.' end otherwise say in' is an invalid entry. Try again.' end end return display_help: say '=================== REXX DEBUGGER HELP ==========================' say 'BROWSE: Displays the physical file member of the source being' say ' debugged (DSPPFM). Useful for lengthy source members.' say 'CHANGE variable value: Changes the value of a variable.' say 'CLEAR: Clears the screen.' say 'DISPLAY variable1-10: Displays up to 10 program variables.' say 'ENTER: Resumes program execution.' say 'FIND string: Searches for and displays all occurrences of a' say ' string with no embedded spaces.' say 'GOTO rrn: Set source relative record number (see LIST).' say 'LIST number: List source lines from last breakpoint, last' say ' statement listed, or from rrn set with GOTO.' say 'QCMD: The "backdoor" to the Command Entry panel.' say 'QUIT: Aborts program.' say 'REMOVE breakpoint: Removes a previously set breakpoint.' say 'STEP fromstmt tostmt: Set breakpoints on all statements between' say ' two statement numbers.' say ' ' say 'To set a breakpoint, move cursor to line LISTed and press F9' say ' or enter entire 6-digit statement number, including all' say ' leading zeros and omitting the decimal point.' return 
Interactive RPG/400 Source Level Debugger

Figure 5 REXX procedure REX001RXA

 'cpysplf file(qpuoprtf) tofile(prt132) splnbr(*last)' 'dltsplf file(qpuoprtf) splnbr(*last)' 'ovrdbf stdin prt132' do until word(in,1) = 'SEQNBR' pull in if in = '' then do say 'No matches found.' exit end end do until word(in,1) = 'NUMBER' | in = '' pull in if datatype(word(in,1)) = 'NUM' then say substr(in,1,70) end return 
Interactive RPG/400 Source Level Debugger

Figure 6 REXX procedure REX001RXB

 arg mbr lib srcf n roll 'ovrdbf file(stdin) tofile('lib'/'srcf') mbr('mbr') position(*rrn ', n')' do roll parse linein src if src = '' then leave say substr(src,1,6) substr(src,13,60) end 
Interactive RPG/400 Source Level Debugger

Figure 7 REXX procedure REX001RXC

 'cpysplf file(qpdbgdsp) tofile(prt132) splnbr(*last)' 'dltsplf file(qpdbgdsp) splnbr(*last)' 'ovrdbf stdin prt132' do until word(in,1) = 'VARIABLE' pull in if in = '' then do say 'Variable not found.' exit end end do forever field = substr(in,45,10) do until word(in,1) = 'TYPE' pull in end if substr(in,47,6) = 'PACKED' then loop = 2 if substr(in,47,5) = 'ZONED' then loop = 2 if substr(in,47,9) = 'CHARACTER' then loop = 3 do loop pull in end do until word(in,1) = 'VARIABLE' if substr(in,1,3) = ' ' then say field' 'substr(in,4,60) field = ' ' pull in if substr(in,52,5) = 'E N D' | in = '' then exit end end return 
Interactive RPG/400 Source Level Debugger

Figure 8 Sample RPG program ORDLST

 Figure 8: Sample RPG Program ORDLST 100 FORDDTL IF E K DISK 200 FQSYSPRT O F 132 OF PRINTER 300 * 400 C *ENTRY PLIST 500 C PARM ORD@@ 600 C PARM PART@@ 700 * 800 C *LIKE DEFN ORDNO ORD@@ 900 C *LIKE DEFN PARTNO PART@@ 1000 * 1100 C ORDKEY KLIST 1200 C KFLD ORDNO 1300 C KFLD PARTNO 1400 * 1500 C EXCPTLINHDR 1600 * 1700 C Z-ADDORD@@ ORDNO 1800 * 1900 C ORDKEY SETLLRORDDTL 2000 C *IN91 DOUEQ'1' 2100 C ORDKEY READERORDDTL 91 2200 C *IN91 IFEQ '0' 2300 C ORDQTY MULT PRICE CHRGE 92 2400 C EXCPTLINOUT 2500 C END 2600 C END 2700 * 2800 C SETON LR 2900 C RETRN 3000 * 3100 OQSYSPRT E 1 LINHDR 3200 O 'Order' 3300 O + 1 'Part Number' 3400 O 34 'Price' 3500 O 41 'Quantity' 3600 O 54 'Charge' 3700 O 65 'Due Date' 3800 O E 1 LINOUT 3900 O ORDNO 4000 O PARTNO + 1 4100 O PRICE J + 1 4200 O ORDQTYZ + 1 4300 O CHRGE J + 1 4400 O DUEDTEY + 1 
Don Denoncourt

Don Denoncourt is a freelance consultant. He can be reached at This email address is being protected from spambots. You need JavaScript enabled to view it..


MC Press books written by Don Denoncourt available now on the MC Press Bookstore.

Java Application Strategies for iSeries and AS/400 Java Application Strategies for iSeries and AS/400
Explore the realities of using Java to develop real-world OS/400 applications.
List Price $89.00

Now On Sale

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: