How To Print a Pointer Value
November 3, 2010 Ted Holt
Over the past few months I’ve been working on more articles dealing with the use of pointers in RPG programs. While I was working on my demo programs, I ran into a little snag while verifying that everything was working correctly. Let me tell you what I ran into and how I got around it.
I wanted to double-check the value of all the pointer variables. In the interactive green-screen debugger, which I was using, seeing the value of a pointer is no problem. Place the cursor on the pointer variable name and press F11, or use the EVAL command. The debugger displays the pointer’s value in hexadecimal.
But I don’t always want to step through a program pressing F11. Another favorite technique I use is to write miscellaneous information to a spool file, which I can then read to track the behavior of a program (or module).
So how do you print the hex representation of a pointer? You can’t put the pointer in printer file DDS or O specs. (DDS has no pointer type. Put a pointer in O specs and you’ll get error RNF7601.) I ended up writing a function subprocedure that, given a pointer, builds a string of hex digits, the same string you see when you press F11 in the debugger. I call it PtrToHex (Pointer to Hexadecimal), and that’s what I want to share with you today.
First, here’s the command to create a printer file for the debugging trail.
Of course, you can use QSYSPRT or some other program-described printer file if you prefer.
Here’s a short program that reads QIWS/QCUSTCDT, allocating memory for each record and printing the pointer value in hex for each allocation.
/define debugging H dftactgrp(*no) actgrp(*new) H option(*srcstmt: *nodebugio) FQCustCdt if e disk /if defined(debugging) FDebugPrtf o f 132 printer /endif D gPtr s * /if defined(debugging) D DbgPrtLine ds 132 /endif D PtrToHex pr 16a varying D inPtr * D inSize 5u 0 value options(*nopass) /free *inlr = *on; dow '1'; read qcustcdt; if %eof(); leave; endif; gPtr = %alloc(20); /if defined(debugging) DbgPrtLine = LstNam + ' ' + PtrToHex (gPtr); write DebugPrtf DbgPrtLine; /endif // do other stuff dealloc gPtr; enddo; return; /end-free P PtrToHex b D pi 16a varying D inPtr * D inSize 5u 0 value options(*nopass) D** locals D DS ds D Ptr D Num 20u 0 overlay(DS: 9) D Size s like(inSize) D MaxSize s like(inSize) D MaxPtrAddrSize c const(16) D HexString s 16a varying D Digits s 16a inz('0123456789ABCDEF') D Number s 20u 0 D Rem s 5u 0 D Base c const(16) /free Ptr = inPtr; Number = Num; if Number = *zero; return '*NULL'; endif; select; when %parms()< 2; MaxSize = MaxPtrAddrSize; when inSize = *zero or inSize > MaxPtrAddrSize; MaxSize = MaxPtrAddrSize; other; MaxSize = inSize; endsl; dow Size < MaxSize; Rem = %rem(Number: Base); HexString = %subst(Digits:Rem+1:1) + HexString; Number = %div(Number: Base); Size += 1; enddo; return HexString; /end-free P e
Here’s the report.
Henning E1D840C14A002000 Jones E1D840C14A002030 Vine E1D840C14A002060 Johnson E1D840C14A002090 Tyron E1D840C14A0020C0 Stevens E1D840C14A0020F0 Alison E1D840C14A002120 Doe E1D840C14A002150 Thomas E1D840C14A002180 Williams E1D840C14A0021B0 Lee E1D840C14A0021E0 Abraham E1D840C14A002210
PtrToHex has a second, optional parameter that I didn’t use in this example. When working on the demo programs, I realized that I only needed to see the last four or five hex digits of each pointer value. The second parameter tells the number of low-order digits to print. The default is 16.
Notice that all the debug code is conditioned to the debugging compiler condition. If this were a real program, I would change the /DEFINE to /UNDEFINE before putting this code into production.
If you use pointers in your programming, I hope you find the PtrToHex routine beneficial. If you don’t use pointers, you’re in for some fun! In the near future I will show you what I mean.