Learn a way to make debugging a bit easier.
Written by Junlei Li
I used to debug programs under Linux with gdb. The versatile supports for expressions provided by gdb allow programmers to evaluate expressions containing any kind of constants, variables, High-Level Language (HLL)-specific operators, type casts, and even function calls. The IBM i System Debugger supports neither calls to user procedures nor calls to language-specific library routines or built-in functions (BIFs)—for example, RPG BIFs, COBOL intrinsic functions, or CL BIFs. Well, the IBM i System Debugger supports a number of debug built-ins that can be used in expressions within a debug command.
The debug BIFs supported by the System Debugger include %SUBSTR, %ADDR, %INDEX, %VAR, and %LOCALVARS. Note that not every debug BIF can be used when debugging a program written in a specific HLL. Debug BIFs available for debugging different IBM i HLLs are listed in the following table.
Debug BIFs |
|||||
HLL |
%SUBSTR |
%ADDR |
%INDEX |
%VAR |
%LOCALVARS |
RPG |
Y |
Y |
Y |
Y |
Y |
COBOL |
Y |
Y |
N |
Y |
Y |
CL |
Y |
Y |
N |
Y |
N |
C/C++ |
N |
N |
N |
N |
Y |
Java |
N |
N |
N |
N |
Y |
Documents about the Debug BIFs can be found in language-specific manuals, including these:
- Section Using Debug Built-In Function in Chapter 12. Debugging Programs of the ILE RPG Programmer's Guide.
- Section Displaying Variables and Expressions in Chapter 7. Debugging a Program of the ILE COBOL Programmer's Guide.
%SUBSTR
The %SUBSTR debug BIF allows you to substring a string variable. The syntax for the %SUBSTR BIF is as follows:
%SUBSTR(identifier start-element number-of-elements) |
The first parameter, identifier, must be a string identifier; the second parameter, start-element, is the starting position; and the third parameter, number-of-elements, is the number of single-byte or double-byte characters. In addition, the second and third parameters must be positive integer literals. Parameters are delimited by one or more spaces.
%SUBSTR can be used to do the following:
- Evaluate a substring of a string identifier.
- Assign a portion of a string identifier.
- Use a portion of a string identifier in the WHEN expression of a conditional break debug command.
- Use a portion of a string identifier in a WATCH expression of the WATCH debug command.
Debug the following RPG program:
d ptr s * inz(%addr(a)) d a s d b s d /free *inlr = *on; // Line 6 /end-free |
In the debug session, when the program is stopped at line 6, enter the following debug commands:
> EVAL %substr(a 1 2) %SUBSTR(A 1 2) = 'aa' > EVAL %substr(b 1 2) %SUBSTR(B 1 2) = 'bb' > EVAL %substr(a 1 2)=%substr(b 1 2) %SUBSTR(A 1 2)=%SUBSTR(B 1 2) = 'bb' > EVAL a A = 'bbaaa ' > BREAK 10 when %substr(a 1 2)='cc' > WATCH %substr(a 1 2) |
Now, the Display Watch display might look like this:
Display Watch
Watch Number . . . : 1 Address . . . . . : E720569891071378 Length . . . . . . : 2 Number of Hits . . : 0
Scope when watch was set: Program/Library/Type: A171 LSBIN *PGM
Module . : A171 Procedure: A171 Variable : %SUBSTR(A 1 2)
F12=Cancel |
%ADDR
The %ADDR debug BIF can be used to retrieve the address of a variable for display or assign the address of a variable to a pointer variable. See the following RPG example:
d info_t ds qualified d a d b 10i 0 d i1 ds likeds(info_t) d i2 ds likeds(info_t) d ptr s * d i ds likeds(info_t) d based(ptr)
/free i1.a = 'A'; i1.b = 1; i2.a = 'B'; i2.b = 2;
*inlr = *on; // Line 16 /end-free |
In the debug session, when the program is stopped at a breakpoint at line 16, issue the following command. The output might be as shown:
> EVAL i1 I1.A = 'A ' I1.B = 1 > EVAL i2 I2.A = 'B ' I2.B = 2 > EVAL ptr = %addr(i1) PTR = %ADDR(I1) = SPP:E720569891077310 > EVAL i I.A = 'A ' I.B = 1 |
%INDEX
The %INDEX debug BIF can be used to change the index of a table or multiple-occurrence data structure. See the following RPG example:
d x ds occurs(5) d c d n 10i 0
c 1 occur x c eval c = 'one' c eval n = 1 c 2 occur x c eval c = 'two' c eval n = 2 c c seton lr |
In the debug session, when the program is stopped at the SETON LR line, enter the following debug commands:
> EVAL c C = 'two ' > EVAL n N = 2 > EVAL x=%index(1) X=%INDEX(1) = 1 > EVAL c C = 'one ' > EVAL n N = 1 |
%VAR
The %VAR debug BIF identifies the specified parameter as a variable. The syntax is as follows:
%VAR(identifier) |
It is used to tell the debugger that identifier is not a debug keyword. If you were trying to debug the following RPG program, you would need the %VAR BIF quite a lot.
d eval s d break s d watch s d pgm s d step s d clear s d qual s /free *inlr = *on; // Line 9 /end-free |
In the debug session, when the program is stopped at line 9, enter the following debug commands:
> EVAL eval Syntax error occurred. > EVAL break Syntax error occurred. > EVAL watch Syntax error occurred. > EVAL pgm Syntax error occurred. > EVAL step Syntax error occurred. > EVAL clear Syntax error occurred. > EVAL qual Syntax error occurred. > EVAL %var(eval) EVAL = ' ' |
%LOCALVARS
An EVAL %LOCALVARS debug command will result in the evaluation of every variable originating in the current scope. See the following Java example.
/// @file ahya.java public class ahya { public static final String _stat = "When and where"; public static void main(String[] args) { String a = "abc"; int b = 456; byte[] c = new byte[] {1, 2, 3};
System.out.println("AH YA?! .... ..."); // Line: 9 } } |
In the debug session, when the program is stopped at a breakpoint at line 9, issue the EVAL %localvars command. The output might be as follows:
> EVAL %localvars args = ARR:DF a = abc b = 456 c = ARR:DF |
Go Forth and Debug
I hope these debug BIFs are as helpful to you as they have been to me.
LATEST COMMENTS
MC Press Online