Title: Coming%20to%20Grips%20with%20Pointers%20and%20User%20Spaces%20in%20RPG%20IV
1Coming to Grips with Pointers and User Spaces in
RPG IV
ComCon 5, Oakton Court Ballybrack Co.
Dublin Ireland
Phone 353 1 282 6230 e-Mail tuohyp_at_comconadviso
r.com Web www.ComConAdvisor.com
Paul Tuohy
2Paul Tuohy
Paul Tuohy has worked in the development of IBM
Midrange applications for 25 years. He has been
IT manager for Kodak Ireland Ltd. and technical
director of Precision Software Ltd. and is
currently CEO of ComCon, a midrange consultancy
company based in Dublin, Ireland. He has been
lecturing at IBM Learning Services for the past
16 years. Paul is the author of the book
Re-engineering RPG Legacy Applications and is one
of the quoted industry experts in the IBM Redbook
"Who knew you could do that with RPG IV?" He
writes regular articles for iSeries 400 Experts
Journal (www.iseries400experts.com) and
Search400.com (www.search400.com). He is also an
award-winning speaker at U.S. COMMON conferences.
3Agenda
- What are pointers?
- How to use pointers.
- Why use pointers?
- Allocating record layouts in trigger programs
- Used with C functions
- Dynamic memory allocation
- User spaces
- Procedure pointers
4What is a pointer?
Basing pointers are used to locate the storage
for based variables. The storage is accessed by
defining a field, array, or data structure as
based on a particular basing pointer variable and
setting the basing pointer variable to point to
the required storage location. From
WebSphere(R) Development Studio ILE RPG Reference
- Basing Pointer Data Type
5What is a pointer?
- A pointer is a field that contains a memory
address. - Assuming that Name is a 30-character field,
translate the eval operation as "from the address
of Name, blank out the next thirty characters". - If we could control "the address of Name", we
would have a pointer!
Program Storage
Eval Name Blanks
6Pointers have always been used in . . .
- Pointers are not new to RPG -- we just have not
been able to manipulate them. - Multiple Occurrence Data Structures
- The occurrence of the database is based on an
offset of the address of the data structure. - DS Address of MODS (Length of DS
(Occurrence 1)) - Parameter Lists
- When passing a parameter the actual parameter
field is not passed, but a pointer containing the
address of the parameter field. This address is
then used as the basis for the parameter field in
the called program. - Lets take a closer look at parameters!
7Parameter lists
Storage of Called Program
Storage of Calling Program
I
J
K
Z
X
Y
BProgram(I J K)
ltltltltltltltltltltltltltltltltltltltltltltltltltltltltltltltltltgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgt
gtgtgtgtgtgtgtgtgtgtgtgtgtgt D BProgram PI
D X 15 D
Y 10 D Z
5
8The problem with pointers
Storage of Called Program
Storage of Calling Program
I
J
K
Y
Z
X
BProgram(I J K) ltltltltltltltltltltltltltltltltltltltltltltltltltlt
ltltltltltltltgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgt
D BProgram PI
D X
15 D Y 10
D Z 15 Z
Blanks
Oops!
9The problem with pointers
Storage of Called Program
Storage of Calling Program
I
J
K
Y
Z
X
BProgram(I J K) ltltltltltltltltltltltltltltltltltltltltltltltltltlt
ltltltltltltltgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgtgt
D BProgram PI
D X
15 D Y 10
D Z 15 Z
Blanks
Oops!
10Better get used to . . .
Message ID . . . . . . RNQ0222
Date sent . . .
. . . 13/09/02 Time sent . . . . . .
114031
Message . . . . Pointer or parameter error (C
G D F).
Cause . . . . . RPG procedure
BASICF in program SPACE01/BASICF at
statement 51 had an error due to a pointer not
being correctly set. The cause of the
error is most likely one of the following
A basing pointer was not
set.
A procedure pointer was not set.
The pointer
was set, but the object it referenced has been
destroyed. A parameter was not passed
to the program containing the procedure.
A parameter was not passed to the procedure by
its caller within the program. A
pointer offset was greater than the size of the
space the pointer was pointing to.
11Remember
When you are using pointers . . .
You are indiscriminately playing with
memory. You must be careful.
12Pointers in RPG IV
- We can now define pointer data types.
- Also, we can define fields, arrays and data
structures whose "positioning" in memory is based
on the value of a pointer. - In other words, when a field is based on a
pointer, memory is not allocated for the field
when the program loads but is allocated
dynamically based on the value of the pointer
field. - If a pointer is used but not defined, the
compiler will automatically define it so watch
out for spelling!
DNameETDsFromTo/LIDc.Keywords
D pPointer S
D BasedField S
20 Based(pPointer)
13Pointers at work
Storage of Program
- pPointer Null
1
BasedField
14Pointers at work
Storage of Program
- pPointer Null
- pPointer An Address
- pPointer Another Address
- pPointer Yet Another Address
- pPointer Addr(BlueField)
5
4
1
BasedField
3
2
15Using pointers
- Pointers have a data type of '' and you don't
define a length. - Actually uses 16 bytes of storage.
- Fields are "subject" to a pointer using the Based
Keyword. - The value of a pointer is set using the Addr
Built-in Function.
DNameETDsFromTo/LIDc.Keywords
D pPointer S
Inz(Addr(Text1))
D BasedField
S 5 Based(pPointer)
"Overlays" Text1
D MyDS DS D Text1
4 Inz('ABCD') D
Text2 4 Inz('WXYZ')
C Eval
pPointer Addr(Text2) Now, BasedField
"Overlays" Text2
16Why use pointers?
When allocating record layouts in trigger
programs. Used with C functions. Dynamic
memory allocation. Used with many APIs - e.g.,
user spaces As a way of calling procedures.
17Standard trigger buffer
D TriggerBuffer DS
Qualified D FileName 10
D LibraryName 10 D
MemberName 10 D Event
1 D Time
1 D CommitLock
1 D Fill01 3
D CCSID 10I 0 D RRN
10I 0 D Fill02
4 D OldOffset
10I 0 D OldLength
10I 0 D OldNullOff 10I 0
D OldNullLen 10I 0 D
NewOffset 10I 0 D
NewLength 10I 0 D
NewNullOff 10I 0 D
NewNullLen 10I 0 Before and
After Images
Offset to Original Record
Offset to New Record
18Accessing the Trigger Buffer
The SUBST Built-in Function can be used to copy
the contents of the Trigger Buffer to the
relevent externally described data structures.
D OldFile E DS
ExtName(FileName) D
Qualified D
NewFile E DS
ExtName(FileName)
OldFile SubST(TriggerBuffer
TriggerBuffer.OldOffset1
TriggerBuffer.OldLength)
NewFile SubST(TriggerBuffer
TriggerBuffer.NewOffset1
TriggerBuffer.NewLength)
19Using pointers
- The two externally described data structures can
be mapped onto the relevent portions of the
Trigger Buffer by basing them on pointers and
setting the values of the pointers to be the
address of the buffer the relevent offset. - No data is copied!!!
D OldFile E DS
ExtName(FileName) D
Qualified
D
Based(OldPtr) D NewFile
E DS ExtName(FileName)
D
Based(NewPtr)
D OldPtr S
D NewPtr S
OldPtr
Addr(TriggerBuffer) TriggerBuffer.OldOffset
NewPtr Addr(TriggerBuffer)
TriggerBuffer.NewOffset
20C functions
- Many C functions require pointers as parameters
and return a pointer. - Example The strtok (string tokenize) function.
- This function breaks up a string into "tokens
- Refer to the Redbook "Who Knew You Could Do That
With RPG IV?" for detailed details. - C functions are not easy to interpret.
- Function names are case sensitive.
- Refer to Barbara Morris "Converting from C
prototypes to RPG prototypes" - http//www.opensource400.org/callc.html.
D GetToken Pr
ExtProc('strtok') D pString
Value Options(String) D pDelimiters
Value Options(String)
21Other C functions
- qsort and bsearch can be used as more powerful
versions of SORTA and LOOKUP. - Refer to the Redbook "Who Knew You Could Do That
With RPG IV?" for details and examples.
D SortIt PR
ExtProc('qsort') D DataStart
Value D Elements
10U 0 Value D Size
10U 0 Value D
CompFunc ProcPtr Value
D FindIt PR
ExtProc('bsearch') D LookFor
Value D DataStart
Value D
Elements 10U 0 Value
D Size 10U 0 Value
D CompFunc
ProcPtr Value
22Dynamic Memory Allocation
- Dynamic Memory Allocation is useful if you are
unsure how much space will be required by a
variable at run time. - Alloc - allocates the required amount of
storage. - ReAlloc - reallocates the current storage to a
new size - DeAlloc - frees the allocated storage
- N.B. Allocated storage should be freed.
D Array S 10
Based(pArray) Dim(10000) D pArray S
D MaxElem
S 10U 0 Inz(10)
/Free
pArray Alloc(Size(Array)
MaxElem) MaxElem
MaxElem 10
pArray ReAlloc(pArray Size(Array)
MaxElem) DeAlloc pArray
InLR On
/End-Free
23Example of Dynamic Memory Allocation
This example shows the use of dynamic memory
allocation for an array that may have more then
32767 elements. The array is repositioned every
32767 elements.
D PathArray S Dim(32767)
D
Based(pPathArray) // Allocate memory for
the array of pointers
pPathArray alloc((size(pDataPtr)
NumberInList))
// Build the array of pointers to the path
entries for i 1 to
NumberInList
j j 1
If (j gt
Elem(PathArray))
pPathArray pPathArray
(Size(pDataPtr) Elem(PathArray))
j 1
EndIf
PathArray(j)
pDataPtr
24Example of Dynamic Memory Allocation
1. NumberInList 70,000
PathArray
Size(PDataPtr) 16
2. PathArray
5. PathArray
4. PathArray
lt 1 ---------------- 524,272 gt
lt 524,273------------ 1,048,544 gt
lt 1,048,545 --------- 1,572,816 gt
pPathArray address of allocated memory
3. Program loops through 32767 elements of
PathArray
4. Move the position of the array
pPathArray pPathArray
(Size(pDataPtr) Elem(PathArray))
5. etc.
25What is a user space?
- Contrary to popular belief, a user space is not
what you find between a user's ears. - It is
- An object on the iSeries (I5, AS/400) with an
object type of USRSPC. - It is simply a stream of bytes that you can
access directly from within a program. - A user space effectively becomes a field in your
program. - More precisely (even though it might sound
extremely vague), a user space is whatever you
want it to be. - The advantages to employing a user space lie in
speed of access and the fact that data can be
shared between programs without having to perform
I/O!!!!
26User space APIs
- You must use APIs to create user spaces and
manipulate their contents. - In fact, the only user space command you will
find is the Delete User Space (DLTUSRSPC)
command. - Incorporating a user space into an application
involves two user space APIs - Create User Space (QUSCRTUS).
- Retrieve Pointer to User Space (QUSPTRUS).
27Create user space
The QUSCRTUS API is called to create a user space
D CreateSpace PR
ExtPgm('QUSCRTUS') D UserSpaceName
20 Const D Attribute 10
Const D Size 10I 0
Const D Initial 1
Const D Authority 10
Const D Text 50 Const
Optional Parameter Group 1 D Replace
10 Const Options(NOPASS) D
ErrorCode Const
Options(NOPASS) D
Like(StandardAPIError) Optional Parameter
Group 2 D Domain 10
Const Options(NOPASS) Optional Parameter
Group 3 D TransferSize 10I 0
Const Options(NOPASS) D OptimumAlign
1 Const Options(NOPASS)
CreateSpace(UserSpace'DTA'10000
X'00''ALL'Text)
28Create user space
- The parameters used on the QUSCRTUS API are
- UserSpace The name and library of the user
space. - Attribute The attribute parameter is any name
you wish it to be. - Size The initial length of the user space in
bytes. - Initial The initial value used to fill the user
space. - Authority Public authority to the user space.
- Text The text description.
DNameETDsFromTo/LIDc.Keywords
D UserSpace S
20 Inz('USERSPACE CURLIB') D Attribute
S 10 Inz('DTA')
D Size S 10I 0 Inz(10000)
D Initial S
1 Inz(X'00') D Authority
S 10 Inz('ALL')
D Text S 50
Inz('Sample User Space')
29Fill user space
- We map a variable in the program onto the user
space. - If we change the variable, we are also changing
the user space. - We map the CATSPACE array onto the CATEGORY user
space. - Each element of CATSPACE will contain a record
from the Category file.
D CatData E DS
ExtName(Category) D NumRows S
5I 0 Based(pNumRows) D pNumRows S
D CatSpace S
Dim(32767) Based(pCatSpace) D
Like(CatData) D pCatSpace S
30Fill user space
- The call to QUSPTRUS API returns a value in the
pNumRows field. - This value reflects the address of the requested
user space. - NumRows now overlays the first two bytes of the
user space. - pCatSpace is equal to the value of pNumRows 2.
- The array CatSpace overlays the user space
starting at position 3.
D GetSpace PR
ExtPgm('QUSPTRUS') D SpaceName
20 Const D pSpacePtr
Optional Parameter Group D ErrorCode
Const Options(NOPASS) D
Like(StandardAPIError)
D UserSpace S 20
Inz('CATEGORY LIBL ')
GetSpace(SpaceNamepNumRows) pCatSpace
pNumRows Size(NumRows)
31Fill user space
We have a loop that fills the user space by
reading a record from the category file and
adding it to the next element of the array.
NumRows 0 Read Category
DoW Not EOF(Category) NumRows
NumRows 1 CatSpace(NumRows)
CatData Read Category
EndDo
32Using the user space
- This example shows a subfile being loaded from a
user space instead of a file. - The program DOES NOT contain a F spec for the
file. - Again, we define the array based on a pointer.
D CatData E DS
ExtName(Category) D NumRows S
5I 0 Based(pNumRows) D pNumRows S
D CatSpace S
Dim(32767) Based(pCatSpace) D
Like(CatData) D pCatSpace S
33Using the user space
- The call to the QUSPTRUS API maps the array to
the user space. - The call to QUSPTRUS is usually issued in the
INZSR subroutine, since it needs to be done only
when the program is first loaded.
// Obtain pointers to the user space
GetSpace(SpaceNamepNumRows) pCatSpace
pNumRows Size(NumRows)
34Using the user space
- The subfile is now loaded from the array as
opposed to the category file. - The relative record number (RRN) for the subfile
doubles as the element pointer for the array. - Each iteration of the For loop places the next
element of the array in the next subfile record. - The same field names are used in the subfile
record format and the CatData data structure.
For RRN 1 To NumRows CatData
CatSpace(RRN)
Write SubRec
EndFor
35APIs and user spaces
- User spaces are used with many of the
system-supplied APIs, especially any of the "list
style" APIs. - Data is "output" to a user space and your program
pages through the user space. - This is an example of using the List Objects API
D ListObjects PR
ExtPgm('QUSLOBJ') D UserSpace
20 Const D Format 8
Const D Objects 20
Const D ObjectType 10
Const D ErrorCode
Like(StandardAPIError)
CreateSpace('MYSPACE QTEMP
''DTA'10000 X'00''ALL'
'All Objects in MYLIB')
ListObjects('MYSPACE QTEMP ''OBJL0100'
'ALL MYLIB
''ALL 'APIError)
36API documentation
The user space APIs are documented in the
Information Center under Programming-gtAPIs-gtAPIs
by Category-gtObject APIs. The use of user
spaces for other APIs is detailed in the
documentation of the individual APIs (like
QUSLOBJ)
37Categories of APIs
Each has its own section, so pick a topic and
while away a weekend in perusal.
Backup and Recovery APIs
Office APIs
Client Management Support APIs
Operational Assistant APIs
Communications APIs
Performance Collector APIs
Configuration APIs
Print APIs
Debugger APIs
Problem Management APIs
Dynamic Screen Manager APIs
Program and CL Command APIs
Edit Function APIs
Registration Facility APIs
File APIs
Remote Procedure Call APIs
Hardware Resource APIs
Security APIs
Hierarchical File System APIs
Server Support APIs
High-Level Language APIs
Software Product APIs
ILE CEE APIs
UNIX-Type APIs
Journal and Commit APIs
User Interface APIs
Message Handling APIs
Virtual Terminal APIs
National Language Support APIs
Work Management APIs
Network Management APIs
Work Station Support APIs
Object APIs
Miscellaneous APIs
38Procedure pointers
- Procedure pointers point to the address of a
procedure - Identified by the ProcPtr Keyword
- The ExtProc keyword has the name of the pointer
- Value set using the PAddr BIF.
- Watch those quotes!
- Watch case!
- Parameters should be the same for all procedures.
No check it is up to you.
D pGenProc S ProcPtr D
GenProc PR 30
ExtProc(pGenProc) pGenProc
PAddr('Proc01') Returned GenProc()
pGenProc PAddr('AnotherProcAltogether')
Returned GenProc()
39Any clearer now?
Basing pointers are used to locate the storage
for based variables. The storage is accessed by
defining a field, array, or data structure as
based on a particular basing pointer variable and
setting the basing pointer variable to point to
the required storage location. From
WebSphere(R) Development Studio ILE RPG Reference
- Basing Pointer Data Type
40Check out the RPG IV Redbook
- Available now - SG24-5402
- Go to www.redbooks.ibm.com
- You can read it online, download the PDF file, or
order a hardcopy - Includes worked examples of
- TCP/IP sockets
- CGI programming
- Using the C function library
- ILE error handling
- and much more
Who Knew You Could Do That with RPG IV? A
Sorcerer's Guide to System Access and More
SG24-5402
International Technical Support
Organization Rochester, Minnesota
41Or check out
- Available at
- www.mcpressonline.com
- www.midrange.com
- www.amazon.com
- ISBN 1-58347-006-9
42Summary
- Pointers open new possibilities.
- Pointers can be dangerous.
- Treat them with respect.
- They are a neccessity for many C functions.
- They are a neccessity for many APIs.
- User spaces are great!