Data Structure Parameters in RPG Prototypes
November 15, 2002 Hey, Ted
Hey, Ted:
Back in my RPG III (RPG/400) days, it was easy to define an entry parameter as a data structure.
IPARM1 DS I 1 8 ACTION I 9 10 CODE I 11 120RTNVAL I* C *ENTRY PLIST C PARM PARM1
I used this same method in RPG IV before I started prototyping entry parameters.
D Parm1 DS D Action 1 8 D Code 9 10 D RtnVal 11 12 0 I* C *entry plist C parm Parm1
|
Now I prototype entry parameters, as you described in the November 16, 2001 issue of Midrange Guru. Since the D-spec for a parameter must be blank in positions 24-25, and a data structure must have DS in positions 24-25, how can I include a data structure in a prototyped parameter list?
— Lee
You can do it, Lee. It just takes a little more work. With the help of Barbara Morris of IBM, I have come up with two methods.
The first method is the only one I know of that will work on releases prior to V5R1. Besides declaring the prototype and procedure interface, you must define a data structure and a pointer to the data structure, as in the following code for called program DSPARM.
D DSParm pr extpgm('DSPARM') D Parm1 like(ParmData) D D DSParm pi D Parm1 like(ParmData) D D ParmAddr s * D ParmData ds based(ParmAddr) D Action 8 D Code 2 D RtnVal 2s 0 D C eval ParmAddr = %addr(Parm1) C action dsply C code dsply C rtnval dsply C eval rtnval = 21
You must set the pointer to the address of the parameter so that manipulating the data structure manipulates the parameter. After the eval runs, anything you do to Action, Code, and RtnVal will take place within Parm1.
The second method is for V5R1 or later. Use the LIKEDS keyword to define subfields for the parameter. You will have to qualify references to the parameter’s subfields by preceding each subfield name with the parameter name and a period. You no longer need the pointer.
D ParmData ds D Action 8 D Code 2 D RtnVal 2s 0 D D DSParm pr extpgm('DSPARM') D Parm1 likeds(ParmData) D D DSParm pi D Parm1 likeds(ParmData) D C Parm1.action dsply C Parm1.code dsply C Parm1.rtnval dsply C eval Parm1.rtnval = 21
Data structure ParmData and its three subfields are not equivalent to the parameter. To access the parameter’s data, you must use the qualified subfields.
If you like to place the prototype in a member of its own, as I do, include the data structure in the prototype so that calling programs also have access to the data structure’s definition. Here’s the copy member that contains the prototype.
D ParmData ds D Action 8 D Code 2 D RtnVal 2s 0 D D DSParm pr extpgm('DSPARM') D Parm1 likeds(ParmData) D
Here’s the called program. It receives the data structure as Parm1 and qualifies the subfields.
D/include prototypes,dsparm D D DSParm pi D Parm1 likeds(ParmData) D C Parm1.action dsply C Parm1.code dsply C Parm1.rtnval dsply C eval Parm1.rtnval = 21
Here’s part of a calling program. MyDS is the data structure that is to be passed to the called program. Notice that all references to the subfields are qualified.
D/include prototypes,dsparm D D MyDS ds likeds(ParmData) D C eval MyDS.Action = 'READNEXT' C eval MyDS.Code = '33' C eval MyDS.RtnVal = *zero C callp DSPARM (MyDS) C if MyDS.rtnval = *zero
Data structure ParmData is defined in both the calling and called programs, but is used only as a pattern. The real data is in MyDS in the caller and in Parm1 in the called program.
In this example, the data structure that is being passed from one program to another is only twelve bytes long. However, if it were much longer, you might want to keep the compiler from allocating storage for the pattern data structure in the copy member. To prevent the allocation of storage, use the BASED keyword.
D ParmData ds based(typedefinition_dummy) D Action 8 D Code 2 D RtnVal 2s 0 D D DSParm pr extpgm('DSPARM') D Parm1 likeds(ParmData) D
Data structure ParmData is still defined in both the caller and called programs, but no storage is allocated for ParmData in either.
The use of the BASED keyword also prevents programmers from using the pattern data structure as a working variable. Instead, programmers must define data structures that are to serve as working variables by using the LIKEDS keyword.
Everything to this point works fine if there are no identifiers in the calling program that have the same names as those of the data structure subfields. To avoid such collisions, add the QUALIFIED keyword to the data structure definition in the prototype member.
D ParmData ds based(typedefinition_dummy) D qualified D Action 8 D Code 2 D RtnVal 2s 0 D D DSParm pr extpgm('DSPARMQ') D Parm1 likeds(ParmData) D
Here’s a calling program that declares a variable named ACTION. Because of the QUALIFIED keyword, this program has no trouble distinguishing between ACTION the standalone variable and ACTION the subfield.
D/include prototypes,dsparm D D MyDS ds likeds(ParmData) D Action s 24 D C eval Action = 'Go getum!' C eval MyDS.Action = 'READNEXT' C eval MyDS.Code = '33' C eval MyDS.RtnVal = *zero C callp DSPARM (MyDS) C if MyDS.rtnval <> *zero
Here’s a final example that Barbara gave me. This example uses two data structures as parameters.
Here’s the prototype copybook member. The two pattern data structures have names that end with an underscore (_) and a lowercase letter t to remind programmers that these data structures serve as data types, not as real variables with allocated storage.
D custInfo_t ds qualified based(typedummy) D name 100a varying D id_no 10i 0 D addr 100a varying D partInfo_t ds qualified based(typedummy) D name 100a varying D id_no 10i 0 D cost 15p 3 D buyOne pr D cust likeds(custInfo_t) const D part likeds(partInfo_t) const D num 10i 0 value
A caller of the procedure would use the data structure names as pseudo data types. All references to the subfields would be qualified.
/copy prototypes,custtrans D theCust ds likeds(custInfo_t) D thePart ds likeds(partInfo_t) /free theCust.name = whatever; buyOne (theCust : thePart : num); /end-free
Prototyping data structure parameters is more complex than the old RPG III method you used. However, I believe that the advantages of prototyping parameters are worth the extra effort.
— Ted
Sponsored By COMMON |
Get the IT training you need by attending COMMON Users Group’s Spring 2003 IT Education Conference and Expo, March 9 – 13, in Indianapolis. Choose from hundreds of sessions and labs covering the widest range of industry topics, including RPG IV, LPAR, WebSphere, and High Availability. COMMON is the best value in IT education, so don’t miss out! Click and visit www.common.org for details! |
Hi, how to manage null capable field in a data structure used as parameters?
Regards,
Olivier.