29
Fri, Nov
0 New Articles

Pointers in ILE RPG

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

Brief: In RPG/400, retrieving data from a user space requires multiple external

API calls, which impacts performance. Now, with ILE RPG pointers, programs can

access this kind of data in a much more efficient manner. This article explains

how you can use ILE RPG pointers to retrieve data from a user space faster than

ever before.

Among the many enhancements made to RPG in V3R1 is support for a new data type

called a pointer. Pointers provide RPG programmers with an efficient new way to

access data. While you probably won't use pointers in every application you

write, they can be extremely useful with certain types of low-level

programming, such as retrieving data from a user space.

You may be familiar with the concept of pointers if you've used other

programming languages, such as C, but there are some slight differences in the

implementation of pointers in RPG. However, even RPG programmers who have never

used pointers before now have the ability to start taking advantage of them. In

this article, I'll explain some of the concepts of pointers, discuss the RPG

implementation, and show you an example of how to use them in an RPG

application.

Pointer Concepts

The simple definition of a pointer is a variable that contains the address of

another variable. A pointer doesn't tell you what you'll find at an address

location; it tells you only where to find it. For this reason, pointers are

often referred to as addresses.

A simple analogy for a pointer is a street address. A street address doesn't

tell you who lives in a particular house, but it does tell you where to find

the house. Using the address, you can determine who lives there by going to the

house and knocking on the door. Pointers work the same way. Since a pointer

stores the address of a particular piece of data, you can use that address to

directly access the data at that address location. Pointers provide you with a

convenient and efficient way to access the data in a user space.

Until V3R1, RPG hasn't had pointers, but OS/400 uses them extensively. One

place in OS/400 where pointers are evident is in parameter passing. When

parameters are passed between RPG or CL programs, they are actually passed as

pointers, not data. I, like many programmers, found this out the hard way. Have

you ever accidentally coded a parameter with the wrong size in the receiving

program and ended up with garbage in an adjacent parameter? That happens

because parameters are passed as pointers. The receiving program goes to the

address of each parameter and processes whatever data it finds there. If you

were to look at the memory locations for the parameters, you would find that

they are stored one right after the other. So if one of the parameters is

defined too large, the program will process multiple parameter values as if

they were a single parameter. Parameters can easily become corrupt if you

aren't careful about matching their sizes.

Pointer Usage

You probably won't want to use pointers in every application you write. The

most likely candidates are programs that use the list application programming

interfaces (APIs). The list APIs produce lists of dataùsuch as fields, members,

and objectsùinto a user space. 1 shows some common list APIs. Using

and objectsùinto a user space. Figure 1 shows some common list APIs. Using

pointers facilitates the process of extracting the list data out of the user

space.

Before I discuss how to extract data from a user space using pointers, let's

first look at how the list APIs organize the data in a user space. 2

first look at how the list APIs organize the data in a user space. Figure 2

shows the general layout of this type of data. As you can see, the user space

is broken down into four sections: generic header, input parameter, header, and

list data. The generic header section is always found at the beginning of the

user space and contains (among other things) the addresses of the other three

sections.

The input parameter section contains a copy of the parameters passed to the

list API. This section is not usually needed in the calling application program

and is therefore generally not extracted from the user space. The header

section (not to be confused with the generic header) contains information

related to the list. For example, the List Fields API places information such

as the file type, record format, and record length in this section. The list

data section is where the actual list is stored. This section is broken down

into individual entries similar to records in a file.

Prior to the existence of pointers in RPG, the common technique to extract data

from a user space was to call the Retrieve User Space (QUSRTVUS) API. This API

needed to be called repeatedly to retrieve the individual sections of the user

space as well as each entry in the list data section. The multiple external API

calls slowed down the performance of the application. In addition, the Retrieve

User Space API copied the data from the user space to a variable in the

program.

RPG programs can now use pointers instead. Using pointers eliminates the need

to perform repetitive external API calls and has the added benefit of being

able to go to the memory location where the data exists and process it directly

without having to first copy it into a variable.

An Example

Let's look at an example of an application that uses pointers. I chose the List

Fields (QUSLFLD) API, but I could have chosen any list API to illustrate this

technique. The List Fields API produces a list of fields from a database file

and places them into a user space. In this example, I've written a command

called List Fields (LSTFLD). This command accepts a database file as a

parameter and produces a screen similar to the one shown in 3. This

parameter and produces a screen similar to the one shown in Figure 3. This

screen lists the fields in the selected file along with their attributes and

text.

The example consists of typical components of any utility applicationùa command

(4), a CL program (5), a display file (6), and an ILE RPG

(Figure 4), a CL program (Figure 5), a display file (Figure 6), and an ILE RPG

program (7). Since the focus of this article is on pointers, I'll

program (Figure 7). Since the focus of this article is on pointers, I'll

discuss only the RPG program. I've supplied the other components so you can use

this application as a starting point for a similar application using one of the

other list APIs. (You can download this code by calling MC-BBS.)

Using pointers in an RPG program requires several pieces of code. The first is

the data definition of the pointer, the second is a data structure or

standalone field containing the BASED keyword, the third is a call to the

Retrieve Pointer to User Space (QUSPTRUS) API, and the fourth is the use of the

address (%ADDR) built-in function. (For more information on the ILE RPG

techniques, refer to the related reading listed at the beginning of this

article.)

At Label A in 7, you can see the data definition of three pointers:

At Label A in Figure 7, you can see the data definition of three pointers:

SpacePtr, HeaderPtr, and ListPtr. In ILE RPG, you define pointers by specifying

an asterisk as the data type (position 40) on a data specification. In this

example, I've coded these pointers as standalone fields as designated by the S

in position 24. You can also code pointers as subfields of a data structure.

Label B shows three data structures: UserSpace, Header, and List. All three

data structures are based on (linked to) a pointer variable that holds the

address of an area of memory. In this case, the area of memory will contain a

portion of a user space. The BASED keyword provides the link. Notice that the

data structure UserSpace is based on pointer variable SpacePtr, Header is based

on HeaderPtr, and List is based on ListPtr. When a valid address is assigned to

one of the pointer variables, the data structure based on the pointer variable

overlays the data contained at that memory address. The data structure and its

subfields can then be used to reference the data beginning at the location

contained in the pointer variable. Before any of the fields in the data

structure can be used, the basing pointer must be assigned a valid address;

otherwise, an exception error is generated.

At label C in 7, the program calls the Retrieve Pointer to User Space

At label C in Figure 7, the program calls the Retrieve Pointer to User Space

API. This API has only two parametersùthe name of a user space (SpaceName) and

the name of a pointer (SpacePtr). After the call to this API, the pointer is

set to the address of the beginning of the user space. This essentially

overlays the data structure on top of the user space data since they both now

begin at the same storage address. All of the subfields of data structure

UserSpace are then available to the program. Among these subfields is the

definition of a large array called Data, which is composed of single byte

elements. As you'll see, this array is used to retrieve the address of the

other sections of the user space.

The code at Label D in 7 shows the use of the %ADDR built-in function.

The code at Label D in Figure 7 shows the use of the %ADDR built-in function.

This function retrieves the address of a storage location and places it into a

pointer. Here, the function is used to retrieve the address of the beginning of

the header section of the user space. The Data array is used to locate the

beginning byte of the header section. That address is placed into the pointer

called HeaderPtr. This overlays the Header data structure on top of the header

section of the user space since they now share the same storage address. Since

the Header data structure is based on this pointer, all of the subfields become

available.

The program then drops into a loop to retrieve each of the entries in the list

data section. During the first iteration, the statement at Label E in 7

data section. During the first iteration, the statement at Label E in Figure 7

retrieves the address of the first element of the list data section. The Data

array is used to locate the address of the beginning byte of the entry. That

address is placed into the pointer called ListPtr (the based-on pointer for the

List data structure). The List data structure now overlays the first entry in

the list data section of the user space as illustrated in 8 (page 112).

the list data section of the user space as illustrated in Figure 8 (page 112).

Before the next iteration of the loop, the offset within the Data array is

incremented by the size of the list entry (see Label F in 7). The new

incremented by the size of the list entry (see Label F in Figure 7). The new

offset value allows the program to retrieve the address of the next entry (see

Label E in 7). The loop is repeated until all of the entries in the list

Label E in Figure 7). The loop is repeated until all of the entries in the list

have been processed.

One Final Point

As you've seen, pointers can be used effectively in ILE RPG to process data

from a user space. This example could have been simplified, though, if IBM had

taken a more traditional approach to pointer implementation in RPG. In other

languages, such as C, it's common to simply increment a pointer to get to

another storage location. Unfortunately, IBM doesn't allow pointer math in ILE

RPG. This restriction is the reason for the large Data array in this example.

By not allowing pointer math, it often becomes necessary to find alternative

methods of retrieving address locations. Perhaps the next release of RPG will

remove this limitation. Until then, this method is still a big improvement over

the method we used prior to having pointers in RPG.

Robin Klima is a senior technical editor for Midrange Computing.

Reference

ILE RPG/400 Reference (SC09-1526-00, CD-ROM QBKAQE00).

Related Reading

An Introduction to

ILE RPG: Part 1

March 1994

An Introduction to

ILE RPG: Part 2

April 1994

An Introduction to

ILE RPG: Part 3

May 1994

An Introduction to

ILE RPG: Part 4

June 1994

An Introduction to

ILE RPG: Part 5

July 1994


Pointers in ILE RPG

Figure 1Common List APIs

 QSRLSAVF List Save Files QDCLCFGD List Configuration Descriptions QUSLMBR List Database File Members QDBLDBR List Database Relations QUSLFLD List Fields QUSLRCD List Record Formats QMHLJOBL List Job Log Messages QMHLSTM List Nonprogram Messages QUSLOBJ List Objects QEZLSGNU List Signed-On Users QPMLPFRD List Performance Data QBNLPGMI List ILE Program Information QBNLSPGM List Service Program Information QSYLAUTU List Authorized Users QSYLATLO List Objects Secured by an Authorization List QSYLOBJP List Objects that Adopt Owner Authority QSYLOBJA List Objects a User is Authorized To QSYLUSRA List Users Authorized to an Object QUSLSPL List Spooled Files QWCLASBS List Active Subsystems QUSLJOB List Jobs QWCLSCDE List Job Schedule Entries QWCLOBJL List Object Locks QWDLSJBQ List Subsystem Job Queues 
Pointers in ILE RPG

Figure 2User Space Organization for List APIs

 UNABLE TO REPRODUCE GRAPHICS 
Pointers in ILE RPG

Figure 3List Fields Screen

 UNABLE TO REPRODUCE GRAPHICS 
Pointers in ILE RPG

Figure 4The LSTFLD Command

 /*===============================================================*/ /* To compile: */ /* */ /* CRTCMD CMD(XXX/LSTFLD) PGM(XXX/FLD001CL) + */ /* SRCFILE(XXX/QCMDSRC) */ /* */ /*===============================================================*/ CMD PROMPT('List Fields') PARM KWD(FILE) TYPE(QUAL) MIN(1) PROMPT('File') PARM KWD(RCDFMT) TYPE(*NAME) DFT(*FIRST) + SPCVAL((*FIRST)) PROMPT('Record format') QUAL: QUAL TYPE(*NAME) LEN(10) QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + SPCVAL((*LIBL)) PROMPT('Library') 
Pointers in ILE RPG

Figure 5CL Program FLD001CL

 /*===============================================================*/ /* To compile: */ /* */ /* CRTCLPGM PGM(XXX/FLD001CL) SRCFILE(XXX/QCLSRC) */ /* */ /*===============================================================*/ PGM PARM(&FILE &RCDFMT) DCL VAR(&FILE) TYPE(*CHAR) LEN(20) DCL VAR(&RCDFMT) TYPE(*CHAR) LEN(10) DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) /* Send all errors to error handling routine */ MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) /* Create user space if necessary */ CHKOBJ OBJ(QTEMP/FLD001US) OBJTYPE(*USRSPC) MONMSG MSGID(CPF9801) EXEC(CALL PGM(QUSCRTUS) + PARM('FLD001US QTEMP' ' ' 32767 ' ' + '*ALL' 'User space for LSTFLD command')) /* Call the List Fields API */ CALL PGM(QUSLFLD) PARM('FLD001US QTEMP' + 'FLDL0100' &FILE &RCDFMT '0') /* Call program to display fields */ CALL PGM(FLD001RG) /* Branch around error handling routine */ GOTO CMDLBL(ENDPGM) /* Error handling routine */ ERROR: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE) ENDPGM: ENDPGM 
Pointers in ILE RPG

Figure 6Display File FLD001DF

 *=============================================================== * To compile: * * CRTDSPF FILE(XXX/FLD001DF) SRCFILE(XXX/QDDSSRC) * *=============================================================== *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 A DSPSIZ(24 80 *DS3) A PRINT A CA03(03) A CA12(12) A R DSPSFL01 SFL A FLDNAME 10A O 7 2 A FLDLENGTH 5Y 0O 7 13EDTCDE(3) A FLDDECPOS 3Y 0O 7 19EDTCDE(3) A N60 DSPATR(ND) A DATATYPE 1 O 7 26 A TEXT 50A O 7 31 A R DSPCTL01 SFLCTL(DSPSFL01) A SFLSIZ(0016) A SFLPAG(0015) A OVERLAY A SFLDSP A SFLDSPCTL A N03 SFLEND(*MORE) A 1 35'List Fields' A DSPATR(HI) A 3 2'File . . . :' A FILENAME 10A O 3 16 A 3 29'Record format . . :' A RCDFORMAT 10A O 3 50 A 4 2'Library . . :' A LIBRNAME 10A O 4 16 A 4 29'File type . . . . :' A FILETYPE 10A O 4 50 A 6 2'Field Len' A DSPATR(HI) A 6 20'Dec Type Text' A DSPATR(HI) A R DSPRCD01 A 23 2'F3=Exit F12=Cancel' A COLOR(BLU) *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 
Pointers in ILE RPG

Figure 7ILE RPG Program FLD001RG

 *========================================================================= * To compile: * * CRTBNDRPG PGM(XXX/FLD001RG) SRCFILE(XXX/QRPGLESRC) * *========================================================================= *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 FFLD001DF CF E WORKSTN SFILE(DSPSFL01:Recno) D SpacePtr S * D HeaderPtr S * D ListPtr S * D UserSpace DS BASED(SpacePtr) D Data 1 DIM(32767) D OffSetHdr 117 120B 0 D OffSetLst 125 128B 0 D NumLstEnt 133 136B 0 D EntrySize 137 140B 0 D Header DS BASED(HeaderPtr) D FileName 1 10 D LibrName 11 20 D FileType 21 30 D RcdFormat 31 40 D List DS BASED(ListPtr) D FldName 1 10 D DataType 11 11 D Length 21 24B 0 D Digits 25 28B 0 D DecPos 29 32B 0 D Text 33 82 D SpaceName S 20 INZ('FLD001US QTEMP') D Recno S 5 0 * Retrieve pointer to user space C CALL 'QUSPTRUS' C PARM SpaceName C PARM SpacePtr * Get heading information C EVAL HeaderPtr = %ADDR(Data(OffSetHdr + 1)) * Repeat for each entry in the List Data section C DO NumLstEnt * Get detail information C EVAL ListPtr = %ADDR(Data(OffSetLst + 1)) * Load field Length and Decimal positions C IF Digits = 0 C EVAL FldLength = Length C EVAL *IN60 = *OFF C ELSE C EVAL FldLength = Digits C EVAL FldDecPos = DecPos C EVAL *IN60 = *ON C ENDIF * Write subfile record C EVAL Recno = Recno + 1 C WRITE DSPSFL01 * Get location of next entry C EVAL OffSetLst = OffSetLst + EntrySize C ENDDO * Write screen C WRITE DSPRCD01 C EXFMT DSPCTL01 C EVAL *INLR = *ON *. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 
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: