Ile RPG For As 400 Programmers Guide
Ile RPG For As 400 Programmers Guide
SC09-2507-00
AS/400 Advanced Series ÉÂÔ
ILE RPG for AS/400
Programmer's Guide
Version 4
SC09-2507-00
Note: Before using this information and the product it supports, be sure to read the general information under “Notices” on
page xix.
This edition to Version 4, Release 2, Modification 0, of IBM Integrated Language Environment RPG for AS/400 (Program 5769-RG1)
and to all subsequent releases and modifications until otherwise indicated in new editions. Make sure you are using the correct
edition for the level of the product. Consult the latest edition of the applicable IBM system bibliography for current information on this
product.
Changes or additions to the text and illustrations are indicated by a vertical line to the left of the change or addition.
Order publications through your IBM representative or the IBM branch office serving your locality. Publications are not stocked at the
address given below.
A form for readers’ comments is provided at the back of this publication. If the form has been removed, address your comments to:
You can also send your comments by facsimile (attention: RCF Coordinator), or you can send your comments electronically to IBM.
See “Communicating Your Comments to IBM” for a description of the methods. This page immediately precedes the Readers’
Comment Form at the back of this publication.
When you send information to IBM, you grant IBM a nonexclusive right to use or distribute the information in any way it believes
appropriate without incurring any obligation to you.
Contents v
Returning from a Called Program or Procedure . . . . . . . . . . . . . . . . . 153
Returning from a Main Procedure . . . . . . . . . . . . . . . . . . . . . . . . 153
Returning from a Subprocedure . . . . . . . . . . . . . . . . . . . . . . . . . 156
Returning using ILE Bindable APIs . . . . . . . . . . . . . . . . . . . . . . . 156
Using Bindable APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Examples of Using Bindable APIs . . . . . . . . . . . . . . . . . . . . . . . 158
Calling a Graphics Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Calling Special Routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Contents vii
Using Externally Described Disk Files . . . . . . . . . . . . . . . . . . . . . . . 282
Record Format Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Access Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Valid Keys for a Record or File . . . . . . . . . . . . . . . . . . . . . . . . . 285
Record Blocking and Unblocking . . . . . . . . . . . . . . . . . . . . . . . . 287
Using Program-Described Disk Files . . . . . . . . . . . . . . . . . . . . . . . . 288
Indexed File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
Sequential File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Record Address File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
Methods for Processing Disk Files . . . . . . . . . . . . . . . . . . . . . . . . . 291
Consecutive Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
Sequential-by-Key Processing . . . . . . . . . . . . . . . . . . . . . . . . . . 293
Random-by-Key Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
Sequential-within-Limits Processing . . . . . . . . . . . . . . . . . . . . . . . 300
Relative-Record-Number Processing . . . . . . . . . . . . . . . . . . . . . . 303
Valid File Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
Using Commitment Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
Starting and Ending Commitment Control . . . . . . . . . . . . . . . . . . . 307
Specifying Files for Commitment Control . . . . . . . . . . . . . . . . . . . 309
Using the COMMIT Operation . . . . . . . . . . . . . . . . . . . . . . . . . . 309
Specifying Conditional Commitment Control . . . . . . . . . . . . . . . . . . 311
Commitment Control in the Program Cycle . . . . . . . . . . . . . . . . . . 312
DDM Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Using Pre-V3R1 DDM Files . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
Appendixes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
Contents ix
Use of Externally Described Data Structures . . . . . . . . . . . . . . . . . 401
Run-time Differences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Contents xi
51. Source for Menu Program . . . . . . . . . . . . . . . . . . . . . . . . . . 107
52. Memory Management - Build a Linked List of Names . . . . . . . . . . 114
53. Heap Storage Misuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
54. /COPY file DYNARRI containing prototypes for DYNARRAY module . 120
55. Global variables and local prototypes for DYNARRAY . . . . . . . . . . 121
56. DYNARRAY Subprocedures . . . . . . . . . . . . . . . . . . . . . . . . . 123
57. Sample module using procedures in DYNARRAY . . . . . . . . . . . . . 127
58. Program and Procedure Calls on the Call Stack . . . . . . . . . . . . . 131
59. Three Modules, each with subprocedures . . . . . . . . . . . . . . . . . 132
60. Recursive Call Stack To Be Avoided . . . . . . . . . . . . . . . . . . . . 133
61. Prototype for CVTCHR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
62. Calling a Prototyped Procedure within an Expression . . . . . . . . . . 136
63. Prototype for Procedure DO_CALC with VALUE Parameters . . . . . . 139
64. Procedure Interface Definition for DO_CALC Procedure . . . . . . . . . 139
65. Prototype for ILE CEE API CEETSTA with CONST Parameter . . . . . 140
66. Requesting Operational Descriptors for a Prototyped Procedure . . . . 141
67. Prototype for System API QCMDEXC with Optional Parameter . . . . . 142
68. Source for procedure FMTADDR . . . . . . . . . . . . . . . . . . . . . . 144
69. Source for /COPY member with Prototype for Procedure FMTADDR . 145
70. Source for procedure PRTADDR . . . . . . . . . . . . . . . . . . . . . . 146
71. Prototype for System API QCMDEXC with *VARSIZE Parameter . . . 148
72. Sample Call Syntax for ILE Bindable APIs . . . . . . . . . . . . . . . . . 157
73. Display Module Source display for program DEBUGEX . . . . . . . . . 171
74. Adding an ILE Service Program to a Debug Session . . . . . . . . . . . 173
75. Removing an ILE Program from a Debug Session . . . . . . . . . . . . 174
76. Changing to a Different Module . . . . . . . . . . . . . . . . . . . . . . . 176
77. Source View of ILE C procedure cproc . . . . . . . . . . . . . . . . . . . 176
| 78. Changing a View of a Module . . . . . . . . . . . . . . . . . . . . . . . . 177
79. Setting an Unconditional Job Breakpoint . . . . . . . . . . . . . . . . . . 180
80. Setting a Conditional Job Breakpoint . . . . . . . . . . . . . . . . . . . . 182
81. Setting a Conditional Job Breakpoint Using the BREAK Command . . 183
82. Setting a Breakpoint Using Statement View . . . . . . . . . . . . . . . . 186
83. Example of a Work with Watch Display . . . . . . . . . . . . . . . . . . . 190
84. Example of a Display Watch Window . . . . . . . . . . . . . . . . . . . . 190
85. Example of a Display Debug Watch Display . . . . . . . . . . . . . . . . 191
| 86. Example of Message Stating WATCH was Successfully Set . . . . . . 193
87. Example of a Display Module Source Panel . . . . . . . . . . . . . . . . 194
88. Display Module Source display of DBGEX Before Stepping Into
RPGPGM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
89. Stepping into RPGPGM . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
90. Stepping into Subprocedure Switch . . . . . . . . . . . . . . . . . . . . . 199
91. Displaying a Field using the EVAL debug command . . . . . . . . . . . 200
92. Sample EVAL commands based on Module DBGEX . . . . . . . . . . . 201
93. Sample EVAL commands for an Array . . . . . . . . . . . . . . . . . . . 202
94. Sample EVAL commands for a Table . . . . . . . . . . . . . . . . . . . . 203
95. Using EVAL with Data Structures . . . . . . . . . . . . . . . . . . . . . . 204
96. Sample EVAL commands for an Array . . . . . . . . . . . . . . . . . . . 205
97. Examples of %SUBSTR using DBGEX . . . . . . . . . . . . . . . . . . . 207
98. Examples of Changing the Values of Fields based on DBGEX . . . . . 209
99. Examples of Displaying the Attributes of Fields based on DBGEX . . . 210
100. Source for Module DBGEX . . . . . . . . . . . . . . . . . . . . . . . . . . 212
101. Source for OPM Program RPGPGM . . . . . . . . . . . . . . . . . . . . 216
102. Source for C Procedure cproc . . . . . . . . . . . . . . . . . . . . . . . . 216
103. Call Stack and Exception Message Percolation . . . . . . . . . . . . . . 219
Figures xiii
152. Printing a Heading on Every Page . . . . . . . . . . . . . . . . . . . . . 319
153. Printing a Field on Every Page . . . . . . . . . . . . . . . . . . . . . . . . 320
154. Overflow Printing: Setting of the Overflow Indicator . . . . . . . . . . . 321
155. Use of Fetch Overflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
156. Example of the PRTCTL Option . . . . . . . . . . . . . . . . . . . . . . . 325
157. SEQ Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
158. SPECIAL Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
159. User-written program USERIO . . . . . . . . . . . . . . . . . . . . . . . . 330
160. Example of the Data Description Specifications for a Display Device File 333
161. Subfile Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
162. Data Description Specifications for a Subfile Record Format . . . . . . 337
163. Data Description Specifications for a Subfile Control-Record Format . . 338
164. DDS for master database file CUSMST (physical file) . . . . . . . . . . 346
165. DDS for display device file MAINMENU . . . . . . . . . . . . . . . . . . 347
166. Source for module CUSMAIN . . . . . . . . . . . . . . . . . . . . . . . . 348
167. Customer Main Inquiry prompt screen . . . . . . . . . . . . . . . . . . . 349
168. DDS for logical file CUSMSTL1 . . . . . . . . . . . . . . . . . . . . . . . 349
169. DDS for display device file MNTMENU . . . . . . . . . . . . . . . . . . . 350
170. Source for module CUSMNT . . . . . . . . . . . . . . . . . . . . . . . . . 352
171. 'Customer File Maintenance' Display Mode prompt screen . . . . . . . 355
172. 'Customer File Maintenance' Display Mode screen . . . . . . . . . . . . 356
173. 'Customer File Maintenance' Add Mode prompt screen . . . . . . . . . 356
174. 'Customer File Maintenance' Add Mode prompt screen . . . . . . . . . 357
175. 'Customer File Maintenance' Delete Mode prompt screen . . . . . . . . 357
176. 'Customer File Maintenance' Update Mode prompt screen . . . . . . . 358
177. DDS for logical file CUSMSTL2 . . . . . . . . . . . . . . . . . . . . . . . 358
178. DDS for display device file SZIPMENU . . . . . . . . . . . . . . . . . . . 359
179. Source for module SCHZIP . . . . . . . . . . . . . . . . . . . . . . . . . 361
180. 'Customer Search by Zip' prompt screen . . . . . . . . . . . . . . . . . . 363
181. 'Customer Search by Zip' screen . . . . . . . . . . . . . . . . . . . . . . 364
182. DDS for logical file CUSMSTL3 . . . . . . . . . . . . . . . . . . . . . . . 364
183. DDS for display device file SNAMMENU . . . . . . . . . . . . . . . . . . 365
184. Source for module SCHNAM . . . . . . . . . . . . . . . . . . . . . . . . . 366
185. 'Customer Search and Inquiry by Name' prompt screen . . . . . . . . . 369
186. 'Customer Search and Inquiry by Name' information screen . . . . . . . 370
187. 'Customer Search and Inquiry by Name' detailed information screen . . 370
188. RPG IV Record Length Breakdown . . . . . . . . . . . . . . . . . . . . . 380
189. RPG III Source for TEST1 . . . . . . . . . . . . . . . . . . . . . . . . . . 391
190. Converted (RPG IV) Source for TEST1 . . . . . . . . . . . . . . . . . . . 392
191. Command Summary of Sample Conversion Report . . . . . . . . . . . . 394
192. Sample Source Section of Conversion Report . . . . . . . . . . . . . . . 395
193. Sample Message Summary of Conversion Report . . . . . . . . . . . . 395
194. Sample Final Summary of Conversion Report . . . . . . . . . . . . . . . 396
195. DDS for model log file QARNCVTLG in library QRPGLE . . . . . . . . 397
| 196. RPG III Source for TEST2 . . . . . . . . . . . . . . . . . . . . . . . . . . 399
| 197. RPG III Source for COPYDS1 . . . . . . . . . . . . . . . . . . . . . . . . 399
198. RPG III /COPY file with input fields only . . . . . . . . . . . . . . . . . . 400
| 199. RPG III Source with a renamed field . . . . . . . . . . . . . . . . . . . . 401
| 200. RPG IV source after converting source with input fields only . . . . . . 401
| 201. DDS for external data structure . . . . . . . . . . . . . . . . . . . . . . . 402
| 202. RPG III source using external data structure with array . . . . . . . . . 402
| 203. RPG IV source with two definitions for the array . . . . . . . . . . . . . 402
| 204. Corrected RPG IV source with a single definition for the array . . . . . 402
205. RPG III source with renamed and initialized external subfield . . . . . . 403
Figures xv
xvi ILE RPG for AS/400 Programmer's Guide
Tables
1. Commonly Used CL Commands . . . . . . . . . . . . . . . . . . . . . . . . 13
2. Programming Languages Supported on the AS/400 . . . . . . . . . . . . 17
3. CRTBNDRPG Parameters and Their Default Values Grouped by Function 58
4. CRTRPGMOD Parameters and Their Default Values Grouped by Function 74
5. Parameters for CRTPGM Command and their Default Values . . . . . . 83
6. Sections of the Binder Listing based on DETAIL Parameter . . . . . . . . 86
7. Parameters for CRTSRVPGM Command and their Default Values . . . . 93
8. Parameter Passing Options . . . . . . . . . . . . . . . . . . . . . . . . . 135
9. RPG Parameter Passing Methods . . . . . . . . . . . . . . . . . . . . . . 149
10. Meaning of Factor 1 and Factor 2 Entries in PARM Operation . . . . . 152
| 11. Debug Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
12. Non-numeric Conditional Breakpoint Expressions . . . . . . . . . . . . . 185
| 13. Operation Codes Allowing Extender 'E' or an Error Indicator in Positions
| 73-74 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
14. Correlation of RPG Device Types with AS/400 File Types . . . . . . . . 262
15. Data Management Operations and the Corresponding RPG I/O
Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
16. System Open Options Allowed with User Open Options . . . . . . . . . 278
17. Processing Methods for DISK Files . . . . . . . . . . . . . . . . . . . . . 292
18. Valid File Operations for Keyed Processing Methods (Random by Key,
Sequential by Key, Sequential within Limits) . . . . . . . . . . . . . . . . 305
19. Valid File Operations for Non-keyed Processing Methods (Sequential,
Random by Relative Record Number, and Consecutive) . . . . . . . . . 306
20. AS/400 Device Files, Related CL commands, and RPG Device Name 315
21. Results of the Presence or Absence of an Overflow Indicator . . . . . . 319
22. Layout of ILE PRTCTL Data Structure . . . . . . . . . . . . . . . . . . . 323
23. Layout of OPM PRTCTL Data Structure . . . . . . . . . . . . . . . . . . 324
24. Valid File Operation Codes for a Sequential File . . . . . . . . . . . . . 326
25. Valid File Operations for a SPECIAL File . . . . . . . . . . . . . . . . . . 329
26. Valid File Operation Codes for a WORKSTN File . . . . . . . . . . . . . 341
27. Description of Each Module in the Interactive Application Example . . . 345
28. Source Member Types and their Conversion Status . . . . . . . . . . . 380
29. CVTRPGSRC Parameters and Their Default Values Grouped by
Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
30. Sections of the Compiler Listing . . . . . . . . . . . . . . . . . . . . . . . 423
IBM may have patents or pending patent applications covering subject matter in
this document. The furnishing of this document does not give you any license to
these patents. You can send license inquiries, in writing, to the IBM Director of
Licensing, IBM Corporation, 500 Columbus Avenue, Thornwood, NY 10594, USA.
Licensees of this program who wish to have information about it for the purpose of
enabling: (i) the exchange of information between independent created programs
and other programs (including this one) and (ii) the mutual use of the information
which has been exchanged, should contact IBM Canada Ltd., Department 071,
1150 Eglinton Avenue East, North York, Ontario M3C 1H7, Canada. Such informa-
tion may be available, subject to appropriate terms and conditions, including in
some cases payment of a fee.
This publication contains examples of data and reports used in daily business oper-
ations. To illustrate them as completely as possible, the examples include the
names of individuals, companies, brands, and products. All of these names are
fictitious and any similarity to the names and addresses used by an actual business
enterprise is entirely coincidental.
| 400 IBMLink
| AFP Integrated Language Environment
| AS/400 Operating System/400
| C/400 OS/400
| COBOL/400 PROFS
| DB2 RPG/400
| FORTRAN/400 System/36
| GDDM System/38
| IBM VisualAge
For information about other AS/400 publications, see either of the following:
¹ The Publications Reference, in the AS/400 Softcopy Library.
¹ The AS/400 Information Directory a unique, multimedia interface to a
searchable database containing descriptions of titles available from IBM or from
selected other publishers. The AS/400 Information Directory is shipped with
your system at no charge.
Though this guide shows how to use the RPG IV in an ILE framework, it does not
provide detailed information on RPG IV specifications and operations. For a
detailed description of the language, see the ILE RPG for AS/400 Reference,
SC09-2508 .
For more information on RPG IV, see the ILE RPG for AS/400 Reference.
RPG IV Specifications
RPG code is written on a variety of specification forms, each with a specific set of
functions. Many of the entries which make up a specification type are position-
dependent. Each entry must start in a specific position depending on the type of
entry and the type of specification.
There are seven types of RPG IV specifications. Each specification type is optional.
Specifications must be entered into your source program in the order shown below.
Subprocedure section:
1. Procedure specifications mark the beginning and end of the subprocedure,
indicate the subprocedure name, and whether it is exported.
2. Definition specifications describe the local data used by the subprocedure.
3. Calculation specifications describe the calculations done on both the global
and local data and the order of the calculations.
The logic the compiler supplies is called the program cycle. When you let the
compiler provide the logic for your programs, it is called cycle programming.
The program cycle is a series of steps that your program repeats until an end-of-file
condition is reached. Depending on the specifications you code, the program may
or may not use each step in the cycle.
If you want to have files controlled by the cycle, the information that you code on
RPG specifications in your source program need not specify when records for these
files are read. The compiler supplies the logical order for these operations, and
some output operations, when your source program is compiled.
If you do not want to have files controlled by the cycle, you must end your program
some other way, either by creating an end-of-file condition by setting on the last
record (LR) indicator, by creating a return condition by setting on the return (RT)
indicator, or by returning directly using the RETURN operation.
Note: No cycle code is generated for subprocedures or when NOMAIN is speci-
fied on the control specification.
Figure 1 shows the specific steps in the general flow of the RPG program cycle.
Write Perform
Get input
Start heading and total
record
detail lines calculations
Perform No Write
LR on
detail Move fields total
calculations output
Yes
End of
program
.1/ RPG processes all heading and detail lines (H or D in position 17 of the
output specifications).
The first and last time through the program cycle differ somewhat from other cycles.
Before reading the first record the first time through the cycle, the program does
three things:
¹ handles input parameters, opens files, initializes program data
¹ writes the records conditioned by the 1P (first page) indicator
¹ processes all heading and detail output operations.
For example, heading lines printed before reading the first record might consist of
constant or page heading information, or special fields such as PAGE and *DATE.
The program also bypasses total calculations and total output steps on the first
cycle.
The last time a program goes through the cycle, when no more records are avail-
able, the program sets the LR (last record) indicator and the L1 through L9 (control
level) indicators to on. The program processes the total calculations and total
output, then all files are closed, and then the program ends.
Subprocedure logic
The general flow of a subprocedure is much simpler: the calculations of a subpro-
cedure are done once, and then the subprocedure returns. There is no cycle code
generated for a subprocedure.
Indicators
| An indicator is a one-byte character field that is either set on ('1') or off ('0'). It is
| generally used to indicate the result of an operation or to condition (control) the
| processing of an operation. Indicators are like switches in the flow of the program
| logic. They determine the path the program will take during processing, depending
| on how they are set or used.
| Indicator variables can be used any place an indicator of the form *INxx may be
| used with the exception of the OFLIND and EXTIND keywords on the file
| description specifications.
An RPG program sets and resets certain indicators at specific times during the
program cycle. In addition, the state of indicators can be changed explicitly in calcu-
lation operations.
Operation Codes
The RPG IV programming language allows you to do many different types of oper-
ations on your data. Operation codes, entered on the calculation specifications,
indicate what operations will be done. For example, if you want to read a new
record, you could use the READ operation code. The following is a list of the types of
operations available.
Arithmetic operations Indicator-setting operations
Array operations Information operations
Bit operations Initialization operations
| Branching operations Memory Management Operations
Call operations Message operation
Compare operations Move operations
Data-Area operations String operations
Date/Time/Timestamp operations Structured programming operations
Declarative operations Subroutine operations
File operations Test operations
Problem Statement
The payroll department of a small company wants to create a print output that lists
employees' pay for that week. Assume there are two disk files, EMPLOYEE and
TRANSACT, on the system.
The first file, EMPLOYEE, contains employee records. The figure below shows the
format of an employee record:
EMP_REC
1 6 22 27
The second file, TRANSACT, tracks the number of hours each employee worked
for that week and any bonus that employee may have received. The figure below
shows the format of a transaction record:
TRN_REC
1 6 10 16
Each employee's pay is calculated by multiplying the "hours" (from the TRANSACT
file) and the "rate" (from the EMPLOYEE file) and adding the "bonus" from the
TRANSACT file. If more than 40 hours were worked, the employee is paid for for
1.5 times the normal rate.
Control Specifications
Today's date will be printed in day, month, year format with "/" as the separator.
FTRANSACT IP E K DISK
FEMPLOYEE IF E K DISK
FQSYSPRT O F 80 PRINTER
Definition Specifications
D Pay S 8P 2
D Heading1 C 'NUMBER NAME RATE H-
D OURS BONUS PAY '
D Heading2 C '______ ________________ ______ _-
D ____ _______ __________'
D CalcPay PR 8P 2
D Rate 5P 2 VALUE
D Hours 10U 0 VALUE
D Bonus 5P 2 VALUE
Calculation Specifications
Output Specifications
OQSYSPRT H 1P 2 3
O 35 'PAYROLL REGISTER'
O *DATE Y 60
O H 1P 2
O 60 Heading1
O H 1P 2
O 60 Heading2
O D N1PN99 2
O TRN_NUMBER 5
O EMP_NAME 24
O EMP_RATE L 33
O TRN_HOURS L 40
O TRN_BONUS L 49
O Pay 60 '$ 0. '
O D N1P 99 2
O TRN_NUMBER 5
O 35 '** NOT ON EMPLOYEE FILE **'
O T LR
O 33 'END OF LISTING'
The output specifications describe what fields are to be written on the QSYSPRT
output:
¹ The Heading Lines that contain the constant string 'PAYROLL REGISTER' as
well as headings for the detail information will be printed if indicator 1P is on.
Indicator 1P is turned on by the ILE RPG program cycle during the first cycle.
¹ The Detail Lines are conditioned by the indicators 1P and 99. Detail Lines are
not printed at 1P time. The N99 will only allow the Detail lines to be printed if
indicator 99 is off, which indicates that the corresponding employee record has
been found. If the indicator 99 is on, then the employee number and the con-
stant string '** NOT ON EMPLOYEE FILE **' will be printed instead.
¹ The Total Line contains the constant string 'END OF LISTING'. It will be printed
during the last program cycle.
A Subprocedure
The subprocedure calculates the pay for the employee using the parameters
passed to it. The resulting value is returned to the caller using the RETURN state-
ment.
The procedure specifications indicate the beginning and end of the procedure. The
definition specifications define the return type of the procedure, the parameters to
the procedure, and the local variable Overtime.
D Overtime S 5P 2 INZ(0)
P CalcPay E
The following figure combines all the specifications used in this program. This is
what you should enter into the source file for this program.
*------------------------------------------------------------------------*
* DESCRIPTION: This program creates a printed output of employee's pay *
* for the week. *
*------------------------------------------------------------------------*
H DATEDIT(*DMY/)
*------------------------------------------------------------------------*
* File Definitions *
*------------------------------------------------------------------------*
FTRANSACT IP E K DISK
FEMPLOYEE IF E K DISK
FQSYSPRT O F 80 PRINTER
*------------------------------------------------------------------------*
* Variable Declarations *
*------------------------------------------------------------------------*
D Pay S 8P 2
*------------------------------------------------------------------------*
* Prototype Definition for subprocedure CalcPay *
*------------------------------------------------------------------------*
D CalcPay PR 8P 2
D Rate 5P 2 VALUE
D Hours 10U 0 VALUE
D Bonus 5P 2 VALUE
*------------------------------------------------------------------------*
* For each record in the transaction file (TRANSACT), if the employee *
* is found, compute the employee's pay and print the details. *
*------------------------------------------------------------------------*
C TRN_NUMBER CHAIN EMP_REC 99
C IF NOT *IN99
C EVAL PAY = CalcPay(EMP_RATE : TRN_HOURS :
C TRN_BONUS)
C ENDIF
*------------------------------------------------------------------------*
* Report Layout *
* -- print the heading lines if 1P is on *
* -- if the record is found (indicator 99 is off) print the payroll *
* details otherwise print an exception record *
* -- print 'END OF LISTING' when LR is on *
*------------------------------------------------------------------------*
OQSYSPRT H 1P 2 3
O 35 'PAYROLL REGISTER'
O *DATE Y 60
O H 1P 2
O 60 Heading1
O H 1P 2
O 60 Heading2
O D N1PN99 2
O TRN_NUMBER 5
O EMP_NAME 24
O EMP_RATE L 33
O TRN_HOURS L 40
O TRN_BONUS L 49
O Pay 60 '$ 0. '
O D N1P 99 2
O TRN_NUMBER 5
O 35 '** NOT ON EMPLOYEE FILE **'
O T LR
O 33 'END OF LISTING'
D Overtime S 5P 2 INZ(0)
P CalcPay E
Refer to the Publications Reference, for a complete list of publications that discuss
the OS/400 system.
The following table lists some of the most commonly used CL commands, their
function, and the reasons you might want to use them.
AS/400 Tools
The AS/400 system offers a full set of tools that you may find useful for program-
ming.
Application Dictionary Services is an impact analysis tool that speeds up the anal-
ysis of applications. The tool stores the information about the application objects
and their relationships to other application objects in a dictionary. A dictionary
extracts the cross-reference information about all of the objects in an application's
libraries, and saves it in a set of database files stored in a library. As application
objects and their relationships to other objects change, the information in the dic-
tionary is automatically updated.
| CODE/400 contains features to help edit, compile, and debug: RPG, ILE RPG,
| COBOL, ILE COBOL, Control Language (CL), ILE C, and ILE CL host source pro-
| grams; design display, printer, and database host files; and manage the compo-
| nents that make up your application. This enhances program development and
| moves the program development workload off the host. The application, when built,
| runs on an AS/400. For RPG and ILE RPG application development and mainte-
| nance, CODE/400 provides:
| ¹ Language sensitive editing— includes token highlighting, format lines, a full
| suite of prompts, and online help.
| ¹ Incremental syntax checking— provides immediate error feedback as each line
| of source is entered
| ¹ Program verification— performs, at the workstation, the full range of syntax and
| semantic checking that the compiler does, without generating object code
| ¹ Program conversion— performs, at the workstation, an OPM to ILE RPG con-
| version
| If you want to learn more about CODE/400 and VisualAge for RPG, see the most
| current information available on the World Wide Web at:
| http://www.software.ibm.com/ad/varpg/
Each of the above areas is explained briefly in the following paragraphs and dis-
cussed further in the following chapters.
Program Creation
In ILE, program creation consists of:
1. Compiling source code into modules
2. Binding (combining) one or more modules into a program object
You can create a program object much like you do in the OPM framework, with a
one-step process using the Create Bound RPG Program (CRTBNDRPG)
command. This command creates a temporary module which is then bound into a
program object. It also allows you to bind other objects through the use of a binding
directory.
In the two-step process, you create a module object using the Create RPG Module
(CRTRPGMOD) command. This command compiles the source statements into a
module object. A module is a nonrunnable object; it must be bound into a program
object to be run. To bind one or more modules together, use the Create Program
(CRTPGM) command.
| You can create a binding directory to contain the names of modules and service
| programs that your program or service program may need. A list of binding directo-
| ries can be specified when you create a program on the CRTBNDRPG,
| CRTSRVPGM, and CRTPGM commands. They can also be specified on the
| CRTRPGMOD command; however, the search for a binding directory is done when
| the module is bound at CRTPGM or CRTSRVPGM time. A binding directory can
| reduce program size because modules or service programs listed in a binding
| directory are used only if they are needed.
Once a program is created you can update the program using the Update Program
(UPDPGM) or Update Service Program (UPDSRVPGM) commands. This is useful,
because it means you only need to have the new or changed module objects avail-
able to update the program.
For more information on the one-step process, see Chapter 6, “Creating a Program
with the CRTBNDRPG Command” on page 57. For more information on the two-
Program Management
ILE provides a common basis for:
¹ Managing program flow
¹ Sharing resources
¹ Using application program interfaces (APIs)
¹ Handling exceptions during a program's run time
It gives RPG users much better control over resources than was previously pos-
sible.
ILE programs and service programs are activated into activation groups which are
specified at program-creation time. The process of getting a program or service
program ready to run is known as activation. Activation allocates resources within a
job so that one or more programs can run in that space. If the specified activation
group for a program does not exist when the program is called, then it is created
within the job to hold the program's activation.
You can dynamically allocate storage for a run-time array using the bindable APIs
provided for all ILE programming languages. These APIs allow single- and mixed-
language applications to access a central set of storage management functions and
offer a storage model to languages that do not now provide one. RPG offers some
storage management capabilities using operation codes. For more information on
storage management, see “Managing Dynamically-Allocated Storage” on page 113.
Program Call
In ILE, you can write applications in which ILE RPG programs and OPM RPG/400
programs continue to interrelate through the traditional use of dynamic program
calls. When using such calls, the calling program specifies the name of the called
program on a call statement. The called program's name is resolved to an address
at run time, just before the calling program passes control to the called program.
You can also write ILE applications that can interrelate with faster static calls. Static
calls involve calls between procedures. A procedure is a self-contained set of code
that performs a task and then returns to the caller. An ILE RPG module consists of
an optional main procedure followed by zero or more subprocedures. Because the
Source Debugging
In ILE, you can perform source-level debugging on any single- or mixed-language
ILE application. The ILE source debugger also supports OPM programs. You can
control the flow of a program by using debug commands while the program is
| running. You can set conditional and unconditional job or thread breakpoints prior
to running the program. After you call the program, you can then step through a
specified number of statements, and display or change variables. When a program
stops because of a breakpoint, a step command, or a run-time error, the pertinent
module is shown on the display at the point where the program stopped. At that
point, you can enter more debug commands.
Bindable APIs
ILE offers a number of bindable APIs that can be used to supplement the function
currently offered by ILE RPG. The bindable APIs provide program calling and acti-
vation capability, condition and storage management, math functions, and dynamic
screen management.
Some APIs that you may wish to consider using in an ILE RPG application include:
¹ CEETREC – Signal the Termination-Imminent Condition
¹ CEE4ABN – Abnormal End
¹ CEECRHP – Create your own heap
¹ CEEDSHP – Discard your own heap
¹ CEEFRST – Free Storage in your own heap
¹ CEEGTST – Get Heap Storage in your own heap
¹ CEECZST – Reallocate Storage in your own heap
For more information on these ILE bindable APIs, see Chapter 9, “Running a
Program” on page 103 and also the System API Reference.
| Multi-Threaded Applications
| The AS/400 now supports multi-threading. However, it is not supported in this
| release for ILE RPG procedures to run in a multi-threaded environment. If you want
| to call an ILE RPG procedure in a multi-threaded application, you must ensure that
| only one thread is calling any ILE RPG procedure at a time. If you want to try
| running an ILE RPG procedure in a multi-threaded environment, even though it is
| not supported, and even though you ensure that only one thread is calling any ILE
| RPG procedure at one time, you should be aware that some functions that ILE
| RPG uses are not thread-safe.
The first strategy is recommended as a temporary one. It is intended for users who
have OPM applications and who, perhaps due to lack of time, cannot move their
applications to ILE all at once. The second strategy can also be a temporary one. It
allows you time to learn more about ILE, but also allows you to immediately use
some of its features. The third strategy is more involved, but offers the most flexi-
bility.
Both the first and second strategy make use of the one-step program creation
process, namely, CRTBNDRPG. The third strategy uses the two-step program cre-
ation process, namely, CRTRPGMOD followed by CRTPGM.
Method
Use the following general approach to create such a program:
1. Convert your source to RPG IV using the CVTRPGSRC command.
Be sure to convert all /COPY members that are used by the source you are
converting.
2. Create a program object using the CRTBNDRPG command, specifying
DFTACTGRP(*YES).
Specifying DFTACTGRP(*YES) means that the program object will run only in the
default activation group. (The default activation group is the activation group where
all OPM programs are run.) As a result, the program object will interact well with
OPM programs in the areas of override scoping, open scoping, and RCLRSC.
When you use this approach you cannot make use of ILE static binding. This
means that you cannot code a bound procedure call in your source, nor can you
use the BNDDIR or ACTGRP parameters on the CRTBNDRPG command when
creating this program.
Job
Default Activation Group
*PGM(X)
OPM CL
*PGM(Y)
ILE RPG
*PGM(Z)
OPM RPG
Effect of ILE
The following deals with the effects of ILE on the way your application handles:
Program call OPM programs behave as before. The system automatically
creates the OPM default activation group when you start your job,
and all OPM applications run in it. One program can call another
program in the default activation group by using a dynamic call.
Data Storage for static data is created when the program is activated,
and it exists until the program is deactivated. When the program
ends (either normally or abnormally), the program's storage is
deleted. To clean up storage for a program that returns without
ending, use the Reclaim Resource (RCLRSC) command.
Files File processing is the same as in previous releases. Files are
closed when the program ends normally or abnormally.
Errors As in previous releases, the compiler handles errors within each
program separately. The errors you see that originated within your
program are the same as before. However, the errors are now
communicated between programs by the ILE condition manager,
so you may see different messages between programs. The mes-
sages may have new message IDs, so if your CL program moni-
tors for a specific message ID, you may have to change that ID.
Method
Use the following general approach to create such a program:
1. If starting with RPG III source, convert your source to RPG IV using the
CVTRPGSRC command.
If converting, be sure to convert all /COPY members and any programs that are
called by the source you are converting. Also, if you are using CL to call the
program, you should also make sure that you are using ILE CL instead of OPM
CL.
2. Determine the activation group the program will run in.
You may want to name it after the application name, as in this example.
| 3. Identify the names of the binding directories, if any, to be used.
| It is assumed with this approach that if you are using a binding directory, it is
| one that is already created for you. For example, there may be a third-party
| service program that you may want to bind to your source. Consequently, all
| you need to know is the name of the binding directory.
4. Create an ILE program using CRTBNDRPG, specifying DFTACTGRP(*NO), the
activation group on the ACTGRP parameter, and the binding directory, if any,
on the BNDDIR parameter.
The main drawback of this strategy is that you do not have a permanent module
object that you can later reuse to bind with other modules to create an ILE
program. Furthermore, any procedure calls must be to modules or service pro-
| grams that are identified in a binding directory. If you want to bind two or more
| modules without using a binding directory when you create the program, you need
| to use the third strategy.
Job
XYZ Activation Group
*PGM(X)
ILE CL
*PGM(Y)
ILE RPG
*SRVPGM(Z)
Supplied Service
Program
Effect of ILE
The following deals with the effects of ILE on the way your program handles:
Program call The system automatically creates the activation group if it does not
already exist, when the application starts.
The application can contain dynamic program calls or static proce-
dure calls. Procedures within bound programs call each other by
using static calls. Procedures call ILE and OPM programs by
using dynamic calls.
Data The lifetime of a program's storage is the same as the lifetime of
the activation group. Storage remains active until the activation
group is deleted.
The ILE RPG run time manages data so that the semantics of
ending programs and reinitializing the data are the same as for
OPM RPG, although the actual storage is not deleted as it was
when an OPM RPG program ended. Data is reinitialized if the pre-
vious call to the procedure ended with LR on, or ended abnor-
mally.
Program data that is identified as exported or imported (using the
keywords EXPORT and IMPORT respectively) is external to the
individual modules. It is known among the modules that are bound
into a program.
Files By default, file processing (including opening, sharing, overriding,
and commitment control) by the system is scoped to the activation
group level. You cannot share files at the data management level
Related Information
Converting to RPG IV “Converting Your Source” on page 382
One-step creation process Chapter 6, “Creating a Program with the
CRTBNDRPG Command” on page 57
Activation groups “Managing Activation Groups” on page 109
RCLRSC “Reclaim Resources Command” on
page 112
ILE static binding Chapter 10, “Calling Programs and
Procedures” on page 129; also ILE Con-
cepts
Exception handling differences “Differences between OPM and ILE RPG
Exception Handling” on page 222
Override and open scope “Overriding and Redirecting File Input and
Output” on page 273 and “Sharing an Open
Data Path” on page 277; also ILE Concepts
The effect of ILE is the same as described in “Effect of ILE” on page 26.
You may want to read about the basic ILE concepts in ILE Concepts before using
this approach.
Method
Because this approach is the most flexible, it includes a number of ways in which
you might create an ILE application. The following list describes the main steps that
you may need to perform:
1. Create a module from each source member using the appropriate command,
for example, CRTRPGMOD for RPG source, CRTCLMOD for CL source, etc..
2. Determine the ILE characteristics for the application, for example:
¹ Determine which module will contain the procedure that will be the starting
point for the application. The module you choose as the entry module is the
first one that you want to get control. In an OPM application, this would be
the command processing program, or the program called because a menu
item was selected.
¹ Determine the activation group the application will run in. (Most likely you
will want to run in a named activation group, where the name is based on
the name of the application.)
¹ Determine the exports and imports to be used.
3. Determine if any of the modules will be bound together to create a service
program. If so, create the service programs using CRTSRVPGM.
| 4. Identify the names of the binding directories, if any, to be used.
| It is assumed with this approach that if you are using a binding directory, it is
| one that is already created for you. For example, there may be a third-party
| service program that you may want to bind to your source. Consequently, all
| you need to know is the name of the binding directory.
5. Bind the appropriate modules and service programs together using CRTPGM,
specifying values for the parameters based on the characteristics determined in
step 2.
An application created using this approach can run fully protected, that is, within its
own activation group. Furthermore, it can be updated easily through use of the
UPDPGM or UPDSRVPGM commands. With these commands you can add or
replace one or more modules without having to re-create the program object.
*PGM(X)
RPG
*PGM(Y)
RPG *MODULE(Y1)
RPG *MODULE(Y2)
RPG *MODULE(Y3)
RPG *MODULE(Y4)
The call from program X to program Y is a dynamic call. The calls among the
modules in program Y are static calls.
See “Effect of ILE” on page 26 for details on the effects of ILE on the way your
application handles calls, data, files and errors.
CL *MODULE(Y1)
RPG *MODULE(Y2)
RPG *MODULE(Y4)
The call from program Y to the OPM API is a dynamic call. The calls among the
modules in program Y are static calls.
See “Effect of ILE” on page 26 for details on the effects of ILE on the way your
application handles calls, data, files and errors.
*SRVPGM(Z)
C *MODULE(Z1)
CL *MODULE(Z2)
The calls from program X to service programs Y and Z are static calls.
See “Effect of ILE” on page 26 for details on the effects of ILE on the way your
application handles calls, data, files and errors.
Related Information
Two-step creation process Chapter 7, “Creating a Program with the
CRTRPGMOD and CRTPGM Commands”
on page 73
Activation groups “Managing Activation Groups” on page 109
ILE static binding Chapter 10, “Calling Programs and
Procedures” on page 129; also ILE Con-
cepts
Exception Handling Chapter 12, “Handling Exceptions” on
page 217; also ILE Concepts
Service programs Chapter 8, “Creating a Service Program” on
page 91; also ILE Concepts
Updating a Program “Using the UPDPGM Command” on
page 87
A Strategy to Avoid
ILE provides many alternatives for creating programs and applications. However,
not all are equally good. In general, you should avoid a situation where an applica-
tion consisting of OPM and ILE programs is split across the OPM default activation
group and a named activation group. In other words, try to avoid the scenario
shown in Figure 11 on page 32.
*PGM(X)
CL
RPG
*SRVPGM(Z)
RPG
Figure 11. Scenario to Avoid. An application is split between the OPM default activation
group and a named activation group.
When split across the default activation group and any named activation group, you
are mixing OPM behavior with ILE behavior. For example, programs in the default
activation group may be expecting the ILE programs to free their resources when
the program ends. However, this will not occur until the activation group ends.
Similarly, the scope of overrides and shared ODPs will be more difficult to manage
when an application is split between the default activation group and a named one.
By default, the scope for the named group will be at the activation group level, but
for the default activation group, it can be either call level or job level, not activation
group level.
Refer to the end of this section to see where to look for more detailed information
on coding modules with multiple procedures.
Subprocedures can provide independence from other procedures because the data
items are local. Local data items are normally stored in automatic storage, which
means that the value of a local variable is not preserved between calls to the pro-
cedure.
*MODULE
Main Procedure
H specifications
F specifications Global
Main D specifications - Data items visible Scope
Source throughout module
Section I specifications
C specifications
O specifications
Subprocedure 1
P specification
D specifications - Data items visible only
Local
to Subprocedure 1
Scope
C specifications - Can access local and
global data items
P specifications
Subprocedure 2
P specification
D specifications - Data items visible
Local
only to Subprocedure 2
Scope
C specifications - Can access local and
global data items
P specifications
As the picture suggests, you can now code subprocedures to handle particular
tasks. These tasks may be needed by the main procedures or by other modules in
the application. Furthermore, you can declare temporary data items in subproce-
dures and not have to worry if you have declared them elsewhere in the module.
Prototyped Calls
To call a subprocedure, you must use a prototyped call. You can also call any
program or procedure that is written in any language in this way. A prototyped call
is one where the call interface is checked at compile time through the use of a
prototype. A prototype is a definition of the call interface. It includes the following
information:
¹ Whether the call is bound (procedure) or dynamic (program)
¹ How to find the program or procedure (the external name)
The prototype is used by the compiler to call the program or procedure correctly,
and to ensure that the caller passes the correct parameters. Figure 13 shows a
prototype for a procedure FmtCust, which formats various fields of a record into
readable form. It has two output parameters.
Figure 15 shows a call to FmtCust. Note that the names of the output parameters,
shown above in Figure 13, do not match those in the call statement. The param-
eter names in a prototype are for documentation purposes only. The prototype
serves to describe the attributes of the call interface. The actual definition of call
parameters takes place inside the procedure itself.
Using prototyped calls you can call (with the same syntax):
¹ Programs that are on the system at run time
¹ Exported procedures in other modules or service programs that are bound in
the same program or service program
¹ Subprocedures in the same module
*--------------------------------------------------------------
* CUSTNAME and CUSTNUM are formatted to look like this:
* A&P Electronics (Customer number 157)
*--------------------------------------------------------------
C EVAL Name = CUSTNAME + ' '
C + '(Customer number '
C + %trimr(NumToChr(CUSTNUM)) + ')'
The use of procedures to return values, as in the above figure, allows you to write
any user-defined function you require. In addition, the use of a prototyped call inter-
face opens up a number of new options for parameter passing.
¹ Prototyped parameters can be passed in several ways: by reference, by value
(for procedures only), or by read-only reference. The default method for RPG is
to pass by reference. However, passing by value or by read-only reference
gives you more options for passing parameters.
¹ If the prototype indicates that it is allowed for a given parameter, you may be
able to do one or more of the following:
– Pass *OMIT
– Leave out a parameter entirely
– Pass a shorter parameter than is specified (for character and graphic
parameters, and for array parameters)
InArrears
Subprocedure to determine if
customer record is in arrears
FmtCust
Subprocedure to format
customer data into report form
TIP
When coding subprocedures that use global fields, you may want to establish a
naming convention that shows the item to be global. In this example, the upper-
case field names indicate DDS fields. Another option would be to prefix 'g_', or
some other string to indicate global scope.
If the record is in arrears, the subprocedure returns '1' to the main procedure.
* Body of procedure
C *ISO MOVE DUEDATE DateDue
C CurDate SUBDUR DateDue DaysLate:*D
P InArrears E .1/
Figure 18 shows the main elements that are common to all subprocedures.
.1/ All subprocedures begin and end with procedure specifications.
.2/ After the Begin-Procedure specification (B in position 24 of the proce-
dure specification), you code a procedure interface definition. The return
value, if any, is defined on the PI specification. Any parameters are
listed after the PI specification.
.3/ Any variables or prototypes that are used by the subprocedure are
defined after the procedure interface definition.
.4/ The return value, if specified, is returned to the caller with a RETURN
operation.
.5/ If the record is not in arrears, the subprocedure returns '0' to the main
procedure.
For all subprocedures, and also for a main procedure with prototyped entry param-
eters, you need to define a procedure interface. A procedure interface definition
is a repeat of the prototype information within the definition of a procedure. It is
used to define the entry parameters for the procedure. The procedure interface
definition is also used to ensure that the internal definition of the procedure is con-
sistent with the external definition (the prototype). In the case of InArrears, there
are no entry parameters.
One of the formatting tasks requires converting a numeric field to a character field
to match the output field type. This conversion could be coded as part of the sub-
procedure itself. However, as this is a task that might be required by other reports,
we decided to code the conversion as a separate subprocedure, NumToChar.
NumToChar takes as input a numeric parameter that is passed by value. It con-
verts the number to a character field and returns that field to the caller, in this case
FmtCust.
*--------------------------------------------------------------*
* FmtCust formats CUSTNAME, CUSTNUM, STREETNAME etc into
* readable forms
*
* Parameters: Name (output)
* Address (output)
* Globals: CUSTNAME, CUSTNUM, STREETNUM, STREETNAME, CITY
STATE, ZIP
* Returns: (none)
*--------------------------------------------------------------*
P FmtCust B
D FmtCust PI
D Name 100A
D Address 100A
D ZipChar S 5A
*--------------------------------------------------------------*
* CUSTNAME and CUSTNUM are formatted to look like this:
* A&P Electronics (Customer number 157)
*--------------------------------------------------------------*
C EVAL Name = CUSTNAME + ' '
C + '(Customer number '
C + %trimr(NumToChar(CUSTNUM)) + ')'
*--------------------------------------------------------------
* STREETNUM, STREETNAME, CITY, STATE, and ZIP are formatted to look like:
* 27 Garbanzo Avenue, Smallville IN 51423
*--------------------------------------------------------------
C MOVEL ZIP ZipChar
C EVAL Address = %trimr(NumToChar(STREETNUM))
C + ' ' + %trimr(STREETNAME) + ', '
C + %trim(CITY) + ' ' + %trim(STATE)
C + ' ' + ZipChar
P FmtCust E
Note that NumToChar is a prototyped procedure, and so you might expect to see
its prototype inside of FmtCust. You could place the prototype in FmtCust.
However, we placed it in the main source section, so that it would be available to
any subprocedure we might add to ARRSRPT. This is shown later on.
Finally, consider the last subprocedure of this application, NumToChar. Notice that
NumToChar does not appear in the ARRSRPT module, that is shown in Figure 17
on page 37. We decided to place NumToChar inside another module called
Figure 20 shows the source of the module CVTPROCS. Since this is a prototyped
procedure, it needs the prototype to be available. So that the prototype can be
shared, we have placed the prototype into a /COPY file.
*=================================================================*
* Source for module CVTPROCS. This module does not have a
* main procedure, as indicated by the keyword NOMAIN.
*=================================================================*
H NOMAIN
*-----------------------------------------------------------------*
* The prototype must be available to EACH module containing
* a prototyped procedure. The /COPY pulls in the prototype
* for NumToChar.
*-----------------------------------------------------------------*
/COPY QRPGLESRC,CVTPROCP
*-----------------------------------------------------------------*
* NumToChar converts a numeric field to a character field
*
* Parameters: NUMPARM (input)
* Globals: (none)
* Returns: character string
*
* The subprocedure will be called by procedures outside of this
* module, and so the keyword EXPORT is required to indicate this.
*-----------------------------------------------------------------*
P NumToChar B EXPORT
D NumToChar PI 31A
D NUMPARM 30P 0 VALUE
* Local declarations
D POS S 5P 0
D SIGN S 1A INZ(' ')
D ZONEDS DS
D NUM 30S 0
D CHAR 30A OVERLAY(NUM)
*
* Body of procedure:
* Handle special case of zero
C IF NUMPARM = 0
C RETURN '0'
C ENDIF
* Handle negatives. Set sign to '-' and make positive.
C IF NUMPARM < 0
C EVAL NUMPARM = - NUMPARM
C EVAL SIGN = '-'
C ENDIF
* Get the input number in character form using a data structure
C EVAL NUM = NUMPARM
* Left-justify
C
C '0' CHECK CHAR POS
C EVAL CHAR = %SUBST(CHAR:POS)
* Return the value adding the sign
C RETURN %TRIML(SIGN + CHAR)
P NumToChar E
ARRSRPT *PGM
InArrears
FmtCust CUSTFILE
DDS
CVTPROCS *MODULE
NOMAIN
NumToChar CUSTRPT
DDS
*=================================================================*
* Source for module ARRSRPT. Contains a main procedure and
* two subprocedures: InArrears and FmtCust.
*
* Related Module: CVTPROCS (NumToChar called by FmtCust)
*=================================================================*
*--------------------------------------------------------------*
* F I L E S
*
* CUSTFILE - contains customer information
* CUSTRPT - printer file (using format ARREARS)
*--------------------------------------------------------------*
| FCUSTFILE IP E DISK
| FCUSTRPT O E PRINTER
Figure 22 (Part 1 of 3). ILE RPG Complete Source for ARRSRPT Module
*--------------------------------------------------------------*
* InArrears returns '1' if the customer is in arrears
*--------------------------------------------------------------*
D InArrears PR 1A
*--------------------------------------------------------------*
* FmtCust formats CUSTNAME, CUSTNUM, STREETNAME etc into
* readable forms
*--------------------------------------------------------------*
D FmtCust PR
D Name 100A
D Address 100A
*--------------------------------------------------------------*
* G L O B A L D E F I N I T I O N S
*--------------------------------------------------------------*
D CurDate S D
ICUSTREC 01
*--------------------------------------------------------------*
* M A I N P R O C E D U R E
*--------------------------------------------------------------*
C IF InArrears = '1'
C CALLP FmtCust(RPTNAME : RPTADDR)
C EVAL RPTNUM = CUSTNUM
C WRITE ARREARS
C ENDIF
C *INZSR BEGSR
C *MDY MOVEL UDATE CurDate
C ENDSR
*--------------------------------------------------------------*
* S U B P R O C E D U R E S
*--------------------------------------------------------------*
*--------------------------------------------------------------*
* InArrears
*
* Parameters: (none)
* Globals: DUEDATE, AMOUNT, CurDate
*
* Returns: '1' if the customer is in arrears
*--------------------------------------------------------------*
P InArrears B
D InArrears PI 1A
* Local declarations
D DaysLate S 10I 0
D DateDue S D
Figure 22 (Part 2 of 3). ILE RPG Complete Source for ARRSRPT Module
P InArrears E
*--------------------------------------------------------------
* FmtCust formats CUSTNAME, CUSTNUM, STREETNAME etc into
* readable forms
*
* Parameters: Name (output)
* Address (output)
* Globals: CUSTNAME, CUSTNUM, STREETNUM, STREETNAME, CITY
STATE, ZIP
* Returns: (none)
*--------------------------------------------------------------
P FmtCust B
D FmtCust PI
D Name 100A
D Address 100A
D ZipChar S 5A
*--------------------------------------------------------------
* CUSTNAME and CUSTNUM are formatted to look like this:
* A&P Electronics (Customer number 157)
*--------------------------------------------------------------
C EVAL Name = CUSTNAME + ' '
C + '(Customer number '
C + %trimr(NumToChar(CUSTNUM)) + ')'
*--------------------------------------------------------------
* StreetNum, STREETNAME, CITY, STATE, and ZIP are formatted to look like:
* 27 Garbanzo Avenue, Smallville 51423
*--------------------------------------------------------------
C MOVEL ZIP ZipChar
C EVAL Address = %trimr(NumToChar(STREETNUM))
C + ' ' + %trimr(STREETNAME) + ', '
C + %trim(CITY) + ' ' + %trim(STATE)
C + ' ' + ZipChar
P FmtCust E
Figure 22 (Part 3 of 3). ILE RPG Complete Source for ARRSRPT Module
Figure 24 and Figure 25 on page 45 show the DDS source for the files CUSTFILE
and CUSTRPT respectively.
A*================================================================*
A* FILE NAME : CUSTFILE
A* RELATED PGMS : ARRSRPT
A* DESCRIPTIONS : THIS IS THE PHYSICAL FILE CUSTFILE. IT HAS
A* ONE RECORD FORMAT CALLED CUSTREC.
A*================================================================*
A* CUSTOMER MASTER FILE -- CUSTFILE
A R CUSTREC
A CUSTNUM 5 0 TEXT('CUSTOMER NUMBER')
A CUSTNAME 20 TEXT('CUSTOMER NAME')
A STREETNUM 5 0 TEXT('CUSTOMER ADDRESS')
A STREETNAME 20 TEXT('CUSTOMER ADDRESS')
A CITY 20 TEXT('CUSTOMER CITY')
A STATE 2 TEXT('CUSTOMER STATE')
A ZIP 5 0 TEXT('CUSTOMER ZIP CODE')
A AMOUNT 10 2 TEXT('AMOUNT OUTSTANDING')
A DUEDATE 10 TEXT('DATE DUE')
Coding Considerations
This section presents some considerations that you should be aware of before you
begin designing applications with multiple-procedure modules. The items are
grouped into the following categories:
¹ General
¹ Program Creation
¹ Main Procedures
¹ Subprocedures
General Considerations
¹ When coding a module with multiple procedures, you will want to make use of
/COPY files, primarily to contain any prototypes that your application may
require. If you are creating a service program, you will need to provide both the
service program and the prototypes, if any.
¹ Maintenance of the application means ensuring that each component is at the
most current level and that any changes do not affect the different pieces. You
may want to consider using a tool such as Application Development Manager
to maintain your applications.
For example, suppose that another programmer makes a change to the /COPY
file that contains the prototypes. When you request a rebuild of your applica-
tion, any module or program that makes use of the /COPY file will be recom-
piled automatically. You will find out quickly if the changes to the /COPY file
affect the calls or procedure interfaces in your application. If there are compila-
tion errors, you can then decide whether to accept the change to prototypes to
avoid these errors, or whether to change the call interface.
Subprocedure Considerations
¹ Any of the calculation operations may be coded in a subprocedure. However,
all files must be defined globally, so all input and output specifications must be
defined in the main source section. Similarly, all data areas must be defined in
the main procedure, although they can be used in a subprocedure.
¹ The control specification can only be coded in the main source section since it
controls the entire module.
¹ A subprocedure can be called recursively. Each recursive call causes a new
invocation of the procedure to be placed on the call stack. The new invocation
has new storage for all data items in automatic storage, and that storage is
unavailable to other invocations because it is local. (A data item that is defined
in a subprocedure uses automatic storage unless the STATIC keyword is speci-
fied for the definition.)
Main Procedures
Topic See
Exception handling “Exception Handling within a Main Procedure” on
page 220
Main Procedure End “Returning from a Main Procedure” on page 153
Subprocedures
Topic See
Defining Chapter on subprocedures, in the ILE RPG for AS/400
Reference
NOMAIN module “Creating a NOMAIN Module” on page 75
Exception handling “Exception Handling within Subprocedures” on
page 221
Procedure Specification Chapter on procedure specifications, in the ILE RPG for
AS/400 Reference
Procedure Interface Chapter on defining data and prototypes in the ILE
RPG for AS/400 Reference
Subprocedure End “Returning from a Subprocedure” on page 156
Many ILE terms and concepts are discussed briefly in the following pages. These
terms and concepts are more fully discussed in ILE Concepts.
To enter RPG source statements into the system, use one of the following
methods:
¹ Interactively using SEU
¹ Interactively using CODE/400
Initially, you may want to enter your source statements into a file called
QRPGLESRC. New members of the file QRPGLESRC automatically receive a
default type of RPGLE. Furthermore, the default source file for the ILE RPG com-
mands that create modules and bind them into program objects is QRPGLESRC.
IBM supplies a source file QRPGLESRC in library QGPL. It has a record length of
112 characters.
Note: You can use mixed case when entering source. However, the ILE RPG
compiler will convert most of the source to uppercase when it compiles it. It
will not convert literals, array data or table data.
To create a library, use the CRTLIB command. To create a source physical, use
the Create Source Physical file (CRTSRCPF) command. The recommended record
length of the file is 112 characters. This record length takes into account the new
ILE RPG structure as shown in Figure 26.
12 80 20
Since the system default for a source physical file is 92 characters, you should
explicitly specify a minimum record length of 112. If you specify a length less than
92 characters, the program may not compile since you may be truncating source
code.
For more information about creating libraries and source physical files, refer to the
ADTS/400: Source Entry Utility manual and the ADTS/400: Programming Develop-
ment Manager manual.
If you name your source file QRPGLESRC, SEU automatically sets the source type
to RPGLE when it starts the editing session for a new member. Otherwise, you
have to specify RPGLE when you create the member.
If you need prompting after you type STRSEU, press F4. The STRSEU display
appears, lists the parameters, and supplies the default values. If you supply param-
eter values before you request prompting, the display appears with those values
filled in.
In the following example you enter source statements for a program which will print
employee information from a master file. This example shows you how to:
¹ Create a library
¹ Create a source physical file
¹ Start an SEU editing session
¹ Enter source statements.
1. To create a library called MYLIB, type:
CRTLIB LIB(MYLIB)
Entering OPTION(2) indicates that you want to start a session for a new
member. The STRSEU command creates a new member EMPRPT in file
QRPGLESRC in library MYLIB and starts an edit session.
The SEU Edit display appears as shown in Figure 27 on page 53. Note that
the screen is automatically shifted so that position 6 is (for specification type) at
the left edge.
4. Type the following source in your SEU Edit display, using the following SEU
prefix commands to provide prompting:
¹ IPF — for file description specifications
¹ IPD — for definition specifications
¹ IPI — for input specifications
¹ IPC — for calculation specifications
¹ IPCX — for calculation specifications with extended Factor 2
¹ IPO — for output specifications
¹ IPP — for output specifications continuation
¹ IPPR — for procedure specifications
D TYPE S 8A
D EMPTYPE PR 8A
D CODE 1A
IEMPREC 01
Figure 29 on page 55 shows the DDS which is referenced by the EMPRPT source.
To create a program from this source use the CRTBNDRPG command, specifying
DFTACTGRP(*NO).
You must enter a separate command to process the SQL statements. Refer to the
DB2 for AS/400 SQL Programming manual and the DB2 for AS/400 SQL Refer-
ence for more information.
Refer to the ADTS/400: Source Entry Utility manual for information about how SEU
handles SQL statement syntax checking.
Whether you obtain a program of the first type or the second type depends on
whether the DFTACTGRP parameter of CRTBNDRPG is set to *YES or *NO
respectively.
Creating a program of the first type produces a program that behaves like an OPM
program in the areas of open scoping, override scoping, and RCLRSC. This high
degree of compatibility is due in part to its running in the same activation group as
OPM programs, namely, in the default activation group.
However, with this high compatibility comes the inability to have static binding.
Static binding refers to the ability to call procedures (in other modules or service
programs) and to use procedure pointers. The inability to have static binding means
that you cannot:
¹ Use the CALLB operation in your source
¹ Call a prototyped procedure
¹ Bind to other modules during program creation
Creating a program of the second type produces a program with ILE characteristics
such as static binding. You can specify at program-creation time the activation
group the program is to run in, and any modules for static binding. In addition, you
can call procedures from your source.
The command starts the ILE RPG compiler and creates a temporary module object
in the library QTEMP. It then binds it into a program object of type *PGM. Once the
program object is created, the temporary module used to create the program is
deleted.
The CRTBNDRPG command is useful when you want to create a program object
from standalone source code (code that does not require modules to be bound
together), because it combines the steps of creating and binding. Furthermore, it
allows you to create an OPM-compatible program.
Note: If you want to keep the module object in order to bind it with other modules
into a program object, you must create the module using the CRTRPGMOD
Table 3 (Page 1 of 2). CRTBNDRPG Parameters and Their Default Values Grouped by Function
Program Identification
PGM(*CURLIB/*CTLSPEC) Determines created program name and library
SRCFILE(*LIBL/QRPGLESRC) Identifies source file and library
SRCMBR(*PGM) Identifies file member containing source specifications
TEXT(*SRCMBRTXT) Provides brief description of program
Program Creation
GENLVL(10) Conditions program creation to error severity (0-20)
OPTION(*GEN) *GEN/*NOGEN, determines if program is created
DBGVIEW(*STMT) Specifies type of debug view, if any, to be included in
program
OPTIMIZE(*NONE) Determines level of optimization, if any
REPLACE(*YES) Determines if program should replace existing program
BNDDIR(*NONE) Specifies the binding directory to be used for symbol
resolution
USRPRF(*USER) Specifies the user profile that will run program
AUT(*LIBCRTAUT) Specifies type of authority for created program
TGTRLS(*CURRENT) Specifies the release level the object is to be run on
ENBPFRCOL(*PEP) Specifies whether performance collection is enabled
DEFINE(*NONE) Specifies condition names that are defined before the
compilation begins
| PRFDTA(*NOCOL) Specifies the program profiling data attribute
Compiler Listing
OUTPUT(*PRINT) Determines if there is a compiler listing
INDENT(*NONE) Determines if indentation should show in listing, and
identifies character for marking it
OPTION(*XREF *NOSECLVL Specifies the contents of compiler listing
*SHOWCPY *NOSHOWSKP *EXPDDS
*EXT)
Data Conversion Options
CVTOPT(*NONE) Specifies how various data types from externally
described files are handled
ALWNULL(*NO) Determines if the program will accept values from null-
capable fields
See Appendix C, “The Create Commands” on page 405 for the syntax diagram
and parameter descriptions of CRTBNDRPG.
The program will be created in the library MYLIB with the same name as the
source member on which it is based, namely, EMPRPT. Note that by default, it
will run in the default named activation group, QILE. This program object can
be debugged using a source view.
2. To debug the program type:
STRDBG EMPRPT
Figure 31 on page 60 shows the screen which appears after entering the
above command.
From this screen (the Display Module Source display) you can enter debug
commands to display or change field values and set breakpoints to control
program flow while debugging.
Assume that you want to bind the program COMPUTE to services which you have
purchased to perform advanced mathematical computations. The binding directory
to which you must bind your source is called MATH. This directory contains the
name of a service program that contains the various procedures that make up the
services.
The source will be bound to the service program specified in the binding directory
MATH at program-creation time. This means that calls to the procedures in the
service program will take less time than if they were dynamic calls.
When the program is called, it will run in the named activation group GRP1. The
default value ACTGRP parameter on CRTBNDRPG is QILE. However, it is recom-
mended that you run your application as a unique group to ensure that the associ-
ated resources are fully protected.
Note: DFTACTGRP must be set to *NO in order for you to enter a value for the
ACTGRP and BNDDIR parameters.
H DATEDIT(*DMY/)
*------------------------------------------------------------------------*
* File Definitions *
*------------------------------------------------------------------------*
FTRANSACT IP E K DISK
FEMPLOYEE IF E K DISK
FQSYSPRT O F 80 PRINTER
*------------------------------------------------------------------------*
* Variable Declarations *
*------------------------------------------------------------------------*
D Pay S 8P 2
*------------------------------------------------------------------------*
* Constant Declarations *
*------------------------------------------------------------------------*
D Heading1 C 'NUMBER NAME RATE H-
D OURS BONUS PAY '
D Heading2 C '______ ________________ ______ _-
D ____ _______ __________'
*------------------------------------------------------------------------*
* For each record in the transaction file (TRANSACT), if the employee *
* is found, compute the employees pay and print the details. *
*------------------------------------------------------------------------*
C TRN_NUMBER CHAIN EMP_REC 99
C IF NOT *IN99
C EVAL (H) Pay = EMP_RATE * TRN_HOURS + TRN_BONUS
C ENDIF
See Appendix D, “Compiler Listings” on page 423 for more information on the dif-
ferent parts of the listing and for a complete sample listing.
| If any compile option keywords are specified on the control specification, the com-
| piler options in effect will appear in the source section of the listing.
You can specify heading information on the compiler listing through the use of the
/TITLE compiler directive. This directive allows you to specify text which will appear
at the top of each page of the compiler listing. This information will precede the
usual page heading information. If the directive is the first record in the source
member, then this information will also appear in the prologue section.
You can also change the date separator, date format, and time separator used in
the page heading and other information boxes throughout the listing. Normally, the
compiler determines these by looking at the job attributes. To change any of these,
use the Change Job (CHGJOB) command. After entering this command you can:
¹ Select one of the following date separators: *SYSVAL, *BLANK, slash (/),
hyphen (-) period (.) or comma (,)
¹ Select one of the following date formats: *SYSVAL, *YMD, *MDY, *DMY, or
*JUL
¹ Select one of the following time separators: *SYSVAL, *BLANK, colon (:),
comma (,) or period (.)
Anywhere a date or time field appears in the listing, these values are used.
You can control the spacing and pagination of the compiler listing through the use
of the /EJECT and /SPACE compiler directives. The /EJECT directive forces a page
break. The /SPACE directive controls line spacing within the listing. For more infor-
mation on these directives refer to the ILE RPG for AS/400 Reference.
For example, to specify that you want structured operations to be indented and
marked with a vertical bar (|) followed by a space, you specify INDENT('| ').
If you request indentation, then some of the information which normally appears in
the source listing is removed, so as to allow for the indentation. The following
columns will not appear in the listing:
¹ Do Num
If you specify indentation and you also specify a listing debug view, the indentation
will not appear in the debug view.
Figure 33 shows part of source listing which was produced with indentation. The
indentation mark is '| '.
In-line diagnostic messages, which are found in the source section, point to errors
which the compiler can flag immediately. Other errors are flagged after additional
information is received during compilation. The messages which flag these errors
are in the source section and Additional Messages section.
To aid you in correcting any compilation errors, you may want to include the
second-level message text in the listing — especially if you are new to RPG. To do
this, specify OPTION(*SECLVL) on either create command. This will add second-
level text to the messages listed in the message summary.
Finally, keep in mind that a compiler listing is a record of your program. Therefore,
if you encounter any errors when testing your program, you can use the listing to
Line <---------------------- Source Specifications ----------------------------><---- Comments ----> Do Page Change Src Seq
Number ....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10 Num Line Date Id Number
Errors are listed in the order in which they are found. As a general rule, you should
focus on correcting the first few severity 30 and 40 errors, since these are often the
cause of other errors.
Non-finger in-line diagnostic messages also indicate errors. However, they are not
issued immediately following the line in error. Figure 35 on page 68 shows an
example of the non-finger in-line diagnostic messages.
In this example, FLD1 is defined like FLD2 with a length 5 bytes greater. Later,
FLD2 is defined as a date, which makes the length adjustment in the definition of
FLD1 invalid. Message RNF3479 is issued pointing at listing line 1. Note that the
SEU sequence number (000100) is also given, to aid you in finding the source line
in error more quickly. (The SEU sequence number can also be found at listing line
1).
While browsing the compiler listing, you can scan for errors and correct those
source statements that have errors. To scan for errors, type F *ERR on the SEU
command line of the browse session. The line with the first (or next) error is high-
lighted and the first-level text of the same message appears at the bottom of the
screen. You can see the second-level text by placing your cursor on the message
at the bottom and then pressing F1 (Help).
When possible, the error messages in the listing identify the SEU sequence number
of the line in error. The sequence number is found just before the message text.
If you have a /COPY member, you can find the source ID number of the actual file
in the /COPY Member table at the end of the listing. For an example of a /COPY
Member table, see “/COPY Member Table” on page 431.
In either case it is advisable to have a full listing, namely, one produced with
OUTPUT(*PRINT) and with OPTION(*XREF *SHOWCPY *SHOWSKP *EXPDDS
*EXT).
Note: Except for *SHOWSKP, this is the default setting for each of these parame-
ters on both create commands.
Of particular value for program maintenance is the Prologue section of the listing.
This section tells you:
¹ who compiled the module/program
¹ what source was used to produce the module/program
¹ what options were used when compiling the module/program
You may need to know about the command options (for example, the debug view
selected, or the binding directory used) when you make later changes to the
program.
The following specifications for the OPTION parameter provide additional informa-
tion as indicated:
¹ *SHOWCPY and *EXPDDS provide a complete description of the program,
including all specifications from /COPY members, and generated specifications
from externally described files.
¹ *SHOWSKP allows you to see the statements that are ignored by the compiler
as a result of /IF, /ELSEIF, /ELSE, OR /EOF directives.
¹ *XREF allows you to check the use of files, fields and indicators within the
module/program.
An ILE RPG module consists of one or more procedures, and the file control blocks
and static storage used by all the procedures in the module. The procedures that
can make up an ILE RPG module are:
¹ an optional main procedure which consists of the set of H, F, D, I, C, and O
specifications that begin the source. The main procedure has its own LR
semantics and logic cycle; neither of which is affected by those of other ILE
RPG modules in the program.
¹ zero or more subprocedures, which are coded on P, D, and C specifications.
Subprocedures do not use the RPG cycle. A subprocedure may have local
storage that is available for use only by the subprocedure itself.
The main procedure (if coded) can always be called by other modules in the
program. Subprocedures may be local to the module or exported. If they are local,
they can only be called by other procedures in the module; if they are exported
from the module, they can be called by any procedure in the program.
A module cannot be run by itself. You must bind one or more modules together to
create a program object (type *PGM) which can then be run. You can also bind one
or more modules together to create a service program object (type *SRVPGM). You
then access the procedures within the bound modules through static procedure
calls.
For more information about the concept of modules, refer to ILE Concepts.
If you are using the command interactively and need prompting, type
CRTRPGMOD and press F4 (Prompt). If you need help, type CRTRPGMOD and
press F1 (Help).
Table 4 lists the parameters of the CRTRPGMOD command and their system-
supplied defaults. The syntax diagram of the command and a description of the
parameters are found in Appendix C, “The Create Commands” on page 405.
Table 4 (Page 1 of 2). CRTRPGMOD Parameters and Their Default Values Grouped by Function
Module Identification
MODULE(*CURLIB/*CTLSPEC) Determines created module name and library
SRCFILE(*LIBL/QRPGLESRC) Identifies source file and library
SRCMBR(*MODULE) Identifies file member containing source specifications
TEXT(*SRCMBRTXT) Provides brief description of module
Module Creation
GENLVL(10) Conditions module creation to error severity (0-20)
OPTION(*GEN) *GEN/*NOGEN, determines if module is created
DBGVIEW(*STMT) Specifies type of debug view, if any, to be included in
module
OPTIMIZE(*NONE) Determines level of optimization, if any
REPLACE(*YES) Determines if module should replace existing module
AUT(*LIBCRTAUT) Specifies type of authority for created module
TGTRLS(*CURRENT) Specifies the release level the object is to be run on
| BNDDIR(*NONE) Specifies the binding directory to be used for symbol
| resolution
ENBPFRCOL(*PEP) Specifies whether performance collection is enabled
DEFINE(*NONE) Specifies condition names that are defined before the
compilation begins
For information on using the compiler listing, see “Using a Compiler Listing” on
page 63. A sample compiler listing is provided in Appendix D, “Compiler Listings”
on page 423.
The module will be created in the library MYLIB with the name specified in the
command, TRANSSVC. The source for the module is the source member
TRANSSVC in file QRPGLESRC in the library MYLIB.
You bind a module containing NOMAIN to another module using one of the
following commands:
a. CRTPGM command
*=================================================================*
* MODULE NAME: TRANSSVC (Transaction Services)
* RELATED FILES: N/A
* RELATED SOURCE: TRANSRPT
* EXPORTED PROCEDURES: Trans_Inc -- calculates the income
* for the transaction using the data in the fields in the
* parameter list. It returns to the caller after all
* the calculations are done.
*
* Prod_Name -- retrieves the product name based on the
* input parameter with the product number.
*=================================================================*
* This module contains only subprocedures; it is a NOMAIN module.
H NOMAIN
*------------------------------------------------------------------
* Pull in the prototypes from the /COPY member
*------------------------------------------------------------------
/COPY TRANSP
D Factor S 5P 0
*
C SELECT
C WHEN ProdNum = 1
C EVAL Factor = 1500
C WHEN ProdNum = 2
C EVAL Factor = 3500
C WHEN ProdNum = 5
C EVAL Factor = 20000
C WHEN ProdNum = 8
C EVAL Factor = 32000
C WHEN ProdNum = 12
C EVAL Factor = 64000
C OTHER
C EVAL Factor = 0
C ENDSL
P Trans_Inc E
*------------------------------------------------------------------
* Subprocedure Prod_Name
*------------------------------------------------------------------
P Prod_Name B EXPORT
D Prod_Name PI 40A
D ProdNum 10P 0 VALUE
*
C SELECT
C WHEN ProdNum = 1
C RETURN 'Large'
C WHEN ProdNum = 2
C RETURN 'Super'
C WHEN ProdNum = 5
C RETURN 'Super Large'
C WHEN ProdNum = 8
C RETURN 'Super Jumbo'
C WHEN ProdNum = 12
C RETURN 'Incredibly Large Super Jumbo'
C OTHER
C RETURN '***Unknown***'
C ENDSL
P Prod_Name E
The module is created in the library MYLIB with the same name as the source file
on which it is based, namely, TRANSRPT. This module object can be debugged
using a source view. For information on the other views available, see “Preparing a
Program for Debugging” on page 166.
/COPY QRPGLE,TRANSP
D Income S 10P 2
D Total S +5 LIKE(Income)
*
ITRNSREC 01
OQSYSPRT H 1P 1
O OR OF
O 12 'Product name'
O 40 'Quantity'
O 54 'Income'
OQSYSPRT H 1P 1
O OR OF
O 30 '----------+
O ----------+
O ----------'
O 40 '--------'
O 60 '------------'
OQSYSPRT D 01 1
O ProdName 30
O QTY 1 40
O Income 1 60
OQSYSPRT T LR 1
O 'Total: '
O Total 1
The DDS for the file TRNSDTA is shown in Figure 39 on page 80. The /COPY
member is shown in Figure 37 on page 78.
Additional Examples
For additional examples of creating modules, see:
¹ “Sample Service Program” on page 94, for an example of creating a module
for a service program.
¹ “Binding to a Program” on page 98. for an example of creating a module to be
used with a service program.
¹ “Managing Your Own Heap Using ILE Bindable APIs” on page 120, for an
example of creating a module for dynamically allocating storage for a run-time
array
¹ “Sample Source for Debug Examples” on page 211, for example of creating an
RPG and C module for use in a sample debug program.
In any ILE program, there may be several RPG cycles active; there is one RPG
cycle for each RPG module that has a main procedure. The cycles are
independent: setting on LR in one main procedure has no effect on the cycle in
another.
Related CL Commands
The following CL commands can be used with modules:
¹ Display Module (DSPMOD)
¹ Change Module (CHGMOD)
¹ Delete Module (DLTMOD)
¹ Work with Modules (WRKMOD)
As part of the binding process, a procedure must be identified as the startup proce-
dure, or program entry procedure. When a program is called, the program entry
procedure receives the parameters from the command line and is given initial
control for the program. The user's code associated with the program entry proce-
dure is the user entry procedure.
Figure 40 gives an idea of the internal structure of a program object. It shows the
program object TRPT, which was created by binding the two modules TRANSRPT
and TRANSSVC. TRANSRPT is the entry module.
*PGM ( TRPT)
TRANSRPT Module
Program Entry
Procedure
Main Procedure
TRANSSVC Module
Trans_Inc
Prod_Name
Within a bound object, procedures can interrelate using static procedure calls.
These bound calls are faster than external calls. Therefore, an application con-
sisting of a single bound program with many bound calls should perform faster than
a similar application consisting of separate programs with many external interappli-
cation calls.
For information on the binding process and the binder, refer to the ILE Concepts.
Before you create a program object using the CRTPGM command, you should:
1. Establish a program name.
2. Identify the module or modules, and if required, service programs you want to
bind into a program object.
3. Identify the entry module.
You indicate which module contains the program entry procedure through the
ENTMOD parameter of CRTPGM. The default is ENTMOD(*FIRST), meaning
that the module containing the first program entry procedure found in the list for
the MODULE parameter is the entry module.
Assuming you have only one module with a main procedure, that is, all
modules but one have NOMAIN specified, you can accept the default (*FIRST).
Alternatively, you can specify (*ONLY); this will provide a check that in fact only
one module has a main procedure. For example, in both of the following situ-
ations you could specify ENTMOD(*ONLY).
¹ You bind an RPG module to a C module without a main() function.
¹ You bind two RPG modules, where one has NOMAIN on the control spec-
ification.
Note: If you are binding more than one ILE RPG module with a main proce-
dure, then you should specify the name of the module that you want to
receive control when the program is called. You can also specify
*FIRST if the module with a main procedure precedes any other
modules with main procedures on the list specified for the MODULE
parameter.
4. Identify the activation group that the program is to use.
Specify the named activation group QILE if your program has no special
requirements or if you are not sure which group to use. In general, it is a good
idea to run an application in its own activation group. Therefore, you may want
to name the activation group after the application.
Note that the default activation group for CRTPGM is *NEW. This means that
your program will run in its own activation group, and the activation group will
To create a program object using the CRTPGM command, perform the following
steps:
1. Enter the CRTPGM command.
2. Enter the appropriate values for the command parameter.
Table 5 lists the CRTPGM command parameters and their default values. For a
full description of the CRTPGM command and its parameters, refer to the CL Ref-
erence.
Once you have entered the CRTPGM command, the system performs the following
actions:
1. Copies listed modules into what will become the program object, and links any
service programs to the program object.
2. Identifies the module containing the program entry procedure, and locates the
first import in this module.
3. Checks the modules in the order in which they are listed, and matches the first
import with a module export.
4. Returns to the first module, and locates the next import.
5. Resolves all imports in the first module.
6. Continues to the next module, and resolves all imports.
7. Resolves all imports in each subsequent module until all of the imports have
been resolved.
8. If any imports cannot be resolved with an export, the binding process termi-
nates without creating a program object.
The CRTPGM command creates a program object TRPT in the library MYLIB.
The program TRPT will run in the named activation group TRPT. The program runs
in a named group to ensure that no other programs can affect its resources.
Additional Examples
For additional examples of creating programs, see:
¹ “Binding to a Program” on page 98, for an example of binding a module and a
service program.
¹ “Sample Source for Debug Examples” on page 211, for an example of creating
a program consisting of an RPG and C module.
Related CL Commands
The following CL commands can be used with programs:
¹ Change Program (CHGPGM)
¹ Delete Program (DLTPGM)
¹ Display Program (DSPPGM)
¹ Display Program References (DSPPGMREF)
¹ Update Program (UPDPGM)
¹ Work with Program (WRKPGM)
The binder listing includes the following sections depending on the value specified
for DETAIL:
The information in this listing can help you diagnose problems if the binding was
not successful, or give feedback about what the binder encountered in the process.
You may want to store the listing for an ILE program in the file where you store the
modules or the module source for a program. To copy this listing to a database file,
you can use the Copy Spool File (CPYSPLF) command.
Note: The CRTBNDRPG command will not create a binder listing. However, if any
binding errors occur during the binding phase, the errors will be noted in
your job log, and the compiler listing will include a message to this effect.
For an example of a basic binder listing, see “Sample Binder Listing” on page 100.
Finally, you may want to reduce the program size once you have completed an
application. ILE programs have additional data added to them which may make
them larger than a similar OPM program.
Each of the above requires different data to make the change. The resources you
need may not be available to you for an ILE program.
The UPDPGM command works with both program and module objects. The param-
eters on the command are very similar to those on the CRTPGM command. For
example, to replace a module in a program, you would enter the module name for
MODULE parameter and the library name. The UPDPGM command requires that
the modules to be replaced be in the same libraries as when the program was
created. You can specify that all modules are to be replaced, or some subset.
The UPDPGM command requires that the module object be present. Thus, it is
easier to use the command when you have created the program using separate
compile and bind steps. Since the module object already exists, you simply specify
its name and library when issuing the command.
However, at higher levels of optimization, the values of fields may not be accurate
when displayed in a debug session, or after recovery from exception. In addition,
optimized code may have altered breakpoints and step locations used by the
source debugger, since the optimization changes may rearrange or eliminate some
statements.
To ensure that the contents of a field reflect their most current value, especially
after exception recovery, you can use the NOOPT keyword on the corresponding
Definition specification. For more information, see “Optimization Considerations” on
page 226.
To circumvent this problem while debugging, you can lower the optimization level of
a module to display fields accurately as you debug a program, and then raise the
To determine the current optimization level of a program object, use the DSPPGM
command. Display 3 of this command indicates the current level. To change the
optimization level of a program, use the CHGPGM command. On the Optimize
program parameter you can specify one the following values: *FULL, *BASIC,
*NONE. These are the same values which can be specified on the OPTIMIZE
parameters of either create command. The program is automatically re-created
when the command runs.
Similarly, to determine the current optimization level of a module, use the DSPMOD
command. Display 1, page 2 of this command indicates the current level. To
change the optimization level, use the CHGMOD command. You then need to re-
create the program either using UPDPGM or CRTPGM.
Removing Observability
| Observability involves the kinds of data that can be stored with an object, and that
| allow the object to be changed without recompiling the source. The addition of this
| data increases the size of the object. Consequently, you may want to remove the
| data in order to reduce object size. But once the data is removed, observability is
| also removed. You must recompile the source and recreate the program to replace
| the data. The types of data are:
| Create Data
| Represented by the *CRTDTA value. This data is necessary to translate
| the code to machine instructions. The object must have this data before
| you can change the optimization level.
| Debug Data
| Represented by the *DBGDTA value. This data is necessary to allow an
| object to be debugged.
| Profiling Data
| Represented by the *BLKORD and *PRCORD values. This data is nec-
| essary to allow the system to re-apply block order and procedure order
| profiling data.
| Use the CHGPGM command or the CHGMOD command to remove some or all the
| data from a program or module respectively. Removing all observability reduces an
| object to its minimum size (without compression). It is not possible to change the
| object in any way unless you re-create it. Therefore, ensure that you have all
| source required to create the program or have a comparable program object with
| CRTDATA. To re-create it, you must have authorization to access the source code.
If you remove the data, ensure that you have all source required to create the
program or have a comparable program object with CRTDATA. Otherwise you will
not be able to change the object.
Service programs are typically used for common functions that are frequently called
within an application and across applications. For example, the ILE compilers use
service programs to provide run-time services such as math functions and
input/output routines. Service programs enable reuse, simplify maintenance, and
reduce storage requirements.
When you bind a service program to a program, the contents of the service
program are not copied into the bound program. Instead, linkage information of the
service program is bound into the program. This is called 'binding by reference' in
contrast to the static binding process used to bind modules into programs.
Because a service program is bound by reference to a program, you can call the
service program's exported procedures using bound procedure calls. The initial call
has a certain amount of overhead because the binding is not completed until the
service program is called. However, subsequent calls to any of its procedures are
faster than program calls.
The set of exports contained in a service program are the interface to the services
provided by it. You can use the Display Service Program (DSPSRVPGM) command
or the service program listing to see what variable and procedure names are avail-
able for use by the calling procedures. To see the exports associated with service
program PAYROLL, you would enter:
DSPSRVPGM PAYROLL DETAIL(*PROCEXP *DATAEXP)
If the interface to a service program changes, then you may have to re-bind any
programs bound to the original service program. However, if the changes required
are upward-compatible, you may be able to reduce the amount of re-binding if you
created the service program using binder language. In this case, after updating the
binder language source to identify the new exports you need to re-bind only those
programs that use them.
TIP
If you are planning a module with only subprocedures (that is, with a module
with keyword NOMAIN specified on the control specification) you may want to
create it as a service program. Only one copy of a service program is needed
on a system, and so you will need less storage for the module.
Also, you can copyright your service programs using the COPYRIGHT keyword
on the control specification.
Binder language gives you control over the exports of a service program. This
control can be very useful if you want to:
¹ Mask certain service program procedures from service-program users
¹ Fix problems
¹ Enhance function
¹ Reduce the impact of changes to the users of an application.
See “Sample Service Program” on page 94 for an example of using binder lan-
guage to create a service program.
For information on binder language, masking exports, and other service program
concepts, see ILE Concepts.
Table 7 on page 93 lists the CRTSRVPGM parameters and their defaults. For a
full description of the CRTSRVPGM command and its parameters, refer to the CL
Reference.
See “Creating the Service Program” on page 97 for an example of using the
CRTSRVPGM command.
For more information on any of the above points, see “Changing a Module or
Program” on page 86.
Related CL commands
The following CL commands are also used with service programs:
¹ Change Service Program (CHGSRVPGM)
¹ Display Service Program (DSPSRVPGM)
¹ Delete Service Program (DLTSRVPGM)
¹ Update Service Program (UPDSRVPGM)
¹ Work with Service Program (WRKSRVPGM)
The field HexString is used to contain the result of the conversion and also to indi-
cate the length of the string to be converted. For example, if a character string of
30 characters is passed, but you are only interested in converting the first ten, you
would pass a second parameter of 20 bytes (2 times 10). Based on the length of
the passed fields, the service program determines the length to handle.
Figure 42 on page 95 shows the source for the service program. Figure 43 on
page 97 shows the /COPY member containing the prototype for CvtToHex.
The basic logic of the procedure contained within the service program is listed
below:
1. Operational descriptors are used to determine the length of the passed param-
eters.
2. The length to be converted is determined: it is the lesser of the length of the
character string, or one-half the length of the hex string field.
3. Each character in the string is converted to a two-byte hexadecimal equivalent
using the subroutine GetHex.
Note that GetHex is coded as a subroutine rather than a subprocedure, in order
to improve run-time performance. An EXSR operation runs much faster than a
bound call, and in this example, GetHex is called many times.
4. The procedure returns to its caller.
The service program makes use of operational descriptors, which is an ILE con-
struct used when the precise nature of a passed parameter is not known ahead of
time, in this case the length. The operational descriptors are created on a call to a
procedure when you specify the operation extender (D) on the CALLB operation, or
when OPDESC is specified on the prototype.
To use the operational descriptors, the service program must call the ILE bindable
API, CEEDOD (Retrieve Operational Descriptor). This API requires certain parame-
ters which must be defined for the CALLB operation. However, it is the last param-
eter which provides the information needed, namely, the length. For more
information on operational descriptors, see “Using Operational Descriptors” on
page 140.
D/COPY RPGGUIDE/QRPGLE,CVTHEXPR
*-----------------------------------------------------------------*
* Main entry parameters
* 1. Input: string character(n)
* 2. Output: hex string character(2 * n)
*-----------------------------------------------------------------*
D CvtToHex PI OPDESC
D InString 16383 CONST OPTIONS(*VARSIZE)
D HexString 32766 OPTIONS(*VARSIZE)
*-----------------------------------------------------------------*
* Prototype for CEEDOD (Retrieve operational descriptor)
*-----------------------------------------------------------------*
D CEEDOD PR
D ParmNum 10I 0 CONST
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 10I 0
D 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------*
* Other fields used by the program *
*-----------------------------------------------------------------*
D HexDigits C CONST('0123456789ABCDEF')
D IntDs DS
D IntNum 5I 0 INZ(0)
D IntChar 1 OVERLAY(IntNum:2)
D HexDs DS
D HexC1 1
D HexC2 1
D InChar S 1
D Pos S 5P 0
D HexPos S 5P 0
*-----------------------------------------------------------------*
* Determine the length to handle (minimum of the input length *
* and half of the hex length) *
*-----------------------------------------------------------------*
C IF InLen > HexLen / 2
C EVAL InLen = HexLen / 2
C ENDIF
*-----------------------------------------------------------------*
* For each character in the input string, convert to a 2-byte *
* hexadecimal representation (for example, '5' --> 'F5') *
*-----------------------------------------------------------------*
C EVAL HexPos = 1
C DO InLen Pos
C EVAL InChar = %SUBST(InString : Pos :1)
C EXSR GetHex
C EVAL %SUBST(HexString : HexPos : 2) = HexDs
C EVAL HexPos = HexPos + 2
C ENDDO
*-----------------------------------------------------------------*
* Done; return to caller. *
*-----------------------------------------------------------------*
C RETURN
*=================================================================*
* GetHex - subroutine to convert 'InChar' to 'HexDs' *
* *
* Use division by 16 to separate the two hexadecimal digits. *
* The quotient is the first digit, the remainder is the second. *
*=================================================================*
C GetHex BEGSR
C EVAL IntChar = InChar
C IntNum DIV 16 X1 5 0
C MVR X2 5 0
*-----------------------------------------------------------------*
* Use the hexadecimal digit (plus 1) to substring the list of *
* hexadecimal characters '012...CDEF'. *
*-----------------------------------------------------------------*
C EVAL HexC1 = %SUBST(HexDigits:X1+1:1)
C EVAL HexC2 = %SUBST(HexDigits:X2+1:1)
C ENDSR
Figure 43. Source for /COPY Member with Prototype for CvtToHex
When designing this service program, it was decided to make use of binder lan-
guage to determine the interface, so that the program could be more easily updated
at a later date. shows the binder language needed to define the exports of the
| service program CVTTOHEX. This source is used in the EXPORT, SRCFILE and
| SRCMBR parameters of the CRTSRVPGM command.Figure 44
STRPGMEXP SIGNATURE('CVTHEX')
EXPORT SYMBOL('CVTTOHEX')
ENDPGMEXP
The binder language EXPORT statements identify the exports of the service
program. You need one for each procedure whose exports you want to make avail-
able to the caller. In this case, the service program contains one module which
contains one procedure. Hence, only one EXPORT statement is required.
For more information on binder language and signatures, see ILE Concepts.
2. Create the service program using the module CVTTOHEX and the binder lan-
guage shown in Figure 44.
CRTSRVPGM SRVPGM(MYLIB/CVTTOHEX) MODULE(*SRVPGM)
EXPORT(*SRCFILE) SRCFILE(MYLIB/QSRVSRC)
SRCMBR(*SRVPGM)
The last three parameters in the above command identify the exports which the
service program will make available. In this case, it is based on the source
found in the member CVTTOHEX in the file QSRVSRC in the library MYLIB.
The service program CVTTOHEX will be created in the library MYLIB. It can be
debugged using a statement view; this is determined by the default DBGVIEW
parameter on the CRTRPGMOD command. No binder listing is produced.
Binding to a Program
To complete the example, we will create an 'application' consisting of a program
CVTHEXPGM which is bound to the service program. It uses a seven-character
string which it passes to CVTTOHEX twice, once where the value of the hex string
is 10 (that is, convert 5 characters) and again where the value is 14, that is, the
actual length.
Note that the program CVTHEXPGM serves to show the use of the service
program CVTTOHEX. In a real application the caller of CVTTOHEX would have
another primary purpose other than testing CVTTOHEX. Furthermore, a service
program would normally be used by many other programs, or many times by a few
programs; otherwise the overhead of initial call does not justify making it into a
service program.
During the process of making CVTHEXPGM ready to run, the system verifies
that:
¹ The service program CVTTOHEX in library MYLIB can be found
¹ The public interface used by CVTHEXPGM when it was created is still valid
at run time.
If either of the above is not true, then an error message is issued.
FQSYSPRT O F 80 PRINTER
D ResultDS DS
D Result14 1 14
D Result10 1 10
D InString S 7
D Comment S 25
*----------------------------------------------------------------*
* Pass character string and the 10-character result field *
* using a prototyped call. Operational descriptors are *
* passed, as required by the called procedure CvtToHex. *
*----------------------------------------------------------------*
C EVAL Comment = '10 character output'
C CLEAR ResultDS
C CALLP CvtToHex(Instring : Result10)
C EXCEPT
*----------------------------------------------------------------*
* Pass character string and the 14-character result field *
* using a CALLB(D). The operation extender (D) will create *
* operational descriptors for the passed parameters. CALLB *
* is used here for comparison with the above CALLP. *
*----------------------------------------------------------------*
C EVAL Comment = '14 character output'
C CLEAR ResultDS
C CALLB(D) 'CVTTOHEX'
C PARM InString
C PARM Result14
C EXCEPT
OQSYSPRT H 1P
O 'Result14++++++'
OQSYSPRT H 1P
O 'Result10++'
OQSYSPRT E
O ResultDS
O Comment +5
With either method, new programs can access the new function. Since the old
exports are in the same order they can still be used by the existing programs. Until
it is necessary to also update the existing programs, they do not have to be re-
compiled.
* * * * * E N D O F B R I E F S U M M A R Y T A B L E * * * * *
Create Program Page 3
| 5769SS1 V4R2M0 980228 MYLIB/CVTHEXPGM AS400S01 02/30/98 23:24:00
Binding Statistics
Symbol collection CPU time . . . . . . . . . . . . . . . . . : .016
Symbol resolution CPU time . . . . . . . . . . . . . . . . . : .004
Binding directory resolution CPU time . . . . . . . . . . . : .175
Binder language compilation CPU time . . . . . . . . . . . . : .000
Listing creation CPU time . . . . . . . . . . . . . . . . . : .068
Program/service program creation CPU time . . . . . . . . . : .234
Total CPU time . . . . . . . . . . . . . . . . . . . . . . . : .995
Total elapsed time . . . . . . . . . . . . . . . . . . . . . : 3.531
* * * * * E N D O F B I N D I N G S T A T I S T I C S * * * * *
*CPC5D07 - Program CVTHEXPGM created in library MYLIB.
* * * * * E N D O F C R E A T E P R O G R A M L I S T I N G * * * * *
For example, to call the program EMPRPT from the command line, type:
CALL EMPRPT
The program object specified must exist in a library and this library must be con-
tained in the library list *LIBL. You can also explicitly specify the library in the CL
CALL command as follows:
CALL MYLIB/EMPRPT
See the CL Reference for further information about using the CL CALL command.
Once you call your program, the OS/400 system performs the instructions found in
the program.
If you are passing parameters to a program where an ILE RPG procedure is the
program entry procedure, then that program must have one and only one *ENTRY
PLIST specified. The parameters that follow (in the PARM statements) should cor-
respond on a one-to-one basis to those passed through the CALL command.
For example, the program EMPRPT2 requires the correct password to be passed
to it when it first started; otherwise it will not run. Figure 47 shows the source.
1. To create the program, type:
CRTBNDRPG PGM(MYLIB/EMPRPT2)
When the CALL command is issued, the contents of the parameter passed by
the command is stored and the program parameter PSWORD points to its
location. The program then checks to see if the contents of PSWORD matches
the value stored in the program, ('HELLO'). In this case, the two values are
the same, and so the program continues to run.
*===============================================================*
* PROGRAM NAME: EMPRPT2 *
* RELATED FILES: EMPMST (PHYSICAL FILE) *
* PRINT (PRINTER FILE) *
* DESCRIPTION: This program prints employee information *
* stored in the file EMPMST if the password *
* entered is correct. *
* Run the program by typing "CALL library name/ *
* EMPRPT2 (PSWORD)" on the command line, where *
* PSWORD is the password for this program. *
* The password for this program is 'HELLO'. *
*===============================================================*
FPRINT O F 80 PRINTER
FEMPMST IP E K DISK
IEMPREC 01
Figure 47 (Part 1 of 2). ILE RPG Program that Requires Parameters at Run Time
C *ENTRY PLIST
C PARM PSWORD 5
*-----------------------------------------------------------------*
* The password for this program is 'HELLO'. The field PSWORD *
* is checked to see whether or not it contains 'HELLO'. *
* If it does not, the last record indicator (LR) and *IN99 *
* are set on. *IN99 controls the printing of messages. *
*-----------------------------------------------------------------*
C PSWORD IFNE 'HELLO'
C SETON LR99
C ENDIF
OPRINT H 1P 2 6
O 50 'EMPLOYEE INFORMATION'
O H 1P
O 12 'NAME'
O 34 'SERIAL #'
O 45 'DEPT'
O 56 'TYPE'
O D 01N99
O ENAME 20
O ENUM 32
O EDEPT 45
O ETYPE 55
O D 99
O 16 '***'
O 40 'Invalid Password Entered'
O 43 '***'
Figure 47 (Part 2 of 2). ILE RPG Program that Requires Parameters at Run Time
A*****************************************************************
A* DESCRIPTION: This is the DDS for the physical file EMPMST. *
A* It contains one record format called EMPREC. *
A* This file contains one record for each employee *
A* of the company. *
A*****************************************************************
A*
A R EMPREC
A ENUM 5 0 TEXT('EMPLOYEE NUMBER')
A ENAME 20 TEXT('EMPLOYEE NAME')
A ETYPE 1 TEXT('EMPLOYEE TYPE')
A EDEPT 3 0 TEXT('EMPLOYEE DEPARTMENT')
A ENHRS 3 1 TEXT('EMPLOYEE NORMAL WEEK HOURS')
A K ENUM
PAYROLL DEPARTMENT MENU
Selection or command
===> _________________________________________________________________________
_______________________________________________________________________________
F3=Exit F4=Prompt F9=Retrieve F12=Cancel
F13=Information Assistant F16=AS/400 main menu
Figure 49. Example of an Application Menu
Figure 50 on page 107 shows the DDS for the display file of the above PAYROLL
DEPARTMENT MENU. The source member is called PAYROL and has a source
type of MNUDDS. The file was created using SDA.
PAYROLQQ,1
0001 call RPGINQ
0002 call RPGCHG
0003 call RPGADD
If the user enters 1, 2, or 3 from the application menu, the source in Figure 51 calls
the programs RPGINQ, RPGCHG, or RPGADD respectively.
For example, you can create a command, PAY, that calls a program, PAYROLL,
where PAYROLL is the name of an RPG program that you want to run. You can
enter the command interactively, or in a batch job. See the CL Programming
manual for further information about using command definitions.
You can add the inquiry messages to a system reply list to provide automatic
replies to the messages. The replies for these messages may be specified individ-
ually or generally. This method of replying to inquiry messages is especially suit-
able for batch programs, which would otherwise require an operator to issue
replies.
You can add the following ILE RPG inquiry messages to the system reply list:
To add inquiry messages to a system reply list using the Add Reply List Entry
command enter:
ADDRPYLE sequence-no message-id
Use the Change Job (CHGJOB) command (or other CL job command) to indicate
that your job uses the reply list for inquiry messages. To do this, you should specify
*SYSRPYL for the Inquiry Message Reply (INQMSGRPY) attribute.
The reply list is only used when an inquiry message is sent by a job that has the
Inquiry Message Reply (INQMSGRPY) attribute specified as
INQMSGRPY(*SYSRPYL). The INQMSGRPY parameter occurs on the following
CL commands:
¹ Change Job (CHGJOB)
¹ Change Job Description (CHGJOBD)
¹ Create Job Description (CRTJOBD)
¹ Submit Job (SBMJOB).
You can also use the Work with Reply List Entry (WRKRPYLE) command to
change or remove entries in the system reply list. See the CL Reference for details
of the ADDRPYLE and WRKRPYLE commands.
If an ILE program ends abnormally and the program was running in a different acti-
vation group than its caller, then the escape message CEE9901
Error message-id caused program to end.
A CL program can monitor for this exception by using the Monitor Message
(MONMSG) command. You can also monitor for exceptions in other ILE languages.
If the ILE program is running in the same activation group as its caller and it ends
abnormally, then the message issued will depend on why the program ends. If it
ends with a function check, then CPF9999 will be issued. If the exception is issued
by an RPG procedure, then it will have a message prefix of RNX.
You identify the activation group that your ILE program will run in at the time of
program creation. The activation group is determined by the value specified on the
ACTGRP parameter when the program object was created. (OPM programs always
run in the default activation group; you cannot change their activation group specifi-
cation.) Once an ILE program (object type *PGM) is activated, it remains activated
until the activation group is deleted.
The remainder of this section tells you how to specify an activation group and how
to delete one. For more information on activation groups, refer to ILE Concepts.
OPM programs automatically run in the OPM default activation group. An ILE
program will also run in the OPM default activation group when one of the following
occurs:
¹ The program was created with DFTACTGRP(*YES) on the CRTBNDRPG
command.
¹ The program was created with ACTGRP(*CALLER) at the time of program cre-
ation and the caller of the program runs in the default activation group. Note
that you can only specify ACTGRP(*CALLER) on the CRTBNDRPG command
if DFTACTGRP(*NO) is also specified.
Note: The resources associated with a program running in the OPM default acti-
vation group via *CALLER will not be deleted until the job ends.
Named activation groups (such as QILE) are persistent activation groups in that
they are not deleted unless explicitly deleted or unless the job ends. The storage
associated with programs running in named activation groups is not released until
these activation groups are deleted.
An ILE RPG program created DFTACTGRP(*YES) will have its storage released
when it ends with LR on or abnormally.
Note: The storage associated with ILE programs running in the default activation
group via *CALLER is not released until you sign off (for an interactive job)
or until the job ends (for a batch job).
If many ILE RPG programs are activated (that is called at least once) system
storage may be exhausted. Therefore, you should avoid having ILE programs that
use large amounts of static storage run in the OPM default activation group, since
the storage will not be reclaimed until the job ends.
The storage associated with a service program is reclaimed only when the acti-
vation group it is associated with ends. If the service program is called into the
default activation group, its resources are reclaimed when the job ends.
You can delete a named activation group using the RCLACTGRP command. Use
this command to delete a nondefault activation group that is not in use. The
command provides options to either delete all eligible activation groups or to delete
an activation group by name.
For more information on RCLACTGRP refer to the CL Reference. For more infor-
mation on the RCLACTGRP and activation groups, refer to ILE Concepts.
| For ILE programs or service programs that were activated into the OPM default
| activation group because they were created with *CALLER, files will be closed
| when the RCLRSC command is issued. For programs, the storage will be re-
| initialized; however, the storage will not be released. For service programs, the
| storage will neither be re-initialized nor released.
| Note: This means that if you have a service program that ran in the default acti-
| vation group and left files open (returning with LR off), and a RCLRSC is
| issued, when you call the service program again, the files will still appear to
| be open, so so any I/O operations will result in an error.
For ILE programs associated with a named activation group, the RCLRSC
command has no effect. You must use the RCLACTGRP command to free
resources in a named activation group.
You are not required to explicitly manage run-time storage. However, you may want
to do so if you want to make use of dynamically allocated run-time storage. For
example, you may want to do this if you do not know exactly how large an array or
multiple-occurrence data structure should be. You could define the array or data
structure as BASED, and acquire the actual storage for the array or data structure
once your program determines how large it should be.
There are two types of heaps available on the system: a default heap and a
user-created heap. The RPG storage management operations use the default heap.
The following sections show how to use RPG storage management operations with
the default heap, and also how to create and use your own heap using the storage
management APIs. For more information on user-created heaps and other ILE
storage management concepts refer to ILE Concepts.
Allocated dynamic storage remains allocated until it is explicitly freed or until the
heap is discarded. The default heap is discarded only when the owning activation
group ends.
Programs in the same activation group all use the same default heap. If one
program accesses storage beyond what has be allocated, it can cause problems for
another program. For example, assume that two programs, PGM A and PGM B are
running in the same activation group. 10 bytes are allocated for PGM A, but 11
bytes are changed by PGM A. If the extra byte was in fact allocated for PGM B,
problems may arise for PGM B.
You can use the following RPG operations on the default heap:
¹ The ALLOC operation allocates storage within the default heap.
¹ The DEALLOC operation frees one previous allocation of heap storage from
any heap.
¹ The REALLOC operation changes the size of previously allocated storage from
any heap.
*-----------------------------------------------------------------*
* Prototypes for subprocedures in this module *
*-----------------------------------------------------------------*
D AddName PR
D name_parm 40A
D Display PR
D Free PR
*-----------------------------------------------------------------*
* Each element in the list contains a pointer to the *
* name and a pointer to the next element *
*-----------------------------------------------------------------*
D elem DS BASED(elem@)
D name@ *
D next@ *
D name_len 5U 0
D nameVal S 40A BASED(name@)
D elemSize C %SIZE(elem)
*-----------------------------------------------------------------*
* The first element in the list is in static storage. *
* The name field of this element is not set to a value. *
*-----------------------------------------------------------------*
D first DS
D * INZ(*NULL)
D * INZ(*NULL)
D 5U 0 INZ(0)
*-----------------------------------------------------------------*
* This is the pointer to the current element. *
* When elem@ is set to the address of <first>, the list is *
* empty. *
*-----------------------------------------------------------------*
D elem@ S * INZ(%ADDR(first))
*-----------------------------------------------------------------*
* Put 5 elements in the list *
*-----------------------------------------------------------------*
C DO 5
C 'Name?' DSPLY name 40
C CALLP AddName(name)
C ENDDO
*-----------------------------------------------------------------*
* Display the list and then free it. *
*-----------------------------------------------------------------*
C CALLP Display
C CALLP Free
*-----------------------------------------------------------------*
* AddName - add a name to the end of the list *
*-----------------------------------------------------------------*
P AddName B
D AddName pi
D name 40A
*-----------------------------------------------------------------*
* Allocate a new element for the array, pointed at by the *
* 'next' pointer of the current end of the list. *
* *
* Before: *
* *
* .-------------. *
* | | *
* | name *--->abc *
* | name_len 3 | *
* | next *-------||| *
* | | *
* '-------------' *
* *
*-----------------------------------------------------------------*
C ALLOC elemSize next@
*-----------------------------------------------------------------*
* *
* After: Note that the old element is still the current one *
* because elem@ is still pointing to the old element *
* *
* .-------------. .--------------. *
* | | .------>| | *
* | name *--->abc | | | *
* | name_len 3 | | | | *
* | next *----------' | | *
* | | | | *
* '-------------' '--------------' *
* *
* Now set elem@ to point to the new element *
*-----------------------------------------------------------------*
C EVAL elem@ = next@
*-----------------------------------------------------------------*
* Save the length of the name (not counting trailing blanks)
*-----------------------------------------------------------------*
C EVAL name_len = %len(%trimr(name))
*-----------------------------------------------------------------*
* Storage is allocated for the name and then set to the value of
* the name.
*-----------------------------------------------------------------*
C ALLOC name_len name@
C EVAL %SUBST(nameVal:1&gml.name_len) = name
*-----------------------------------------------------------------*
* *
* After: *
* *
* .-------------. .--------------. *
* | | .------>| | *
* | *--->abc | | name *--->newname *
* | 3 | | | name_len nn | *
* | *----------' | next *--->||| *
* | | | | *
* '-------------' '--------------' *
*-----------------------------------------------------------------*
P AddName E
*-----------------------------------------------------------------*
* Save the current elem pointer so the list can be restored after *
* being displayed and set the list pointer to the beginning of *
* the list. *
*-----------------------------------------------------------------*
C EVAL saveElem@ = elem@
C EVAL elem@ = %ADDR(first)
*-----------------------------------------------------------------*
* Loop through the elements of the list until the next pointer is *
* *NULL *
*-----------------------------------------------------------------*
C DOW next@ <> *NULL
C EVAL elem@ = next@
C EVAL dspName = %SUBST(nameVal:1&gml.name_len)
C 'Name: ' dsply dspName
C ENDDO
*-----------------------------------------------------------------*
* Restore the list pointer to its former place
*-----------------------------------------------------------------*
C EVAL elem@ = saveElem@
P Display E
*-----------------------------------------------------------------*
* Loop through the elements of the list until the next pointer is *
* *NULL, starting from the first real element in the list *
*-----------------------------------------------------------------*
C EVAL elem@ = %ADDR(first)
C EVAL elem@ = next@
*-----------------------------------------------------------------*
* Free the storage for name *
*-----------------------------------------------------------------*
C DEALLOC name@
*-----------------------------------------------------------------*
* Save the pointer to current elem@
*-----------------------------------------------------------------*
C EVAL prv@ = elem@
*-----------------------------------------------------------------*
* Advance elem@ to the next element
*-----------------------------------------------------------------*
C EVAL elem@ = next@
*-----------------------------------------------------------------*
* Free the storage for the current element
*-----------------------------------------------------------------*
C DEALLOC prv@
C ENDDO
*-----------------------------------------------------------------*
* Ready for a new list:
*-----------------------------------------------------------------*
C EVAL elem@ = %ADDR(first)
P Free E
*-----------------------------------------------------------------*
* After this point, Fld1 should not be accessed since the
* basing pointer ptr1 no longer points to allocated storage.
*-----------------------------------------------------------------*
C CALL 'SOMEPGM'
*-----------------------------------------------------------------*
* During the previous call to 'SOMEPGM', several storage
* allocations may have been done.
* In any case, it is extremely dangerous to make the
* following assignment, since 25 bytes of storage will be
* filled with 'a'. It is impossible to know what that storage
* is currently being used for.
*-----------------------------------------------------------------*
C EVAL Fld1 = *ALL'a'
The following example shows you how to manage dynamic storage for a run-time
array with a user-created heap from an ILE RPG procedure. In this example, the
procedures in the module DYNARRAY dynamically allocate storage for a practically
unbounded packed array. The procedures in the module perform the following
actions on the array:
¹ Initialize the array
¹ Add an element to the array
¹ Return the value of an element
¹ Release the storage for the array.
DYNARRAY performs these actions using the three ILE bindable storage APIs,
CEECRHP (Create Heap), CEEGTST (Get Storage), and CEEDSHP (Discard
Heap), as well as the REALLOC operation code. See the System API Referencefor
specific information about the storage management bindable APIs.
Figure 54 shows the /COPY file DYNARRI containing the prototypes for the proce-
dures in DYNARRAY. This /COPY file is used by the DYNARRAY module as well
as any other modules that call the procedures in DYNARRAY.
DYNARRAY has been defined for use with a (15,0) packed decimal array. It could
easily be converted to handle a character array simply by changing the definition of
DYNA_TYPE to a character field.
*=================================================================
* DYNARRAY : Handle a (practically) unbounded run-time
* Packed(15,0) array. The DYNARRAY module contains
* procedures to allocate the array, return or set
* an array value and deallocate the array.
*=================================================================
D DYNA_TYPE S 15P 0
D DYNA_INIT PR
D DYNA_TERM PR
D DYNA_SET PR
D Element VALUE LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
D DYNA_GET PR LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
Figure 54. /COPY file DYNARRI containing prototypes for DYNARRAY module
Figure 55 on page 121 shows the beginning of module DYNARRAY containing the
Control specification, and Definition specifications.
*-----------------------------------------------------------------
* Prototypes for the procedures in this module.
*-----------------------------------------------------------------
/COPY DYNARRI
*-----------------------------------------------------------------
* Interface to the CEEGTST API (Get Heap Storage).
* 1) HeapId = Id of the heap.
* 2) Size = Number of bytes to allocate
* 3) RetAddr= Return address of the allocated storage
* 4) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-----------------------------------------------------------------
D CEEGTST PR
D HeapId 10I 0 CONST
D Size 10I 0 CONST
D RetAddr *
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------
* Interface to the CEECRHP API (Create Heap).
* 1) HeapId = Id of the heap.
* 2) InitSize = Initial size of the heap.
* 3) Incr = Number of bytes to increment if heap must be
* enlarged.
* 4) AllocStrat = Allocation strategy for this heap. We will
* specify a value of 0 which allows the system
* to choose the optimal strategy.
* 5) *OMIT = The feedback parameter. Specifying *OMIT here
* means that we will receive an exception from
* the API if it cannot satisfy our request.
* Since we do not monitor for it, the calling
* procedure will receive the exception.
*-----------------------------------------------------------------
D CEECRHP PR
D HeapId 10I 0
D InitSize 10I 0 CONST
D Incr 10I 0 CONST
D AllocStrat 10I 0 CONST
D Feedback 12A OPTIONS(*OMIT)
Figure 55 (Part 1 of 2). Global variables and local prototypes for DYNARRAY
*-----------------------------------------------------------------
* Global variables.
*-----------------------------------------------------------------
D HeapVars DS
D HeapId 10I 0
D DynArr@ *
*-----------------------------------------------------------------
* Define the dynamic array. We code the number of elements
* as the maximum allowed, noting that no storage will actually
* be declared for this definition (because it is BASED).
*-----------------------------------------------------------------
D DynArr S DIM(32767) BASED(DynArr@)
D LIKE(DYNA_TYPE)
*-----------------------------------------------------------------
* Global to keep track of the current number of elements
* in the dynamic array.
*-----------------------------------------------------------------
D NumElems S 10I 0 INZ(0)
*-----------------------------------------------------------------
* Initial number of elements that will be allocated for the
* array, and minimum number of elements that will be added
* to the array on subsequent allocations.
*-----------------------------------------------------------------
D INITALLOC C 100
D SUBSALLOC C 100
Figure 55 (Part 2 of 2). Global variables and local prototypes for DYNARRAY
*-----------------------------------------------------------------
* Local variables.
*-----------------------------------------------------------------
D Size S 10I 0
*
* Start with a pre-determined number of elements.
*
C Z-ADD INITALLOC NumElems
*
* Determine the number of bytes needed for the array.
*
C EVAL Size = NumElems * %SIZE(DynArr)
*
* Create the heap
*
C CALLP CEECRHP(HeapId : Size : 0 : 0 : *OMIT)
*
* Allocate the storage and set the array basing pointer
* to the pointer returned from the API.
*
* Note that the ALLOC operation code uses the default heap so
* we must use the CEEGTST API to specify a different heap.
*
C CALLP CEEGTST(HeapId : Size : DynArr@ : *OMIT)
*
* Initialize the storage for the array.
*
C 1 DO NumElems I 5 0
C CLEAR DynArr(I)
C ENDDO
P DYNA_INIT E
*=================================================================
* DYNA_TERM: Terminate array handling.
*
* Function: Delete the heap.
*=================================================================
P DYNA_TERM B EXPORT
C CALLP CEEDSHP(HeapId : *OMIT)
C RESET HeapVars
P DYNA_TERM E
*-----------------------------------------------------------------
* Input parameters for this procedure.
*-----------------------------------------------------------------
D DYNA_SET PI
D Element VALUE LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
*-----------------------------------------------------------------
* Local variables.
*-----------------------------------------------------------------
D Size S 10I 0
*-----------------------------------------------------------------
* If the user selects to add to the array, then first check
* if the array is large enough, if not then increase its
* size. Add the element.
*-----------------------------------------------------------------
C Index IFGT NumElems
C EXSR REALLOC
C ENDIF
C EVAL DynArr(Index) = Element
*=================================================================
* REALLOC: Reallocate storage subroutine
*
* Function: Increase the size of the dynamic array
* and initialize the new elements.
*=================================================================
C REALLOC BEGSR
*
* Remember the old number of elements
*
C Z-ADD NumElems OldElems 5 0
*
* Calculate the new size of the array
*
C EVAL Size = NumElems * %SIZE(DynArr)
*
* Reallocate the storage. The new storage has the same value
* as the old storage.
*
C REALLOC Size DynArr@
*
* Initialize the new elements for the array.
*
C 1 ADD OldElems I
C I DO NumElems I 5 0
C CLEAR DynArr(I)
C ENDDO
C ENDSR
P DYNA_SET E
*-----------------------------------------------------------------
* Input parameters for this procedure.
*-----------------------------------------------------------------
D DYNA_GET PI LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
*-----------------------------------------------------------------
* Local variables.
*-----------------------------------------------------------------
D Element S LIKE(DYNA_TYPE) INZ
*-----------------------------------------------------------------
* If the element requested is within the current size of the
* array then return the element's current value. Otherwise
* the default (initialization) value can be used.
*-----------------------------------------------------------------
C Index IFLE NumElems
C EVAL Element = DynArr(Index)
C ENDIF
C RETURN Element
P DYNA_GET E
The procedure can then be bound with other modules using CRTPGM or
CRTSRVPGM.
Figure 57 on page 127 shows another module that tests the procedures in
DYNARRAY.
/COPY EXAMPLES,DYNARRI
D X S LIKE(DYNA_TYPE)
* Clean up
C CALLP DYNA_TERM
C SETON LR
An ILE 'program call' is a special form of procedure call; that is, it is a call to the
program entry procedure. A program entry procedure is the procedure that is desig-
nated at program creation time to receive control when a program is called. If the
entry module of the program is an ILE RPG module, then the main procedure of
that module is called by the program entry procedure immediately after the program
is called.
Calling Programs
You can call OPM or ILE programs by using program calls. A program call is a
call that is made to a program object (*PGM). The called program's name is
resolved to an address at run time, just before the calling program passes control
to the called program for the first time. For this reason, program calls are often
referred to as dynamic calls.
Calls to an ILE program, an EPM program, or an OPM program are all examples of
program calls. A call to a non-bindable API is also an example of a program call.
You use the CALLP operation or both the CALL and PARM operations to make a
program call. If you use the CALL and PARM operations, then the compiler cannot
perform type checking on the parameters, which may result in run-time errors.
When an ILE program is called, the program entry procedure receives the program
parameters and is given initial control for the program. In addition, all procedures
within the program become available for procedure calls.
Calling Procedures
Unlike OPM programs, ILE programs are not limited to using program calls. ILE
programs can also use static procedure calls or procedure pointer calls to call other
procedures. Procedure calls are also referred to as bound calls.
A static procedure call is a call to an ILE procedure where the name of the proce-
dure is resolved to an address during binding — hence, the term static. As a result,
run-time performance using static procedure calls is faster than run-time perform-
ance using program calls. Static calls allow operational descriptors, omitted param-
eters, and they extend the limit (to 399) on the number of parameters that are
passed.
Any procedure that can be called by using a static procedure call can also be
called through a procedure pointer.
For a list of examples using static procedure calls, see “Examples of Free-Form
Call” on page 137 and “Examples of CALL and CALLB” on page 151. For exam-
You use the CALLP or both the CALLB and PARM operations to make a procedure
call. You can also call a prototyped procedure with an expression if the procedure
returns a value. If you use the CALLB and PARM operations, then the compiler
cannot perform type checking on the parameters, which may result in run-time
errors.
When an ILE program is called, the program entry procedure is first added to the
call stack. The system then automatically performs a procedure call, and the asso-
ciated user's procedure (the main procedure) is added. When a procedure is called,
only the user's procedure (a main procedure or subprocedure) is added; there is no
overhead of a program entry procedure.
CALL STACK
OPM
OPM
Program A
Program Call
ILE
RPG Module
ILE
Program
PEP
Entry Proc.
Procedure Call (by system)
ILE
Main
Procedure
Procedure
Procedure Call
ILE
Sub-
Procedure Procedure
Procedure Call
C Module ILE
Procedure Procedure
Note: In a program call, the calls to the program entry procedure and the user
entry procedure (UEP) occur together, since the call to the UEP is auto-
matic. Therefore, from now on, the two steps of a program call will be com-
bined in later diagrams involving the call stack in this and remaining
chapters.
A main procedure that is on the call stack cannot be called until it returns to its
caller. Therefore, be careful not to call a procedure that might call an already active
main procedure.
Try to avoid situations that might inadvertently lead to recursive calls. For example,
suppose there are three modules, as shown in Figure 59.
PRC_A
PRC_B
PRC_C
So while subprocedures can be called recursively, if you are not aware that
recursion is occurring, you may exhaust system resources.
Attention!
Unconditional recursive calls can lead to infinite recursion which leads to exces-
sive use of system resources. Infinite recursion can be avoided with proper pro-
gramming. In general, a proper recursive procedure begins with a test to
determine if the desired result has been obtained. If it has been obtained, then
the recursive procedure returns to the most recent caller.
Parameter-Passing Considerations
When designing a call interface, you must make a number of decisions in terms of
how parameters will be passed. On the other hand, if you are the caller then then
most of the decisions have already been made for you. The following lists some of
the parameter-passing considerations to keep in mind when you are designing a
call interface.
¹ Compile-time parameter checking
The call interface of a prototyped call is checked at compile time. This checking
ensures that:
– the data types are correctly used
– all required parameters are passed
– *OMIT is only passed where it is allowed.
¹ Parameter passing method
Each HLL provides one or more ways of passing parameters. These may
include: passing a pointer to the parameter value, passing a copy of the value,
or passing the value itself.
¹ Passing operational descriptors
Table 8 on page 135 associates the above considerations with the two types
parameters: prototyped or non-prototyped.
In RPG, prototyped calls are also known as free-form calls. Free-form call refers to
the call syntax where the arguments for the call are specified using free-form
syntax, much like the arguments for built-in functions. It contrasts with fixed-form
call, where the arguments are placed in separate specifications. There are two
ways to make a free-form call, depending on whether there is a return value that is
to be used. If there is no return value, use the CALLP operation. If there is one,
and you want to use the value that is returned, then place the prototyped procedure
within an expression, for example, with EVAL. If you use CALLP to a procedure
that returns a value, the return value is ignored.
Note: Only prototyped procedures can return values; prototyped programs cannot.
The following example shows a call to a procedure Switch, which changes the state
of the indicator that is passed to it, in this case *IN10..
C CALLP Switch(*in10)
You can use CALLP from anywhere within the module. If the keyword EXTPGM is
specified on the prototype, the call will be a dynamic external call; otherwise it will
be a bound procedure call.
Note that if CALLP is used to call a procedure which returns a value, that value will
not be available to the caller. If the value is required, call the prototyped procedure
within an expression.
Figure 61 shows the prototype for a procedure CVTCHR that takes a numeric input
parameter and returns a character string. Figure 62 shows how the procedure
might be used in an expression.
This section discusses the various options that are available when defining proto-
typed parameters, and the impact of these options on the call interface.
Passing by Reference
The default parameter passing style for ILE RPG is to pass by reference. Conse-
quently, you do not have to code any keywords on the parameter definition to pass
the parameter by reference. You should pass parameters by reference to a proce-
dure when you expect the callee to modify the field passed. You may also want to
pass by reference to improve run-time performance, for example, when passing
large character fields. Note also that parameters that are passed on external
program calls can only be passed by reference.
One primary use for passing by value is that you can allow less stringent matching
of the attributes of the passed parameter. For example, if the definition is for a
numeric field of type packed-decimal and length 5 with 2 decimal positions, you
must pass a numeric value, but it can be:
¹ A packed, zoned or binary constant or variable, with any number of digits and
number of decimal positions
¹ A built-in function returning a numeric value
¹ A procedure returning a numeric value
¹ A complex numeric expression such as
2 * (Min(Length(First) + Length(Last) + 1): %size(Name))
If the prototype requires an array of 4 elements, the passed parameter can be:
¹ An array with fewer than 4 elements. In this case, the remaining elements in
the received parameter will contain the default value for the type.
¹ An array with 4 elements. In this case, each element of the received parameter
will correspond to an element of the passed parameter.
¹ An array with more than 4 elements. In this case, some of the elements of the
passed array will not be passed to the received parameter.
¹ A non-array. In this case, each element of the received parameter will contain
the passed parameter value.
To pass a parameter by value, specify the keyword VALUE on the parameter defi-
nition in the prototype, as shown in the figures below.
P DO_CALC B EXPORT
*-------------------------------------------------------------
* This procedure performs a function on the 3 numeric values
* passed to it as value parameters. It also returns a value.
*-------------------------------------------------------------
D DO_CALC PI 10I 0
D Term1 5I 0 VALUE
D Term2 5I 0 VALUE
D Term3 5I 0 VALUE
D Result S 10I 0
C EVAL Result = Term1 ** 2 * 17
C + Term2 * 7
C + Term3
C RETURN Result * 45 + 23
P E
When a parameter is passed by read-only reference, the compiler may copy the
parameter to a temporary field and pass the address of the temporary. Some condi-
tions that would cause this are: the passed parameter is an expression or the
passed parameter has a different format.
Note: If the called program or procedure is compiled using a prototype in a lan-
guage that enforces the read-only reference method (either ILE RPG using
prototypes, or C), then the parameter will not be changed. If the called
program or procedure does not use a prototype, then the compiler cannot
ensure that the parameter is not changed. In this case, the person defining
the prototype must be careful when specifying this parameter-passing
method.
*------------------------------------------------------------------
* CEETSTA (Test for omitted argument) -- ILE CEE API
* 1. Presence flag Output Binary(4)
* 2. Argument number Input Binary(4)
*------------------------------------------------------------------
D CEETSTA PR EXTPROC('CEETSTA')
D Present 10I 0
D ArgNum 10I 0 CONST
...
D HaveParm S 10I 0
...
C CALLP CEETSTA(HaveParm : 3)
C IF HaveParm = 1
C do something with third parameter
C ENDIF
Figure 65. Prototype for ILE CEE API CEETSTA with CONST Parameter
The second parameter passed to CEETSTA can be any numeric field, a literal, a
built-in function, or expression.
Many ILE bindable APIs expect operational descriptors. In the System API Refer-
ence, if any parameter is defined as 'by descriptor', then you should pass opera-
tional descriptors to the API. An example of this is the ILE CEE API CEEDATM
(Convert Seconds to Character Timestamp). The second and third parameters
require an operational descriptor.
Note: Currently, the ILE RPG compiler only supports operational descriptors for
character and graphic fields and subfields. Operational descriptors are not
available for data structures, arrays, or tables. In addition, operational
descriptors are not available for data of type numeric, date, time, timestamp,
basing pointer or procedure pointer.
You can request operational descriptors for both prototyped and non-prototyped
parameters. For prototyped parameters, you specify the keyword OPDESC on the
prototype definition. For non-prototyped parameters, you specify (D) as the opera-
tion code extender of the CALLB operation. In either case, operational descriptors
You can retrieve information from an operational descriptor using the ILE bindable
APIs Retrieve Operational Descriptor Information (CEEDOD) and Get Descriptive
Information About a String Argument (CEESGI).
Note that operational descriptors are only allowed for bound calls. Furthermore, for
non-prototyped calls, an error message will be issued by the compiler if the 'D'
operation code extender is specified on a CALL operation.
*-------------------------------------------------------------
* Len returns a 10-digit integer value. The parameter
* is a character string passed by read-only reference.
* Operational descriptors are required so that Len knows
* the length of the parameter.
* OPTIONS(*VARSIZE) is required so that the parameter can
* be less than 32767 bytes.
*-------------------------------------------------------------
D Len PR 10I 0 OPDESC
D 32767A OPTIONS(*VARSIZE) CONST
Omitting Parameters
When calling a procedure, you may sometimes want to leave out a parameter. It
may be that it is not relevant to the called procedure. For example, this situation
might arise when you are calling the ILE bindable APIs. Another reason might be
that you are calling an older procedure that does not handle this particular param-
eter. If you need to omit a parameter on a call, you have two choices:
¹ Pass *OMIT
¹ Do not pass the parameter
The primary difference between the two methods has to do with how you check to
see if a parameter has been omitted. An omitted parameter cannot be referenced
by the called procedure; if it is, an error will occur. So if the called procedure is
designed to handle different numbers of parameters, you will have to check for the
number of parameters passed. If *OMIT is passed, it will 'count' as a parameter.
Passing *OMIT
You can pass *OMIT for a prototyped parameter if the called procedure is aware
that *OMIT might be passed. In other words, you can pass *OMIT if the keyword
OPTIONS(*OMIT) is specified on the corresponding parameter definition in the pro-
totype. When *OMIT is specified, the compiler will generate the necessary code to
indicate to the called procedure that the parameter has been omitted.
To determine if *OMIT has been passed to an ILE RPG procedure, use the
%ADDR built-in function to check the address of the parameter in question. If the
address is *NULL, then *OMIT has been passed. You can also use the CEETSTA
(Check for Omitted Argument) bindable API. (See Figure 65 on page 140 for a
brief example.)
The following is a simple example of how *OMIT can be used. In this example, a
procedure calls the ILE bindable API CEEDOD in order to decompose an opera-
tional descriptor. The CEEDOD API expects to receive seven parameters; yet only
six have been defined in the calling procedure. The last parameter of CEEDOD
(and of most bindable APIs) is the feedback code which can be used to determine
how the API ended. However, the calling procedure has been designed to receive
any error messages via an exception rather than this feedback code. Conse-
quently, on the call to CEEDOD, the procedure must indicate that the parameter for
the feedback code has been omitted.
You can specify both *NOPASS and *OMIT for the same parameter, in either order,
that is, OPTIONS(*NOPASS:*OMIT) or OPTIONS(*OMIT:*NOPASS).
*-------------------------------------------------------------
* This prototype for QCMDEXC defines three parameters:
* 1- a character field that may be shorter in length
* than expected
* 2- any numeric field
* 3- an optional character field
*-------------------------------------------------------------
D qcmdexc PR EXTPGM('QCMDEXC')
D cmd 3000A OPTIONS(*VARSIZE) CONST
D cmdlen 15P 5 CONST
D 3A CONST OPTIONS(*NOPASS)
Figure 67. Prototype for System API QCMDEXC with Optional Parameter
%PARMS does not take any parameters. The value returned by %PARMS also
includes any parameters for which *OMIT has been passed. For the main proce-
dure, %PARMS returns the same value as contained in the *PARMS field in a
PSDS, although to use the *PARMS field, you must also code the PSDS.
For both *PARMS and %PARMS, if the number of passed parameters is not
known, the value -1 is returned. (In order to determine the number of parameters
passed, a minimal operational descriptor must be passed. ILE RPG always passes
one on a call; however other ILE languages may not.) If the main procedure is not
active, *PARMS is unreliable. It is not recommended to reference *PARMS from a
subprocedure.
Using %PARMS
In this example, a procedure FMTADDR has been changed several times to allow
for a change in the address information for the employees of a company.
FMTADDR is called by three different procedures. The procedures differ only in the
number of parameters they use to process the employee information. That is, new
requirements for the FMTADDR have arisen, and to support them, new parameters
have been added. However, old procedures calling FMTADDR are still supported
and do not have to be changed or recompiled.
*=================================================================*
* FMTADDR - format an address
*
* Interface parameters
* 1. Address character(70)
* 2. Street number packed(5,0)
* 3. Street name character(20)
* 4. City character(15) (some callers do not pass)
* 5. Province character(15) (some callers do not pass)
*=================================================================*
DFmtAddr PI
D Address 70
D Street# 5 0 CONST
D Street 20 CONST
D P_City 15 OPTIONS(*NOPASS) CONST
D P_Province 15 OPTIONS(*NOPASS) CONST
*-----------------------------------------------------------------*
* Default values for parameters that might not be passed.
*-----------------------------------------------------------------*
D City S 15 INZ('Toronto')
D Province S 15 INZ('Ontario')
*-----------------------------------------------------------------*
* Check whether the province parameter was passed. If it was,
* replace the default with the parameter value.
*-----------------------------------------------------------------*
C IF %PARMS > 4
C EVAL Province = P_Province
C ENDIF
*-----------------------------------------------------------------*
* Check whether the city parameter was passed. If it was, *
* replace the default with the parameter value. *
*-----------------------------------------------------------------*
C IF %PARMS > 3
C EVAL City = P_City
C ENDIF
*-----------------------------------------------------------------*
* Set 'CStreet#' to be character form of 'Street#' *
*-----------------------------------------------------------------*
C EXSR GetStreet#
*-----------------------------------------------------------------*
* Format the address as Number Street, City, Province *
*-----------------------------------------------------------------*
C EVAL ADDRESS = %TRIMR(CSTREET#) + ' ' +
C %TRIMR(CITY) + ' ,' +
C %TRIMR(PROVINCE)
C RETURN
C ENDSR
*=================================================================*
* Prototype for FMTADDR - format an address
*=================================================================*
DFmtAddr PR
D addr 70
D strno 5 0 CONST
D st 20 CONST
D cty 15 OPTIONS(*NOPASS) CONST
D prov 15 OPTIONS(*NOPASS) CONST
Figure 69. Source for /COPY member with Prototype for Procedure FMTADDR
Figure 70 on page 146 shows the source for the procedure PRTADDR. This pro-
cedure serves to illustrate the use of FMTADDR. For convenience, the three proce-
dures which would each call FMTADDR are combined into this single procedure.
Also, for the purposes of the example, the data is program-described.
*-----------------------------------------------------------------*
* Prototype for FmtAddr
*-----------------------------------------------------------------*
DFmtAddr PR
D addr 70
D strno 5 0
D st 20
D cty 15 OPTIONS(*NOPASS)
D prov 15 OPTIONS(*NOPASS)
DAddress S 70
*-----------------------------------------------------------------*
* Stage1: Original address data structure.
* Only street and number are variable information.
*-----------------------------------------------------------------*
D Stage1 DS
D Street#1 5P 0 DIM(2) CTDATA
D StreetNam1 20 DIM(2) ALT(Street#1)
*-----------------------------------------------------------------*
* Stage2: Revised address data structure as city information
* now variable.
*-----------------------------------------------------------------*
D Stage2 DS
D Street#2 5P 0 DIM(2) CTDATA
D Addr2 35 DIM(2) ALT(Street#2)
D StreetNam2 20 OVERLAY(Addr2:1)
D City2 15 OVERLAY(Addr2:21)
*-----------------------------------------------------------------*
* Stage3: Revised address data structure as provincial
* information now variable.
*-----------------------------------------------------------------*
D Stage3 DS
D Street#3 5P 0 DIM(2) CTDATA
D Addr3 50 DIM(2) ALT(Street#3)
D StreetNam3 20 OVERLAY(Addr3:1)
D City3 15 OVERLAY(Addr3:21)
D Province3 15 OVERLAY(Addr3:36)
*-----------------------------------------------------------------*
* 'Program 1'- Use of FMTADDR before city parameter was added.
*-----------------------------------------------------------------*
C DO 2 X 5 0
C CALLP FMTADDR (Address:Street#1(X):StreetNam1(X))
C EXCEPT
C ENDDO
C EXCEPT
C ENDDO
*-----------------------------------------------------------------*
* 'Program 3' - Use of FMTADDR after province parameter was added.*
*-----------------------------------------------------------------*
C DO 2 X 5 0
C CALLP FMTADDR (Address:Street#3(X):
C StreetNam3(X):City3(X):Province3(X))
C EXCEPT
C ENDDO
C SETON LR
*-----------------------------------------------------------------*
* Print the address. *
*-----------------------------------------------------------------*
OQSYSPRT E
O Address
**
00123Bumble Bee Drive
01243Hummingbird Lane
**
00003Cowslip Street Toronto
01150Eglinton Avenue North York
**
00012Jasper Avenue Edmonton Alberta
00027Avenue Road Sudbury Ontario
Figure 71 shows the prototype for QCMDEXC, where the first parameter is defined
with OPTIONS(*VARSIZE) meaning that you can pass parameters of different
lengths for the first parameter. Note that OPTIONS *VARSIZE can only be specified
for a character field, a graphic field, or an array.
*-------------------------------------------------------------
* This prototype for QCMDEXC defines three parameters. The
* first parameter can be passed character fields of
* different lengths, since it is defined with *VARSIZE.
*-------------------------------------------------------------
D qcmdexc PR EXTPGM('QCMDEXC')
D cmd 3000A OPTIONS(*VARSIZE) CONST
D cmdlen 15P 5 CONST
D 3A CONST OPTIONS(*NOPASS)
Figure 71. Prototype for System API QCMDEXC with *VARSIZE Parameter
Order of Evaluation
There is no guaranteed order for evaluation of parameters on a prototyped call.
This fact may be important when using parameters that cause side effects, as the
results may not be what you would expect.
If a side effect occurs, then, if the parameter is used elsewhere in the parameter
list, then the value used for the parameter in one part of the list may not be the
same as the value used in another part. For example, consider this call statement.
CALLP procA (fld : procB(fld) : fld)
Assume that procA has all value parameters, and procB has a reference param-
eter. Assume also that fld starts off with the value 3, and that procB modifies fld to
be 5, and returns 10. Depending on the order in which the parameters are evalu-
| ated, procA will receive either 3, 10, and 5 or possibly, 3, 10, and 3. Or possibly, 5,
| 10, and 3; or even 5, 10, and 5.
Passing By Value
ILE RPG – prototype D proc PR
D parm 1A VALUE
C CALLP proc('a')
Fld1 is protected from being changed, but TEMP is not. There is no expectation that
the parameter will not be changed.
For information on the data types supported by different HLLs, consult the appro-
priate language manual.
Either operation transfers control from the calling to the called object. After the
called object is run, control returns to the first operation that can be processed after
the call operation in the calling program or procedure.
The Factor 1 and factor 2 entries are optional and indicate variables or literals
whose value is transferred to or received from the Result Field entry depending on
whether these entries are in the calling program/procedure or the called
program/procedure. Table 10 on page 152 shows how factor 1 and factor 2 are
used.
Note: The moves to either the factor 1 entry or the result-field entry occur only
when the called procedure returns normally to its caller. If an error occurs
while attempting to move data to either entry, then the move is not com-
pleted.
Factor 1 of the PLIST operation must contain the PLIST name. This name can be
specified in the Result field of one or more call operations. If the parameter list is
the entry parameter list of a called procedure, then Factor 1 must contain *ENTRY.
Multiple PLISTs can appear in a procedure. However, only one *ENTRY PLIST can
be specified, and only in the main procedure.
For examples of the PLIST operation see Figure 47 on page 104 and Figure 111
on page 240.
Because of the cycle code associated with main procedures, their return is also
associated with certain termination routines. This section discusses the different
ways that main procedures and subprocedures can return, and the actions that
occur with each.
A main procedure returns control to the calling procedure in one of the following
ways:
¹ With a normal end
¹ With an abnormal end
¹ Without an end.
Normal End
A main procedure ends normally and control returns to the calling procedure when
the LR indicator is on and the H1 through H9 indicators are not on. The LR indi-
cator can be set on:
¹ implicitly, as when the last record is processed from a primary or secondary file
during the RPG program cycle
¹ explicitly, as when you set LR on.
On the next call to the main procedure, with the exception of exported variables, a
fresh copy is available for processing. (Exported variables are initialized only once,
when the program is first activated in an activation group. They retain their last
assigned value on a new call, even if LR was on for the previous call. If you want
to re-initialize them, you have to reset them manually.)
TIP
You would only want to do this if you did not need your program re-initialized
each time.
On the next call to the procedure, a fresh copy is available for processing. (For
more information on exception handlers, see “Using RPG-Specific Handlers” on
page 227.)
If you call a main procedure and it returns without ending, when you call the proce-
dure again, all fields, indicators, and files in the procedure will hold the same values
they did when you left the procedure. However, there are three exceptions:
¹ This is not true if the program is running in a *NEW activation group, since the
activation group is deleted when the program returns. In that case, the next
time you call your program will be the same as if you had ended with LR on.
¹ If you are sharing files, the state of the file may be different from the state it
held when you left the procedure.
¹ If another procedure in the same module was called in between, then the
results are unpredictable.
You can use either the RETURN operation (with a blank factor 2) or the RT indi-
cator in conjunction with the LR indicator and the H1 through H9 indicators. Be
If the main procedure is never called (and therefore cannot end) then any files, data
areas, etcetera, will not be closed. If you think this might arise for a subprocedure,
you should code a termination procedure that gets called when the subprocedure
ends. This is especially true if the subprocedure is in a module with NOMAIN speci-
fied on the control specification.
Similarly, you can end a procedure abnormally using the ILE bindable API
CEE4ABN. The procedure will then follow abnormal termination as described
above.
Note: You cannot use either of these APIs in a program created with
DFTACTGRP(*YES), since procedure calls are not allowed in these proce-
dures.
Note that if the main procedure is not active, or if there is no main, then nothing will
get closed or freed. In this case, you should enable an ILE cancel handler, using
CEERTX. If the cancel handler is in the same module, it can close the files, unlock
the data areas, and perform the other termination actions.
For more information on CEETREC and CEE4ABN refer to the System API Refer-
ence.
You access ILE bindable APIs using the same call mechanisms used by ILE RPG
to call procedures, that is, the CALLP operation or the CALLB operation. If the API
returns a value and you want to use it, call the API in an expression. For the
information required to define a prototype for an API see the description of the API
in the System API Reference. Figure 72 shows a sample 'call' to a bindable API.
D CEExxxx PR EXTPROC('CEExxxx')
D parm1 ...
D ...
where
¹ CEExxxx is the name of the bindable API
¹ parm1, parm2, ... parmn are omissible or required parameters passed to or
returned from the called API.
¹ feedback is an omissible feedback code that indicates the result of the bindable
API.
Note: Bindable APIs cannot be used if DFTACTGRP(*YES) is specified on the
CRTBNDRPG command.
For more information on bindable APIs, refer to the System API Reference.
The procedure that processes the CALL does not implicitly start or end OS/400
graphics routines.
For more information on OS/400 Graphics, graphics routines and parameters, see
the GDDM Programming Guide manual and the GDDM Reference.
Note: You can call OS/400 Graphics using the CALL operation. You can also use
CALLP if you define a prototype for the routine and specify the EXTPGM
keyword on the prototype. You cannot use the CALLB operation. You
cannot pass Date, Time, Timestamp, or Graphic fields to GDDM, nor can
you pass pointers to it.
While the message retrieval routine is still supported, it is recommended that you
use the QMHRTVM message API, which is more powerful.
This chapter describes how to use the ILE source debugger to:
¹ Prepare your ILE RPG program for debugging
¹ Start a debug session
¹ Add and remove programs from a debug session
¹ View the program source from a debug session
¹ Set and remove breakpoints and watch conditions
¹ Step through a program
| ¹ Display and change the value of fields
¹ Display the attributes of fields
¹ Equate a shorthand name to a field, expression, or debug command
While debugging and testing your programs, ensure that your library list is changed
to direct the programs to a test library containing test data so that any existing real
data is not affected.
You can prevent database files in production libraries from being modified uninten-
tionally by using one of the following commands:
¹ Use the Start Debug (STRDBG) command and retain the default *NO for the
UPDPROD parameter
¹ Use the Change Debug (CHGDBG) command and specify the *NO value of the
UPDPROD parameter
¹ Use the SET debug command in the Display Module Source display and
specify UPDPROD NO
See the appendix on debugging in the CL Reference for more information on pre-
venting unintended modification of production files.
See the chapter on debugging in ILE Concepts for more information on the ILE
source debugger (including authority required to debug a program or service
program and the effects of optimization levels).
Before you can use the source debugger, you must select a debug view when you
create a module object or program object using CRTRPGMOD or CRTBNDRPG.
After starting the debugger you can set breakpoints and then call the program.
Debug Commands
Many debug commands are available for use with the ILE source debugger. The
debug commands and their parameters are entered on the debug command line
displayed on the bottom of the Display Module Source and Evaluate Expression
displays. These commands can be entered in uppercase, lowercase, or mixed
case.
Note: The debug commands entered on the debug command line are not CL
commands.
The online help for the ILE source debugger describes the debug commands,
explains their allowed abbreviations, and provides syntax diagrams for each
command. It also provides examples in each of the ILE languages of displaying and
changing variables using the source debugger.
Follow these steps to access the online help information for ILE RPG:
The type of debug data that can be associated with a module is referred to as a
debug view. You can create one of the following views for each module that you
want to debug. They are:
¹ Root source view
¹ COPY source view
¹ Listing view
¹ Statement view
The default value for both CRTBNDRPG and CRTRPGMOD is to create a state-
ment view. This view provides the closest level of debug support to previous
releases.
If you do not want debug data to be included with the module or if you want faster
compilation time, specify DBGVIEW(*NONE) when the module is created.
However, a formatted dump will not list the values of program variables when no
debug data is available.
Note also that the storage requirements for a module or program will vary some-
what depending on the type of debug data included with it. The following values for
the DBGVIEW parameter are listed in increasing order based on their effect on sec-
ondary storage requirements:
1. *NONE
2. *STMT
3. *SOURCE
4. *COPY
5. *LIST
6. *ALL
Once you have created a module with debug data and bound it into a program
object (*PGM), you can start to debug your program.
| Note: An OPM program must be compiled with OPTION(*SRCDBG) or
| OPTION(*LSTDBG) in order to debug it using the ILE source debugger. For
| more information, see “Starting the ILE Source Debugger” on page 169
You create a root source view to debug a module by using the *SOURCE, *COPY
or *ALL options on the DBGVIEW parameter for either the CRTRPGMOD or
CRTBNDRPG commands when you create the module.
The compiler creates the root source view while the module object (*MODULE) is
being compiled. The root source view is created using references to locations of
text in the root source member rather than copying the text of the member into the
module object. For this reason, you should not modify, rename, or move root
source members between the module creation of these members and the debug-
ging of the module created from these members. If you do, the views for these
source members may not be usable.
For example, to create a root source view for a program DEBUGEX when using
CRTBNDRPG, type:
CRTBNDRPG PGM(MYLIB/DEBUGEX) SRCFILE(MYLIB/QRPGLESRC)
TEXT('ILE RPG/400 program DEBUGEX')
DBGVIEW(*SOURCE)
To create a root source view for a module DBGEX when using CRTRPGMOD,
type:
CRTRPGMOD MODULE(MYLIB/DBGEX) SRCFILE(MYLIB/QRPGLESRC)
TEXT('Entry module for program DEBUGEX')
DBGVIEW(*SOURCE)
The view of the root source member generated by DBGVIEW(*COPY) is the same
view generated by DBGVIEW(*SOURCE). As with the root source view, a COPY
source view is not available if the source file is a DDM file.
You create a COPY source view to debug a module by using the *COPY or *ALL
option on the DBGVIEW parameter.
The compiler creates the COPY view while the module object (*MODULE) is being
compiled. The COPY view is created using references to locations of text in the
source members (both root source member and /COPY members) rather than
copying the text of the members into the view. For this reason, you should not
modify, rename, or move source members between the time the module object is
created and the debugging of the module created from these members. If you do,
the views for these source members may not be usable.
For example, to create a source view of a program TEST1 that contains /COPY
members type:
CRTBNDRPG PGM(MYLIB/TEST1) SRCFILE(MYLIB/QRPGLESRC)
TEXT('ILE RPG/400 program TEST1')
DBGVIEW(*COPY)
Note that if you specify indentation in the compiler listing (via the INDENT param-
eter), the indentation will not appear in the listing view.
You create a listing view to debug a module by using the *LIST or *ALL options on
the DBGVIEW parameter for either the CRTRPGMOD or CRTBNDRPG commands
when you create a module.
The compiler creates the listing view while the module object (*MODULE) is being
generated. The listing view is created by copying the text of the appropriate source
members into the module object. There is no dependency on the source members
upon which it is based, once the listing view is created.
For example, to create a listing view for a program TEST1 that contains expanded
DDS type:
Specifying DBGVIEW(*LIST) for the DBGVIEW parameter and *EXPDDS for the
OPTION parameter on either create command creates a listing view with expanded
DDS for debugging the source for TEST1. Note that OUTPUT(*PRINT) and
OPTION(*EXPDDS) are both default values.
You create a statement view to debug a module by using the *STMT option on the
DBGVIEW parameter for either the CRTRPGMOD or CRTBNDRPG commands
when you create a module.
For example, to create a statement view for the program DEBUGEX using
CRTBNDRPG, type:
CRTBNDRPG PGM(MYLIB/DEBUGEX) SRCFILE(MYLIB/QRPGLESRC)
TEXT('ILE RPG/400 program DEBUGEX')
By default a compiler listing and a statement view are produced. Using a compiler
listing to obtain the statement numbers, you debug the program using the debug
commands.
If the default values for either create command have been changed, you must
explicitly specify DBGVIEW(*STMT) and OUTPUT(*PRINT).
Initially you can add as many as 20 program objects to a debug session by using
the Program (PGM) parameter on the STRDBG command. They can be any combi-
| For an ILE program, the entry module is shown if it has debug data; otherwise, the
| first module bound to the ILE program with debug data is shown.
For an OPM program, the first program specified on the STRDBG command is
shown if it has debug data, and the OPMSRC parameter is *YES. That is, if an
OPM program is in a debug session, then you can debug it using the ILE source
debugger if the following conditions are met:
1. The OPM program was compiled with OPTION(*LSTDBG) or
OPTION(*SRCDBG). (Three OPM languages are supported: RPG, COBOL,
and CL. RPG and COBOL programs can be compiled with *LSTDBG or
*SRCDBG, but CL programs must be compiled with *SRCDBG.
2. The ILE debug environment is set to accept OPM programs. You can do this
by specifying OPMSRC(*YES) on the STRDBG command. (The system default
is OPMSRC(*NO).)
| If these two conditions are not met, then you must debug the OPM program with
the OPM system debugger.
STRDBG Example
To start a debug session for the sample debug program DEBUGEX and a called
OPM program RPGPGM, type:
STRDBG PGM(MYLIB/DEBUGEX MYLIB/RPGPGM) OPMSRC(*YES)
The Display Module Source display appears as shown in Figure 73 on page 171.
DEBUGEX consists of two modules, an RPG module DBGEX and a C module
cproc. See “Sample Source for Debug Examples” on page 211 for the source for
DBGEX, cproc, and RPGPGM.
If the entry module has a root source, COPY, or listing view, then the display will
show the source of the entry module of the first program. In this case, the program
was created using DBGVIEW(*ALL) and so the source for the main module,
DBGEX, is shown.
Changing the debug options using the SET debug command affects the value for
the corresponding parameter, if any, specified on the STRDBG command. You can
| also use the Change Debug (CHGDBG) command to set debug options. However,
| the OPMSRC option can not be changed by the CHGDBG command. OPMSRC
| can only be changed by the debug SET command.
Suppose you are in a debug session working with an ILE program and you decide
you should also debug an OPM program that has debug data available. To enable
the ILE source debugger to accept OPM programs, follow these steps:
1. After entering STRDBG, if the current display is not the Display Module Source
display, type:
DSPMODSRC
3. The Set Debug Options display appears. On this display type Y (Yes) for the
OPM source debug support field, and press Enter to return to the Display
Module Source display.
You can now add the OPM program, either by using the Work with Module display,
or by processing a call statement to that program.
For ILE programs, you use option 1 (Add program) on the Work with Module List
display of the DSPMODSRC command. To remove an ILE program or service
program, use option 4 (Remove program) on the same display. When an ILE
program or service program is removed, all breakpoints for that program are
removed. There is no limit to the number of ILE programs or service programs that
can be in or removed from a debug session at one time.
For OPM programs, you have two choices depending on the value specified for
OPMSRC. If you specified OPMSRC(*YES), by using either STRDBG, the SET
debug command, or CHGDBG, then you add or remove an OPM program using the
Work With Module Display. (Note that there will not be a module name listed for an
OPM program.) There is no limit to the number of OPM programs that can be
included in a debug session when OPMSRC(*YES) is specified.
If you specified OPMSRC(*NO), then you must use the Add Program (ADDPGM)
command or the Remove Program (RMVPGM) command. Only 20 OPM programs
can be in a debug session at one time when OPMSRC(*NO) is specified.
Note: You cannot debug an OPM program with debug data from both an ILE and
an OPM debug session. If OPM program is already in an OPM debug
session, you must first remove it from that session before adding it to the
ILE debug session or stepping into it from a call statement. Similarly, if you
want to debug it from an OPM debug session, you must first remove it from
an ILE debug session.
Work with Module List
System: AS400S1
Type options, press enter.
1=Add program 4=Remove program 5=Display module source
8=Work with module breakpoints
Bottom
Command
===> ________________________________________________________________________
F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel
Figure 74. Adding an ILE Service Program to a Debug Session
Bottom
Command
===> ________________________________________________________________________
F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel
Figure 75. Removing an ILE Program from a Debug Session
The source of an OPM program can be shown if the following conditions are met:
1. The OPM program was compiled with OPTION(*LSTDBG) or
OPTION(*SRCDBG). (Only RPG and COBOL programs can be compiled with
*LSTDBG.)
2. The ILE debug environment is set to accept OPM programs; that is the value of
OPMSRC is *YES. (The system default is OPMSRC(*NO).)
There are two methods to change what is shown on the Display Module Source
display:
¹ Change to a different module
¹ Change the view of a module
When you change a view, the ILE source debugger maps to equivalent positions in
the view you are changing to. When you change the module, the runnable state-
ment on the displayed view is stored in memory and is viewed when the module is
displayed again. Line numbers that have breakpoints set are highlighted. When a
If you use this option with an ILE program object, the entry module with a root
source, COPY, or listing view is shown (if it exists). Otherwise, the first module
object bound to the program object with debug data is shown. If you use this option
with an OPM program object, then the source or listing view is shown (if available).
The module object module-name is shown. The module object must exist in a
program object that has been added to the debug session.
For example, to change from the module DBGEX in Figure 73 on page 171 to the
module cproc using the Display module source option, follow these steps:
1. To work with modules type DSPMODSRC, and press Enter. The Display Module
Source display is shown.
2. Press F14 (Work with module list) to show the Work with Module List display.
Figure 76 on page 176 shows a sample display.
3. To select cproc, type 5 (Display module source) next to it and press Enter.
Since a root source view is available, it is shown, as in Figure 77 on page 176.
If a root source was not available, the first module object bound to the program
object with debug data is shown.
Bottom
Command
===> ________________________________________________________________________
F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel
Figure 76. Changing to a Different Module
Display Module Source
Bottom
Debug . . . _________________________________________________________________
_______________________________________________________________________________
F3=End program F6=Add/Clear breakpoint F10=Step F11=Display variable
| F12=Resume F17=Watch variable F18=Work with watch F24=More keys
Figure 77. Source View of ILE C procedure cproc
You can change the view of the module object that is shown on the Display Module
Source display through the Select View display. The Select View display can be
accessed from the Display Module Source display by pressing F15 (Select View).
The Select View display is shown in Figure 78. The current view is listed at the top
of the window, and the other views that are available are shown below. Each
module object in a program object can have a different set of views available,
depending on the debug options used to create it.
For example, to change the view of the module from root source to listing, follow
these steps:
1. Type DSPMODSRC, and press Enter. The Display Module Source display is shown.
2. Press F15 (Select view). The Select View window is shown in Figure 78.
|
| Display Module Source
| ..............................................................................
| : Select View :
| : :
| : Current View . . . : ILE RPG Copy View :
| : :
| : Type option, press Enter. :
| : 1=Select :
| : :
| : Opt View :
| : 1 ILE RPG Listing View :
| : ILE RPG Source View :
| : ILE RPG Copy View :
| : :
| : Bottom :
| : F12=Cancel :
| : :
| :............................................................................:
| More...
| Debug . . . _________________________________________________________________
| _______________________________________________________________________________
| F3=End program F6=Add/Clear breakpoint F10=Step F11=Display variable
| F12=Resume F17=Watch variable F18=Work with watch F24=More keys
|
| Figure 78. Changing a View of a Module
The current view is listed at the top of the window, and the other views that are
available are shown below. Each module in a program can have a different set
of views available, depending on the debug options used to create it.
Note: If a module is created with DBGVIEW(*ALL), the Select View window
will show three views available: root source, COPY, and listing. If the
module has no /COPY members, then the COPY view is identical to the
root source view.
3. Type a 1 next to the listing view, and press Enter. The Display Module Source
display appears showing the module with a listing view.
| There are two types of breakpoints: job and thread. Each thread in a threaded
| application may have it's own thread breakpoint at the same position at the same
| time. Both job and thread breakpoints can be unconditional or conditional. In
| general, there is one set of debug commands and Function keys for job breakpoints
| and another for thread breakpoints. For the rest of this section on breakpoints, the
| word breakpoint refers to both job and thread, unless specifically mentioned other-
| wise.
| Note: This release does not support running ILE RPG procedures in a multi-
| threaded environment.
You set the breakpoints prior to running the program. When the program object
stops, the Display Module Source display is shown. The appropriate module object
is shown with the source positioned at the line where the breakpoint occurred. This
line is highlighted. At this point, you can evaluate fields, set more breakpoints, and
run any of the debug commands.
You should know the following characteristics about breakpoints before using them:
¹ When a breakpoint is set on a statement, the breakpoint occurs before that
statement is processed.
¹ When a statement with a conditional breakpoint is reached, the conditional
expression associated with the breakpoint is evaluated before the statement is
processed. If the expression is true, the breakpoint takes effect and the
program stops on that line.
¹ If the line on which you want to set a breakpoint is not a runnable statement,
the breakpoint will be set on the next runnable statement.
¹ If a breakpoint is bypassed that breakpoint is not processed.
¹ Breakpoint functions are specified through debug commands. These functions
include:
– Adding breakpoints to program objects
– Removing breakpoints from program objects
– Displaying breakpoint information
– Resuming the running of a program object after a breakpoint has been
reached
| – You can either have a job or thread breakpoint on a specified position at
| the same time, but not both.
If you change the view of the module after setting breakpoints, then the line
numbers of the breakpoints are mapped to the new view by the source debugger.
If you are debugging a module or program created with a statement view, then you
can set or remove breakpoints using statement numbers obtained from the compiler
| The simplest way to set and remove an unconditional job breakpoint is to use F6
(Add/Clear breakpoint). The function key acts as a toggle and so it will remove a
breakpoint from the line your cursor is on, if a breakpoint is already set on that line.
| To remove an unconditional job breakpoint using F13 (Work with module break-
| points), press F13 (Work with module breakpoints) from the Display Module Source
| display. A list of options appear which allow you to set or remove breakpoints. If
| you select 4 (Clear), a job breakpoint is removed from the line.
on the debug command line. The variable line-number is the line number in the
currently displayed view of the module object on which you want to set a break-
point.
on the debug command line. The variable line-number is the line number in the
currently displayed view of the module object from which you want to remove a
| breakpoint. When a job breakpoint is cleared, it is also cleared for all threads.
on the debug command line where module-name is the name of the module
that you want to display.
3. To set an unconditional breakpoint on the first Calculation specification, place
the cursor on line 88.
Display Module Source
5. After the breakpoint is set, press F3 (Exit) to leave the Display Module Source
display. The breakpoint is not removed.
6. Call the program. When a breakpoint is reached, the program stops and the
Display Module Source display is shown again, with the line containing the
breakpoint highlighted. At this point you can step through the program or
resume processing.
| The TBREAK debug command has the same syntax as the BREAK debug
| command. Where the BREAK debug command sets a job breakpoint at the same
| position in all threads, the TBREAK debug command sets a thread breakpoint in a
| single thread — the current thread.
| One way you can set or remove conditional job breakpoints is through the Work
with Module Breakpoints display. You access the Work with Module Breakpoints
display from the Display Module Source display by pressing F13 (Work with module
breakpoints). The display provides you with a list of options which allow you to
| either add or remove conditional and unconditional job breakpoints. An example of
the display is shown in Figure 80 on page 182.
| To make the job breakpoint conditional, specify a conditional expression in the Con-
| dition field. If the line on which you want to set a job breakpoint is not a runnable
statement, the breakpoint will be set at the next runnable statement.
| Once you have finished specifying all of the job breakpoints, you call the program.
You can use F21 (Command Line) from the Display Module Source display to call
the program object from a command line or call the program after exiting from the
display.
on the debug command line. The variable line-number is the line number in the
currently displayed view of the module object on which you want to set a breakpoint
and expression is the conditional expression that is evaluated when the breakpoint
is encountered. The relational operators supported for conditional breakpoints are
noted at the beginning of this section.
on the debug command line. The variable line-number is the line number in the
currently displayed view of the module object from which you want to remove a
breakpoint.
Work with Module Breakpoints
System: TORASD80
Program . . . : DEBUGEX Library . . . : MYLIB
Module . . . : DBGEX Type . . . . . : *PGM
Bottom
Command
===> ________________________________________________________________________
F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel
Breakpoint added to line 127.
Figure 80. Setting a Conditional Job Breakpoint
Display Module Source
The sort sequence table used by the source debugger for expressions of type
Char-8 is the sort sequence table specified on the SRTSEQ parameter for the
CRTRPGMOD or CRTBNDRPG commands.
If the resolved sort sequence table is *HEX, no sort sequence table is used. There-
fore, the source debugger uses the hexadecimal values of the characters to deter-
mine the sort sequence. Otherwise, the specified sort sequence table is used to
assign weights to each byte before the comparison is made. Bytes between, and
including, shift-out/shift-in characters are not assigned weights. This differs from the
way ILE RPG handles comparisons; all characters, including the shift-out/shift-in
characters, are assigned weights.
Notes:
1. The alternate sequence specified by ALTSEQ (*SRC) on the Control specifica-
tion is not available to the ILE source debugger. Instead the source debugger
uses the *HEX sort sequence table.
2. The name of the sort sequence table is saved during compilation. At debug
time, the source debugger uses the name saved from the compilation to access
the sort sequence table. If the sort sequence table specified at compilation time
resolves to something other than *HEX or *JOBRUN, it is important the sort
sequence table does not get altered before debugging is started. If the table
cannot be accessed because it is damaged or deleted, the source debugger
uses the *HEX sort sequence table.
Notes:
1. Character literal is of the form 'abc'.
2. Hexadecimal literal is of the form X'hex digits'.
3. Graphic literal is of the form G'oK1K2i'. Shift-out is represented as o and shift-in is
represented as i.
| To set an unconditional job breakpoint using the BREAK debug command, type:
BREAK procedure-name/statement-number
on the debug command line. The variable procedure-name is the name of the pro-
cedure in which you are setting the breakpoint, which for ILE RPG is the module
name. (ILE RPG only allows one procedure per module.) The variable statement-
number is the statement number from the compiler listing on which you want to set
a breakpoint.
For example, to set the breakpoint at statement-number 2 for the procedure TEST,
type:
BREAK TEST/2
Program: TEST Library: MYLIB Module: TEST
Bottom
Debug . . . break TEST/2
| To set a conditional job breakpoint using the BREAK debug command, type:
BREAK procedure-name/statement-number WHEN expression
| To remove a conditional thread breakpoint using the Work with Module Breakpoints
| display:
| 1. Type 4 (Clear) in the Opt field next to the breakpoint you want to remove.
| 2. Press Enter.
on the debug command line. The breakpoints are removed from all of the modules
bound to the program.
Characteristics of Watches
You should know the following characteristics about watches before working with
them:
¹ Watches are monitored system-wide, with a maximum number of 256 watches
that can be active simultaneously. This number includes watches set by the
system.
Depending on overall system use, you may be limited in the number of watch
conditions you can set at a given time. If you try to set a watch condition while
the maximum number of active watches across the system is exceeded, you
receive an error message and the watch condition is not set.
Note: If an expression or a variable crosses a page boundary, two watches
are used internally to monitor the storage locations. Therefore, the
maximum number of expressions or variables that can be watched
simultaneously system-wide ranges from 128 to 256.
¹ Watch conditions can only be set when a program is stopped under debug, and
the expression or variable to be watched is in scope. If this is not the case, an
error message is issued when a watch is requested, indicating that the corre-
sponding call stack entry does not exist.
¹ Once the watch condition is set, the address of a storage location watched
does not change. Therefore, if a watch is set on a temporary location, it could
result in spurious watch-condition notifications.
An example of this is the automatic storage of an ILE RPG subprocedure,
which can be re-used after the subprocedure ends.
A watch condition may be registered although the watched variable is no longer
in scope. You must not assume that a variable is in scope just because a
watch condition has been reported.
| ¹ Two watch locations in the same job must not overlap in any way. Two watch
locations in different jobs must not start at the same storage address; other-
System: DEBUGGER
Type options, press Enter.
4=Clear 5=Display
Bottom
Command
===>____________________________________________________________________
F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel
Figure 83. Example of a Work with Watch Display
| The Work with Watch display shows all watches currently active in the debug
| session. You can clear, and display watches from this display. When you
| select Option 5 Display, the Display Watch window shown below displays
| information about the currently active watch.
Work with Watch
..........................................................
: Display Watch : DEBUGGER
: :
: Watch Number ....: 1 :
: Address .........: 080090506F027004 :
: Length ..........: 4 :
: Number of Hits ..: 0 :
: :
: Scope when watch was set: :
: Program/Library/Type: PAYROLL ABC *PGM :
: :
: Module...: PAYROLL :
: Procedure: PAYROLL :
: Variable.: SALARY :
: :
: F12=Cancel :
: :
..........................................................
Bottom
Command
===>____________________________________________________________________
F3=Exit F4=Prompt F5=Refresh F9=Retrieve F12=Cancel
Figure 84. Example of a Display Watch Window
on a debug command line. This command brings up the Display Debug Watches
display shown below.
Display Debug Watches
System: DEBUGGER
------------Job--------------- NUM LENGTH ADDRESS
MYJOBNAME1 MYUSERPRF1 123456 1 5 080090506F027004
JOB4567890 PRF4567890 222222 1 8 09849403845A2C32
JOB4567890 PRF4567890 222222 2 2 098494038456AA00
JOB PROFILE 333333 14 4 040689578309AF09
SOMEJOB SOMEPROFIL 444444 3 4 005498348048242A
Bottom
Press Enter to continue
The watch number can be obtained from the Work With Watches display.
To clear all watches for your session, type:
CLEAR WATCH ALL
If the value of the variable SALARY changes subsequently, the application stops and
the Display Module Source display is shown, as illustrated in Figure 86 on
page 193.
¹ The line number of the statement where the change to the watch variable was
detected is highlighted. This is typically the first executable line following the
statement that changed the variable.
¹ A message indicates that the watch condition was satisfied.
Note: If a text view is not available, a blank Display Module Source display
is shown, with the same message as above in the message area.
The following programs cannot be added to the ILE debug environment:
1. ILE programs without debug data
2. OPM programs with non-source debug data only
3. OPM programs without debug data
In the first two cases, the stopped statement number is passed. In the third case,
the stopped MI instruction is passed. The information is displayed at the bottom of
a blank Display Module Source display as shown below. Instead of the line
number, the statement or the instruction number is given.
| F3=End program F12=Resume F14=Work with module list F18=Work with watch
F21=Command entry F22=Step into F23=Display output
Watch number 1 at instruction 18, variable: SALARY
Figure 87. Example of a Display Module Source Panel
You can step into an OPM program if it has debug data available and if the debug
session accepts OPM programs for debugging.
The simplest way to step through a program object one statement at a time is to
use F10 (Step) or F22 (Step into) on the Display Module Source display. When
you press F10 (Step) or F22 (Step into), then next statement of the module object
shown in the Display Module Source display is run, and the program object is
stopped again.
Note: You cannot specify the number of statements to step through when you use
F10 (Step) or F22 (Step into). Pressing F10 (Step) or F22 (Step into) per-
forms a single step.
Another way to step through a program object is to use the STEP debug command.
The STEP debug command allows you to run more than one statement in a single
step. The default number of statements to run, using the STEP debug command, is
one. To step through a program object using the STEP debug command, type:
STEP number-of-statements
on the debug command line, the next five statements of your program object are
run, then the program object is stopped again and the Display Module Source
display is shown.
A call statement for ILE RPG includes any of the following operations:
¹ CALL
¹ CALLB
¹ CALLP
¹ Any operation where there is an expression in the extended-factor 2 field, and
the expression contains a call to a procedure.
If you choose to step over the call statement, then you will stay inside the current
procedure. The call statement is processed as a single step and the cursor moves
to the next step after the call. Step over is the default step mode.
If you choose to step into the call statement, then each statement inside the call
statement is run as a single step. Depending on the number of steps specified, the
step command may end inside the call statement, in which case the source for the
call statement is shown in the Display Module Source display.
Note: You cannot step over or step into RPG subroutines. You can, however, step
over and into subprocedures.
You can use F10 (Step) on the Display Module Source display to step over a call
statement in a debug session. If the call statement to be run is a CALL operation to
another program object, then pressing F10 (Step) will cause the called program
object to run to completion before the calling program object is stopped again. Simi-
| larly, if the call statement is an EVAL operation where a procedure is called in the
expression, then the complete EVAL operation is performed, including the call to
the procedure, before the calling program or procedure is stopped again.
Alternately, you can use the STEP OVER debug command to step over a call
statement in a debug session. To use the STEP OVER debug command, type:
STEP number-of-statements OVER
You can use F22 (Step into) on the Display Module Source display to step into a
called program or procedure in a debug session. If the next statement to be run is
a call statement to another program or procedure, then pressing F22 (Step into) will
cause the first runnable statement in the called program or procedure to be run.
The called program or procedure will then be shown in the Display Module Source
display.
Note: The called program or procedure must have debug data associated with it
in order for it to be shown in the Display Module Source display.
Alternately, you can use the STEP INTO debug command to step into a call state-
ment in a debug session. To use the STEP INTO debug command, type:
STEP number-of-statements INTO
If one of the statements that are run contains a call statement the debugger will
step into the called program or procedure. Each statement in the called program or
procedure will be counted in the step. If the step ends in the called program or
procedure, then the called program or procedure will be shown in the Display
Module Source display. For example, if you type
STEP 5 INTO
on the debug command line, the next five statements of the program object are run.
If the third statement is a CALL operation to another program object, then two
statements of the calling program object are run and the first three statements of
the called program object are run.
In the example of DEBUGEX, if you enter STEP INTO (or press F22) while on the
EVAL operation that calls the procedure c_proc, then you would step into the C
module.
The STEP INTO command works with the CL CALL command as well. You can
take advantage of this to step through your program after calling it. After starting
the source debugger, from the initial Display Module Source display, enter
STEP 1 INTO
This will set the step count to 1. Use the F12 key to return to the command line
and then call the program. The program will stop at the first statement with debug
data.
Display Module Source
5. Press F22 (Step into). One statement of the program runs, and then the
Display Module Source display of RPGPGM is shown, as in Figure 89 on
page 198.
In this case, the first runnable statement of RPGPGM is processed (line 13)
and then the program stops.
Note: You cannot specify the number of statements to step through when you
use F22. Pressing F22 performs a single step.
Bottom
Debug . . . _________________________________________________________________
_______________________________________________________________________________
F3=End program F6=Add/Clear breakpoint F10=Step F11=Display variable
| F12=Resume F17=Watch variable F18=Work with watch F24=More keys
Step completed at line 13.
Figure 89. Stepping into RPGPGM
If the ILE source debugger is not set to accept OPM programs, or if there is no
debug data available, then you will see a blank Display Module Source display with
a message indicating that the source is not available. (An OPM program has debug
data if it was compiled with OPTION(*SRCDBG) or OPTION(*LSTDBG).)
Debug . . . _________________________________________________________________
_______________________________________________________________________________
F3=End program F6=Add/Clear breakpoint F10=Step F11=Display variable
| F12=Resume F17=Watch variable F18=Work with watch F24=More keys
Step completed at line 145.
Figure 90. Stepping into Subprocedure Switch
The scope of the fields used in the EVAL command can be defined by using the
QUAL command in languages such as ILE C. However, this command does not
currently apply to ILE RPG,
Note: You cannot display return values because there is no external name avail-
able for use with the EVAL debug command.
The easiest way to display data or an expression is to use F11 (Display variable)
on the Display Module Source display. To display a field using F11 (Display vari-
able), place your cursor on the field that you want to display and press F11
(Display variable). The current value of the field is shown on the message line at
the bottom of the Display Module Source display.
In cases where you are evaluating structures, records, or arrays, the message
returned when you press F11 (Display variable) may span several lines. Messages
that span several lines are shown on the Evaluate Expression display to show the
entire text of the message. Once you have finished viewing the message on the
Evaluate Expression display, press Enter to return to the Display Module Source
display.
Figure 91 shows an example of using the EVAL debug command to display the
contents of a subfield LastName.
Display Module Source
Figure 92 on page 201 shows the use of the EVAL command with different types
of RPG fields. The fields are based on the source in Figure 100 on page 212.
Additional examples are also provided in the source debugger online help.
Based Fields
> EVAL String 6A INZ('ABCDEF')
STRING = 'ABCDEF'
> EVAL BasePtr * INZ(%ADDR(String))
BASEPTR = SPP:C01947001218
> EVAL BaseString 6A BASED(BasePtr)
BASESTRING = 'ABCDEF'
The variable field-name is the name of the array, the variable n is a number repres-
enting the start of the range, and the variable m is a number representing the end
of the range.
You can change the current element using the %INDEX built-in function. To deter-
mine the value of the table index, enter the following command:
EVAL _QRNU_TABI_name
Figure 94 on page 203 shows the use of EVAL with the table in DBGEX.
Compile-time data: **
> EVAL TableA ** Show value at aaa
TABLEA = 'aaa' current index bbb
ccc
> EVAL TableA(1) ** Specify index 1 **
TABLEA(1) = 'aaa'
> EVAL TableA(2) ** Specify index 2 **
TABLEA(2) = 'bbb'
Similarly, to view the contents of a particular occurrence of a subfield, use the index
notation.
To determine the value of the current index, enter the following command:
EVAL _QRNU_DSI_name
where the variable subfield-name is the name of the subfield you wish to display,
occurrence-index is the number of the array occurrence to display, and array-index
is the number of the element to display.
** Note that you can enter the data structure name or a subfield name. **
To display a data structure for which no subfields have been defined, you must use
the character display function of EVAL which is discussed below.
Displaying Indicators
Indicators are defined as 1-byte character fields. Except for indicators such as
*INLR, you can display indicators either as '*INxx' or '*IN(xx)'. Because the system
stores indicators as an array, you can display them all or some subset of them
using the range notation. For example, if you enter EVAL *IN, you will get a list of
indicators 01 to 99. To display indicators *IN01 to *IN06 you would enter EVAL
*IN(1..6).
on the debug command line. The variable field-name is the name of the field that
you want to display in hexadecimal format. 'x' specifies that the field is to be dis-
played in hexadecimal format. The variable number-of-bytes indicates the number
of bytes displayed. If no length is specified after the 'x', the size of the field is
used as the length. A minimum of 16 bytes is always displayed. If the length of the
field is less than 16 bytes, then the remaining space is filled with zeroes until the 16
byte boundary is reached.
For example, the field String is defined as six-character string. To find out the
hexadecimal equivalent of the first 3 characters, you would enter:
| EVAL String: x 3
| Result:
| 00000 C1C2C3.. ........ ........ ........ - ABC.............
on the debug command line. The variable field-name is the name of the field that
you want to display in character format. 'c' specifies the number of characters to
display.
For example, in the program DEBUGEX, data structure DS2 does not have any
subfields defined. Several MOVE operations move values into the subfield.
This would be especially useful when the data that the pointer addresses is not
stored in printable form, such as packed or binary data.
When the debugger displays a null-capable field, the content of the field is dis-
played regardless of whether the field is considered null. For example, suppose
FLD1 is null-capable, and is currently null. Then the result of EVAL
_QRNU_NULL_FLD1 is '1' and EVAL FLD1 shows the current content of FLD1,
even though its null indicator is on.
EVAL _QRNU_NULL_FLD1 Result: _QRNU_NULL_FLD1 = '1'
EVAL FLD1 Result: FLD1 = 'abcde'
The %SUBSTR built-in function allows you to substring a string variable. The first
parameter must be a string identifier, the second parameter is the starting position,
and the third parameter is the number of single-byte or double-byte characters. In
addition. the second and third parameters must be positive, integer literals. Param-
eters are delimited by one or more spaces.
Figure 97 shows some examples of the use of %SUBSTR based on the source in
Figure 100 on page 212.
To change the current index, you can use the %INDEX built-in function, where the
index is specified in parentheses following the function name. An example of
%INDEX is found in the table section of Figure 94 on page 203 and Figure 95 on
page 204.
Note: %INDEX will change the current index to the one specified. Therefore, any
source statements which refer to the table or multiple-occurrence data struc-
ture subsequent to the EVAL statement may be operating with a different
index than expected.
Use the %VARS debug built-in function when the variable name conflicts with any
of the debug command names. For example, EVAL %VAR(EVAL) can be used to
evaluate a variable named EVAL, whereas EVAL EVAL would be a syntax error.
The scope of the fields used in the EVAL command is defined by using the QUAL
command. However, you do not need to specifically define the scope of the fields
contained in an ILE RPG module because they are all of global scope.
on the debug command line. field-name is the name of the variable that you want
to change and value is an identifier, literal, or constant value that you want to
assign to variable field-name. For example,
EVAL COUNTER=3
Use the EVAL debug command to assign numeric, alphabetic, and alphanumeric
data to fields. You can also use the %SUBSTR built-in function in the assignment
expression.
When you assign values to a character field, the following rules apply:
¹ If the length of the source expression is less than the length of the target
expression, then the data is left justified in the target expression and the
remaining positions are filled with blanks.
¹ If the length of the source expression is greater than the length of the target
expression, then the data is left justified in the target expression and truncated
to the length of the target expression.
Note: Graphic fields can be assigned any of the following:
¹ Another graphic field
¹ A graphic literal of the form G'oK1K2i'
¹ A hexadecimal literal of the form X'hex digits'
** Using %SUBSTR **
Figure 99 shows some examples of displaying field attributes based on the source
in Figure 100 on page 212. Additional examples are also provided in the source
debugger online help.
on the debug command line. shorthand-name is the name that you want to equate
with a field, expression, or debug command, and definition is the field, expression,
or debug command that you are equating with the name.
on the debug command line. Now, each time DC is typed on the debug command
line, the command EVAL COUNTER is performed.
To see the names that have been defined with the EQUATE debug command for a
debug session, type:
DISPLAY EQUATE
on the debug command line. A list of the active names is shown on the Evaluate
Expression display.
The program DEBUGEX is designed to show the different aspects of the ILE
source debugger and ILE RPG formatted dumps. The sample dumps are provided
in the next chapter.
The following steps describe how the program DEBUGEX was created for use in
these examples:
1. To create the module DBGEX using the source in Figure 100 on page 212,
type:
CRTRPGMOD MODULE(MYLIB/DBGEX) SRCFILE(MYLIB/QRPGLESRC) DBGVIEW(*ALL)
TEXT('Main module for Sample Debug Program')
The first module DBGEX is the entry module for this program. The program will
run in a new activation group (that is, *NEW) when it is called.
4. To create the called RPG program using the source in Figure 101 on
page 216, type:
CRTBNDRPG PGM(MYLIB/RPGPGM) DFTACTGRP(*NO)
DBGVIEW(*SOURCE) ACTGRP(*NEW)
TEXT('RPG program for Sample Debug Program')
We could have created RPGPGM to run in the OPM default activation group.
However, we decided to have it run in the same activation group as
DEBUGEX, and since DEBUGEX needs only a temporary activation group,
*NEW was chosen for both programs.
*=================================================================*
* DEBUGEX - Program designed to illustrate use of ILE source
* debugger with ILE RPG source. Provides a
* sample of different data types and data structures.
*
* Can also be used to produce sample formatted dumps.
*=================================================================*
*-----------------------------------------------------------------*
* The DEBUG keyword enables the formatted dump facility.
*-----------------------------------------------------------------*
H DEBUG
*-----------------------------------------------------------------*
* Define standalone fields for different ILE RPG data types.
*-----------------------------------------------------------------*
D String S 6A INZ('ABCDEF')
D Packed1D0 S 5P 2 INZ(-93.4)
D ZonedD3D2 S 3S 2 INZ(-3.21)
D Bin4D3 S 4B 3 INZ(-4.321)
D Bin9D7 S 9B 7 INZ(98.7654321)
D Int5 S 5I 0 INZ(-2046)
D Int10 S 10I 0 INZ(-31904)
D Unsigned5 S 5U 0 INZ(2046)
D Unsigned10 S 10U 0 INZ(31904)
D DBCSString S 3G INZ(G'"BBCCDD"')
* Array
D Arry S 3S 2 DIM(2) INZ(1.23)
* Table
D TableA S 3 DIM(3) CTDATA
*-----------------------------------------------------------------*
* Define different types of data structures.
*-----------------------------------------------------------------*
D DS1 DS OCCURS(3)
D Fld1 5A INZ('ABCDE')
D Fld1a 1A DIM(5) OVERLAY(Fld1)
D Fld2 5B 2 INZ(123.45)
*
D DS2 DS 10 OCCURS(2)
*
D DS3 DS
D Title 5A INZ('Mr. ')
D LastName 10A INZ('Jones ')
D FirstName 10A INZ('Fred ')
*-----------------------------------------------------------------*
* Define prototypes for called procedures c_proc and switch
*-----------------------------------------------------------------*
D c_proc PR * EXTPROC('c_proc')
D size 10U 0 VALUE
D inzval 1A CONST
D Switch PR
D Parm 1A
*-----------------------------------------------------------------*
* Define parameters for non-prototyped call
* PARM1 is used when calling RPGPROG program.
*-----------------------------------------------------------------*
D PARM1 S 4P 3 INZ(6.666)
D EXPORTFLD S 6A INZ('export') EXPORT
*-----------------------------------------------------------------*
* Change the occurrence of DS2 to 2 and move 'b's to DS2,
* making the first 10 bytes 'a's and the second 10 bytes 'b's.
*-----------------------------------------------------------------*
C 2 OCCUR DS2
C MOVE *ALL'b' DS2
*-----------------------------------------------------------------*
* Fld1a is an overlay field of Fld1. Since Fld1 is initialized
* to 'ABCDE', the value of Fld1a(1) is 'A'. After the
* following MOVE operation, the value of Fld1a(1) is '1'.
*-----------------------------------------------------------------*
C MOVE '1' Fld1a(1)
*-----------------------------------------------------------------*
* Call the program RPGPGM, which is a separate program object.
*-----------------------------------------------------------------*
C Plist1 PLIST
C PARM Parm1
C CALL 'RPGPGM' Plist1
*-----------------------------------------------------------------*
* Call c_proc, which imports ExportFld from the main procedure.
*-----------------------------------------------------------------*
C EVAL SpcPtr = c_proc(SpcSiz : 'P')
*-----------------------------------------------------------------*
* Call a local subprocedure Switch, which reverses the value of
* an indicator.
*-----------------------------------------------------------------*
C EVAL *IN10 = '0'
C CALLP Switch(*in10)
*-----------------------------------------------------------------*
* Put a new value in the second cell of Arry.
*-----------------------------------------------------------------*
C MOVE 4 Arry
*-----------------------------------------------------------------*
* Now start a formatted dump and return, by setting on LR.
*-----------------------------------------------------------------*
C DUMP
C SETON LR
*=================================================================*
* Define the subprocedure Switch.
*=================================================================*
P Switch B
D Switch PI
D Parm 1A
*-----------------------------------------------------------------*
* Define a local variable for debugging purposes.
*-----------------------------------------------------------------*
D Local S 5A INZ('aaaaa')
C IF Parm = '1'
C EVAL Parm = '0'
C ELSE
C EVAL Parm = '1'
C ENDIF
P Switch E
*=================================================================*
* Compile-time data section for Table. *
*=================================================================*
**
aaa
bbb
ccc
Figure 100 (Part 4 of 4). Source for Module DBGEX. DBGEX is the main module of the
program DEBUGEX.
D InputParm S 4P 3
C *ENTRY PLIST
C PARM InputParm
C InputParm DSPLY
C SETON LR
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
extern char EXPORTFLD[6];
Most programs benefit from some sort of planned exception handling because it
can minimize the number of unnecessary abnormal ends (namely, those associated
with function checks). ILE condition handlers also allow you to handle exceptions in
mixed-language applications in a consistent manner.
You can use the RPG exception handlers to handle most situations that might arise
in a RPG application. The minimum level of exception handling which RPG pro-
vides is the use of error indicators on certain operations. To learn how to use them,
read the following sections in this chapter:
¹ “ILE RPG Exception Handling” on page 220
¹ “Specifying Error Indicators or the 'E' Operation Code Extender” on page 227
For information on exception handling and the RPG cycle, see ILE RPG for AS/400
Reference.
Note: In this book the term 'exception handling' is used to refer to both exception
handling and error handling. However, for consistency with other RPG
terms, the term 'error' is used in the context of 'error indicator' and 'error
subroutine'.
Exception messages are associated with call stack entries. Each call stack entry is
in turn associated with a list of exception handlers defined for that entry. (See “The
Call Stack” on page 131 for further discussion of a call stack.)
Figure 103 on page 219 shows a call stack where an OPM program calls an ILE
program consisting of several modules and therefore several procedures. Refer to
this figure in the discussions which follow.
In general, when an exception occurs, the handlers associated with the call stack
entry are given a chance to handle the exception. If the exception is not handled by
any of the handlers on the list then it is considered to be unhandled, at which point
the following default actions are taken for the unhandled exception:
1. If the exception is a function check, the call stack entry is removed from the
stack.
2. The exception is moved (percolated) to the previous call stack entry.
3. The exception handling process is restarted for this call stack entry.
The action of allowing the previous call stack entry to handle an exception is
referred to as percolation. Percolation continues until the exception is handled, or
until the control boundary is reached. A control boundary is a call stack entry for
which the immediately preceding call stack entry is in a different activation group or
is an OPM program. In Figure 103 on page 219 Procedure P1 is the control
boundary.
Program A
Activation
ILE
Proc. P1
ILE Percolate
Unhandled
Proc. P2 Exception
Exception
Handlers
for P2
ILE
Proc. P3
exception
occurs
for P3
Pass 2
Call Stack
OPM
Program A Sending
Terminating
Exception CEE9901
Activation
ILE
Proc. P1
ILE Percolate
Function
Proc. P2 Check
(CPF9999)
Exception
Handlers
for P2
ILE
Proc. P3
exception
occurs
for P3
In OPM, the exception message is associated with the program which is active on
the call stack. If the exception is not handled by the associated exception handlers,
then a function check is sent to the same call stack entry which received the excep-
RPG categorizes exceptions into two classes, program and file; this determines
which type of error subroutine is called. Some examples of program exceptions are
division by zero, out-of-bounds array index, or SQRT of a negative number. Some
examples of file exceptions are undefined record type or a device error.
There are four ways for you to indicate that RPG should handle an exception. You
can:
1. Specify an error indicator in positions 73 - 74 of the calculation specifications of
the appropriate operation code.
| 2. Specify the operation code extender 'E' for the appropriate operation code.
3. Code a file error subroutine, which is defined by the INFSR keyword on a file
description specification, for file exceptions. The file error subroutine can only
be coded in the main source section. You cannot code an INFSR for a file that
is used in a subprocedure.
4. Code a program error subroutine, which is named *PSSR, for program
exceptions. Note that a *PSSR is local to the procedure in which it is coded.
This means that a *PSSR in a main procedure will handle only those program
errors associated with the main procedure. Similarly, a *PSSR in a subproce-
dure will only handle the errors in that subprocedure.
See “Unhandled Exceptions” on page 223 for a full description of the RPG default
handler.
Note that the PSDS and INFDS have module scope. Both main procedures and
subprocedures can access them.
TIP
In OPM, an inquiry message would be issued for PGM C. In ILE, the exception is
percolated to PGM B, since it is unhandled by PGM C. The error indicator in PGM
B is turned on allowing PGM B to handle the error, and in the process PGM C ends
abnormally. There is no inquiry message.
If PGM C has a *PSSR error subroutine coded, then in both OPM and ILE, the
exception is handled by PGM C and the error subroutine is run.
Note: Inquiry messages issued by ILE RPG will start with the prefix 'RNQ', not
'RPG', as in OPM RPG.
Certain behavioral differences exist for some specific errors. See Appendix A,
“Behavioral Differences Between OPM RPG/400 and ILE RPG for AS/400” on
page 373 for further information.
In addition, keep in mind the following when planning your exception handlers:
¹ Priority of handlers
¹ Nested exceptions
¹ Default actions for unhandled exceptions
¹ Effect of optimization level
Nested Exceptions
Exceptions can be nested. A nested exception is an exception that occurs while
another exception is being handled. When this happens, the processing of the first
exception is temporarily suspended. Exception handling begins again with the most
recently generated exception.
Unhandled Exceptions
An unhandled exception is one that has not been handled by an exception handler
associated with the call stack entry that first received the exception. When an
exception is unhandled, one of the following actions occurs:
If the message type is a function check (CPF9999) associated with a main pro-
cedure then the RPG default handler will issue an inquiry message describing the
originating condition.
¹ If you pick the D(ump) or C(ancel) option then the procedure which first
received the exception terminates and the function check is percolated to the
caller.
¹ If you pick the R(etry) or G(et Input) option then the function check is handled,
exception processing ends, and the procedure resumes processing at *GETIN
For other types of messages the exception is percolated up the call stack to the
caller of the procedure. That procedure is presented with the exception and given a
chance to handle it. If it does not, then the exception is percolated up the call stack
until it reaches the control boundary, at which point the exception is converted to a
function check, and exception handling starts over as described above.
When PGM1 calls PGM2, and the SUBST operation is attempted, an exception
message, RNX0100, is generated. Figure 104 depicts this scenario and the events
which occur.
Procedure PRC2
-1 SUBST RPG default Hdlr
RNX0100 issued
When PGM1 calls PGM2, a pointer error occurs because the basing pointer is
defined as null. Consequently, MCH1306 is generated. A function check occurs
when PRC2 tries to percolate the exception past the control boundary. Figure 105
on page 226 depicts this scenario and the events which occur.
Procedure PRC1
Percolate CALL PRC2 RPG default Hdlr
MCH3601
Procedure PRC2
RPG default Hdlr
D FLD S 5A BASED(PTR)
C EVAL PTR=NULL
C EVAL FLD='ABCDE'
MCH3601 issued
PASS 2
Procedure PRC1
Percolate CALL PRC2 RPG default Hdlr
CPF9999
Procedure PRC2
RPG default Hdlr
D FLD S 5A BASED(PTR)
C EVAL PTR=NULL
C EVAL FLD='ABCDE'
CPF9999 issued
Optimization Considerations
While running a *FULL optimized program, the optimizer may keep frequently used
values in machine registers and restore them to storage only at predefined points
during normal program processing. Exception handling may break this normal proc-
essing and consequently program variables contained in registers may not be
returned to their assigned storage locations.
Specifically, variables may not contain their current values if an exception occurs
and you recover from it using one of:
¹ *PSSR error subroutine
ILE RPG automatically defines indicators such that they contain their current values
even with full optimization. To ensure that the content of fields or data structures
contain their correct (current) values, specify the NOOPT keyword on the appro-
priate Definition specification.
For more information on the NOOPT keyword, see ILE RPG for AS/400 Reference.
For more information on optimization, see “Changing the Optimization Level” on
page 87.
You can obtain more information about the error which occurred by coding the
appropriate data structures and querying the relevant data structure fields.
| If you are using the 'E' extender instead of error indicators, the relevant program
| and file error information can be obtained by using the %STATUS and %ERROR
| built-in-functions.
This section provides some examples of how to use each of these RPG constructs.
The ILE RPG for AS/400 Reference provides more information on the *PSSR and
INFSR error subroutines, on the EXSR operation code, and on the INFDS and
PSDS data structures.
| To enable the RPG error indicator handler, you specify an error indicator in posi-
| tions 73 and 74 for the operation codes listed in Table 13 on page 228 (except for
| CALLP). If an exception occurs on the operation, the indicator is set on, the appro-
| priate data structure (PSDS or INFDS) is updated, and control returns to the next
| To enable the 'E' operation code extender handler, you specify an 'E' (or 'e') with
| any of the operation codes in Table 13. Coding the 'E' extender affects the value
| returned by the built-in functions %ERROR and %STATUS for exceptions. Before
| the operation begins, the value returned by these built-in functions is set to zero. If
| an exception occurs on the operation, the return values for these built-in functions
| are updated accordingly, the appropriate data structure (PSDS or INFDS) is
| updated, and control returns to the next sequential instruction. You can then use
| these built-in functions to test the returned values and determine what action to
| take.
| Table 13. Operation Codes Allowing Extender 'E' or an Error Indicator in Positions
| 73-74
| ACQ (e) ADDDUR (e) ALLOC (e) CALL (e)
| CALLB(d e) CALLP (e m/r)1 CHAIN (e n) CHECK (e)
| CHECKR (e) CLOSE (e) COMMIT (e) DEALLOC(e/n)
| DELETE (e) DSPLY (e) EXFMT (e) EXTRCT (e)
| FEOD (e) IN (e) NEXT (e) OCCUR (e)
| OPEN (e) OUT (e) POST (e) READ (e n)
| READC (e) READE (e n) READP (e n) READPE (e n)
| REALLOC (e) REL (e) RESET (e) ROLBK (e)
| SCAN (e) SETGT (e) SETLL (e) SUBDUR (e)
| SUBST (e p) TEST (e d/t/z) UNLOCK (e) UPDATE (e)
| WRITE (e) XLATE (e p)
| Notes:
| 1. CALLP (e m/r) is an extended Factor-2 operation code and cannot have an error
| indictator. However, program status and error conditions can be determined by spec-
| ifying the 'e' extender with this operation code.
| When you specify an error indicator or an 'E' extender on an operation code, you
| can explicitly call a file error subroutine (INFSR) or a program error subroutine
| (*PSSR) with the EXSR operation. If either INFSR or *PSSR is explicitly called by
| the EXSR operation and Factor 2 of the ENDSR operation is blank or the field
| specified has a value of blank, control returns to the next sequential instruction fol-
| lowing the EXSR operation.
A file error subroutine can handle errors in more than one file.
To add a file error subroutine to your program, you do the following steps:
1. Enter the name of the subroutine after the keyword INFSR on a File
Description specification. The subroutine name can be *PSSR, which indicates
that the program error subroutine is given control for the exception on this file.
2. Optionally identify the file information data structure on a File Description spec-
ification using the keyword INFDS.
3. Enter a BEGSR operation where the Factor 1 entry contains the same subrou-
tine name that is specified for the keyword INFSR.
Figure 106 on page 231 shows an example of exception handling using an INFSR
error subroutine. The program TRNSUPDT is a simple inventory update program. It
uses a transaction file TRANSACT to update a master inventory file PRDMAS. If an
I/O error occurs, then the INFSR error subroutine is called. If it is a record lock
error, then the record is written to a backlog file. Otherwise, an inquiry message is
issued.
Note that the File specification for PRDMAS identifies both the INFDS and identifies
the INFSR to be associated with it.
*-----------------------------------------------------------------*
* Define the files: *
* 1) PRDMAS - Product master file *
* 2) TRANSACT - Transaction file *
* 3) TRNBACKLG - Transaction backlog file *
* 2) PRINT - Error report. *
*-----------------------------------------------------------------*
FPRDMAS UF E K DISK
F INFSR(PrdInfsr)
F INFDS(PrdInfds)
FTRANSACT IP E DISK
FTRNBACKLG O E DISK
FPRINT O F 80 PRINTER
*-----------------------------------------------------------------*
* Define the file information data structure for file PRDMAS. *
* The *STATUS field is used to determine what action to take. *
*-----------------------------------------------------------------*
D PrdInfds DS
D PrdStatus *STATUS
*-----------------------------------------------------------------*
* List of expected exceptions. *
*-----------------------------------------------------------------*
D ErrRecLock C CONST(1218)
*-----------------------------------------------------------------*
* Error report format. *
*-----------------------------------------------------------------*
OPRINT E NOTFOUND
O TRNPRDNO
O 29 'NOT IN PRDMAS FILE'
Note that the check for a record lock error is done by matching the *STATUS sub-
field of the INFDS for PRDMAS against the field ErrRecLock which is defined with
the value of the record lock status code. The INFSR could be extended to handle
You can code a *PSSR for any (or all) procedures in the module. Each *PSSR is
local to the procedure in which it is coded.
To add a *PSSR error subroutine to your program, you do the following steps:
1. Optionally identify the program status data structure (PSDS) by specifying an S
in position 23 of the definition specification.
2. Enter a BEGSR operation with a Factor 1 entry of *PSSR.
3. Identify a return point, if any, and code it on the ENDSR operation in the sub-
routine. For subprocedures, factor 2 must be blank. For a discussion of the
valid entries for Factor 2, see “Specifying a Return Point in the ENDSR
Operation” on page 238.
4. Code the rest of the program error subroutine. Any of the ILE RPG compiler
operations can be used in the program error subroutine. The ENDSR operation
must be the last specification for the program error subroutine.
*-----------------------------------------------------------------*
* BODY OF CODE GOES HERE
* An error occurs when division by zero takes place.
* Control is passed to the *PSSR subroutine.
*-----------------------------------------------------------------*
*=================================================================*
* *PSSR: Error Subroutine for the main procedure. We check for a
* division by zero error, by checking if the status is
* 102. If it is, we add 1 to the divisor and continue
* by moving *GETIN to ReturnPt.
*=================================================================*
C *PSSR BEGSR
C IF Err = 102
C ADD 1 Divisor
C MOVE '*GETIN' ReturnPt 6
*-----------------------------------------------------------------*
* An unexpected error has occurred, and so we move
* *CANCL to ReturnPt to end the procedure.
*-----------------------------------------------------------------*
C ELSE
C MOVE '*CANCL' ReturnPt
C ENDIF
C ENDSR ReturnPt
If the exception was not a divide by zero, the literal ‘*CANCL’ is moved into the
ReturnPt field, and the procedure ends.
Figure 108 on page 235 and Figure 109 on page 236 show how you would code
similar program error subroutines in a subprocedure. In one example, you code a
GOTO and in the other you code a RETURN operation.
C *PSSR BEGSR
*-----------------------------------------------------------------*
* If this is a divide-by-zero error, add 1 to the divisor
* and try again
*-----------------------------------------------------------------*
C IF Err = 102
C ADD 1 Divisor
C GOTO TryAgain
C ENDIF
*-----------------------------------------------------------------*
* If control reaches ENDSR, the procedure will fail
*-----------------------------------------------------------------*
C ENDSR
P E
C *PSSR BEGSR
*-----------------------------------------------------------------*
* If this is a divide-by-zero error, return 0 from the subprocedure
*-----------------------------------------------------------------*
C IF Err = 102
C RETURN 0
C ENDIF
*-----------------------------------------------------------------*
* If control reaches ENDSR, the procedure will fail
*-----------------------------------------------------------------*
C ENDSR
P E
One way to avoid such a loop is to set a first-time switch in the subroutine. If it is
not the first time through the subroutine, you can specify an appropriate return
point, such as *CANCL, for the Factor 2 entry of the ENDSR operation.
Figure 110 on page 237 shows a program NOLOOP which is designed to generate
exceptions in order to show how to avoid looping within a *PSSR subroutine. The
program generates an exception twice:
1. In the main body of the code, to pass control to the *PSSR
2. Inside the *PSSR to potentially cause a loop.
*-----------------------------------------------------------------*
* Generate an array out of bounds error to pass control to *PSSR. *
*-----------------------------------------------------------------*
C Z-ADD -1 Neg1 5 0
C MOVE Arr1(Neg1) Arr1(Neg1)
C MOVE *ON *INLR
*=================================================================*
* *PSSR: Error Subroutine for the procedure. We use the *
* variable InPssr to detect recursion in the PSSR. *
* If we detect recursion, then we *CANCL the procedure. *
*=================================================================*
C *PSSR BEGSR
C IF InPssr = 1
C MOVE '*CANCL' ReturnPt 6
C Z-ADD 0 InPssr 1 0
C ELSE
C Z-ADD 1 InPssr
* *
* We now generate another error in the PSSR to see *
* how the subroutine cancels the procedure. *
* *
C MOVE Arr1(Neg1) Arr1(Neg1)
* *
* Note that the next two operations will not be *
* processed if Neg1 is still negative. *
* *
C MOVE '*GETIN' ReturnPt
C Z-ADD 0 InPssr
C ENDIF
C ENDSR ReturnPt
| To create the program and start debugging it, using the source in Figure 110, type:
| CRTBNDRPG PGM(MYLIB/NOLOOP) DBGVIEW(*SOURCE)
| STRDBG PGM(MYLIB/NOLOOP)
Set a break point on the BEGSR line of the *PSSR subroutine so you can step
through the *PSSR subroutine.
The approach used here to avoid looping can also be used within an INFSR error
subroutine.
After the ENDSR operation of the INFSR or the *PSSR subroutine is run, the ILE
RPG compiler resets the field or array element specified in Factor 2 to blanks.
Because Factor 2 is set to blanks, you can specify the return point within the sub-
routine that is best suited for the exception that occurred.
If this field contains blanks at the end of the subroutine, the ILE RPG default excep-
tion handler receives control following the running of the subroutine, unless the
INFSR or the *PSSR subroutine was called by the EXSR operation. If the subrou-
tine was called by the EXSR operation and Factor 2 of the ENDSR operation is
blank, control returns to the next sequential instruction following the EXSR opera-
tion.
Note: You cannot specify a factor 2 entry for an ENDSR in a subprocedure. If you
want to resume processing in the subprocedure, you have to use a GOTO
operation to a TAG in the body of the subprocedure. Alternatively, you can
code a RETURN operation in the *PSSR. The subprocedure will then return
to the caller.
There are several reasons why you might want to use an ILE condition handler:
¹ You can bypass language-specific handling by handling the exception in your
own handler.
This enables you to provide the same exception handling mechanism in an
application with modules in different ILE HLLs.
¹ You can use this API to scope exception handling to a call stack entry.
The ILE bindable API CEEHDLR is scoped to the invocation that contains it. It
remains in effect until you unregister it, or until the procedure returns.
Note: Any call to the CEEHDLR API from any detail, total or subroutine calcu-
lation will make the condition handler active for the entire procedure,
including all input, calculation, and output operations. However, it will
not affect subprocedures, nor will a subprocedure calling CEEHDLR
affect the main procedure.
If a subprocedure is called recursively, only the invocation that calls CEEHDLR
is affected by it. If you want the condition handler active for every invocation,
then CEEHDLR must be called by each invocation.
For information on how to use ILE condition handlers, refer to ILE Concepts.
While SHOWERR is designed primarily to show how RPGHDLR works, the two
procedures combined are also useful for determining 'how' ILE exception handling
works. Both procedures write to QSYSPRT the 'actions' which occur as they are
processed. You might want to modify these procedures in order to simulate other
aspects of ILE exception handling which you would like to explore.
Figure 111 on page 240 shows the source for the procedure RPGHDLR. The pro-
cedure defines three procedure parameters: an ILE condition token structure, a field
*=================================================================*
* RPGHDLR: RPG exception handling procedure. *
* This procedure does the following: *
* Handles the exception if it is the RPG *
* out of bounds error (RNX0100) *
* otherwise *
* percolates the exception *
* It also prints out what it has done. *
* *
* Note: This is the exception handling procedure for the *
* SHOWERR procedure. *
*=================================================================*
FQSYSPRT O F 132 PRINTER
*-----------------------------------------------------------------*
* Procedure parameters *
* 1. Input: Condition token structure *
* 2. Input: Procedure name in which error occurred *
* 3. Output: Code identifying actions to be performed on the *
* exception *
* 4. Output: New condition if we decide to promote the *
* condition. Since this handler only resumes and *
* percolates, we will ignore this parameter. *
*-----------------------------------------------------------------*
D CondTok DS
D MsgSev 4B 0
D MsgNo 2A
D 1A
D MsgPrefix 3A
D 4A
D pPSDS S *
D PassedPSDS DS BASED(pPSDS)
D ProcName 1 10
D Action S 9B 0
*
* Action codes are:
*
D Resume C 10
D Percolate C 20
Figure 111 (Part 1 of 2). Source for Condition Handler for Out-of-Bounds Substring Error
*-----------------------------------------------------------------*
* If substring error, then handle else percolate. *
* Note that the message number value (MsgNo) is in hex. *
*-----------------------------------------------------------------*
C EXCEPT
C IF MsgPrefix = 'RNX' AND
C MsgNo = X'0100'
C EXCEPT Handling
C EVAL Action = Resume
C ELSE
C EXCEPT Perclating
C EVAL Action = Percolate
C ENDIF
C RETURN
*=================================================================*
* Procedure Output *
*=================================================================*
OQSYSPRT E
O 'In Handler for '
O ProcName
OQSYSPRT E Handling
O ' Handling...'
OQSYSPRT E Perclating
O ' Percolating.. .'
Figure 111 (Part 2 of 2). Source for Condition Handler for Out-of-Bounds Substring Error
Figure 112 on page 242 shows the source for the procedure SHOWERR, in which
the condition handler RPGHDLR is registered.
*=================================================================*
* SHOWERR: Show exception handling using a user-defined *
* exception handler. *
*=================================================================*
FQSYSPRT O F 132 PRINTER
*-----------------------------------------------------------------*
* The following are the parameter definitions for the CEEHDLR *
* API. The first is the procedure pointer to the *
* procedure which will handle the exception. The second *
* is a pointer to a communication area which will be passed *
* to the exception handling procedure. In this example, *
* we will pass a pointer to the name of this procedure *
*-----------------------------------------------------------------*
D pConHdlr S * PROCPTR
D INZ(%paddr('RPGHDLR'))
*-----------------------------------------------------------------*
* PSDS *
*-----------------------------------------------------------------*
D DSPsds SDS NOOPT
D ProcName *PROC
*-----------------------------------------------------------------*
* Array that will be used to cause an error *
*-----------------------------------------------------------------*
D Arr1 S 10A DIM(5)
*-----------------------------------------------------------------*
* CEEHDLR Interface *
*-----------------------------------------------------------------*
D CEEHDLR PR
D pConHdlr * PROCPTR
D CommArea * CONST
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------*
* CEEHDLU Interface *
*-----------------------------------------------------------------*
D CEEHDLU PR
D pConHdlr * PROCPTR
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------*
* Generate a substring error *
*-----------------------------------------------------------------*
C Z-ADD -1 Neg1 5 0
C Neg1 SUBST 'Hello' Examp 10
*-----------------------------------------------------------------*
* The exception was handled by the handler and control *
* resumes here. *
*-----------------------------------------------------------------*
C EXCEPT ImBack
*-----------------------------------------------------------------*
* Generate an array out of bounds error *
*-----------------------------------------------------------------*
C MOVE Arr1(Neg1) Arr1(Neg1)
*-----------------------------------------------------------------*
* The exception was not handled by the handler, so, *
* control does not return here. The exception is *
* percolated and control resumes in the *PSSR. *
*-----------------------------------------------------------------*
*-----------------------------------------------------------------*
* Deregister the handler *
* Note: If an exception occurs before the handler is *
* deregistered, it will be automatically deregistered *
* when the procedure is cancelled. *
*-----------------------------------------------------------------*
C EXSR DeRegHndlr
C
C SETON LR
*=================================================================*
* RegHdlr - Call the API to register the Handler *
*=================================================================*
C RegHndlr BEGSR
C CALLP CEEHDLR(pConHdlr : %ADDR(DSPsds) : *OMIT)
C ENDSR
*=================================================================*
* DeRegHndlr - Call the API to unregister the Handler *
*=================================================================*
C DeRegHndlr BEGSR
C ENDSR
C EXCEPT InPssr
C EXCEPT Cancelling
C ENDSR '*CANCL'
*=================================================================*
* Procedure Output *
*=================================================================*
OQSYSPRT E ImBack
O 'I'm Back'
OQSYSPRT E InPssr
O 'In PSSR'
OQSYSPRT E Cancelling
O 'Cancelling...'
2. To create the procedure SHOWERR, using the source shown in Figure 112 on
page 242, type:
CRTRPGMOD MODULE(MYLIB/SHOWERR)
The Register Call Stack Entry Termination User Exit Procedure (CEERTX) and the
Call Stack Entry Termination User Exit Procedure (CEEUTX) ILE bindable APIs
Figure 113 shows an example of enabling and coding a cancel handler for a sub-
procedure. (Cancel handlers can also be enabled for main procedures in the same
way.)
*-----------------------------------------------------------------
* Define the prototype for the cancel handler. This procedure is
* a local procedure.
*-----------------------------------------------------------------
D CanHdlr PR
D pMsg *
*-----------------------------------------------------------------
* Define the prototype for a subprocedure to enable the cancel
* handler.
*-----------------------------------------------------------------
D Enabler PR
*-----------------------------------------------------------------
* Define the prototype for a subprocedure to call Enabler
*-----------------------------------------------------------------
D SubProc PR
*-----------------------------------------------------------------
* Main procedure. Call SubProc three times.
*-----------------------------------------------------------------
C CALLP SubProc
C CALLP SubProc
C CALLP SubProc
C SETON LR
| Figure 113 (Part 1 of 4). Enabling and Coding a Cancel Handler for a Subprocedure
*-----------------------------------------------------------------
* Procedure SubProc. Call Enabler. Since this call will fail,
* define a local *PSSR subroutine to handle the error.
*-----------------------------------------------------------------
P SubProc B
C CALLP Enabler
*-----------------------------------------------------------------
* The PSSR has a RETURN operation, so the call from the main
* procedure to SubProc will not fail.
*-----------------------------------------------------------------
C *PSSR BEGSR
C 'Subproc PSSR'DSPLY
C RETURN
C ENDSR
P SubProc E
| Figure 113 (Part 2 of 4). Enabling and Coding a Cancel Handler for a Subprocedure
* Local variables
D Handler S * PROCPTR INZ(%PADDR('CANHDLR'))
D Msg S 20A
D pMsg S * INZ(%ADDR(Msg))
D Zero S 5P 0 INZ(0)
D Count S 5I 0 INZ(0) STATIC
D Array S 1A DIM(2)
*-----------------------------------------------------------------
* Enable the cancel handler. When this procedure gets canceled,
* procedure 'CANHDLR' will be called.
*-----------------------------------------------------------------
C CALLB 'CEERTX'
C PARM Handler
C PARM pMsg
C PARM *OMIT
*-----------------------------------------------------------------
* This procedure will be called three times. The first two times
* will get an error while the cancel handler is enabled.
*-----------------------------------------------------------------
C EVAL Count = Count + 1
C SELECT
C WHEN Count = 1
C EVAL Msg = 'Divide by zero'
C EVAL Zero = Zero / Zero
C WHEN Count = 2
C EVAL Msg = 'String error'
C 'A' SCAN 'ABC':Zero Zero
*-----------------------------------------------------------------
* On the third call, disable the cancel handler. The array index
* error will cause the procedure to fail, but the handler will
* not be invoked.
*-----------------------------------------------------------------
C WHEN Count = 3
C CALLB 'CEEUTX'
C PARM Handler
C PARM *OMIT
C EVAL Msg = 'Array index error'
C EVAL Array(Zero) = 'x'
C ENDSL
P Enabler E
| Figure 113 (Part 3 of 4). Enabling and Coding a Cancel Handler for a Subprocedure
*-----------------------------------------------------------------
* Define a field based on the input pointer pMsg.
*-----------------------------------------------------------------
D Msg S 20A BASED(pMsg)
*-----------------------------------------------------------------
* Display the message set by the procedure that enabled the
* handler.
*-----------------------------------------------------------------
C 'Cancel Hdlr 'DSPLY Msg
P CanHdlr E
| Figure 113 (Part 4 of 4). Enabling and Coding a Cancel Handler for a Subprocedure
The following is the output from program CANHDLR. Note that the *PSSR of the
procedure SubProc is called three times but the cancel handler is only called twice
because it was disabled before the third error.
For example, if the ILE RPG procedure writes a record to a printer file and the
actual printer file has a shorter record length that was declared in the RPG proce-
dure, notify message CPF4906 is sent to the RPG procedure. The RPG exception
handling percolates this message which causes the default reply of 'I' to ignore the
message. This should allow the output operation to continue normally, and the RPG
procedure should proceed to the next instruction.
However, when the ILE CL MONMSG gets control, control passes immediately to
the action for the MONMSG or the next statement in the ILE CL procedure.
Note: For this problem to occur, the procedure monitoring for the message does
not have to be the immediate caller of the RPG procedure.
If you encounter this problem, you have two possible ways to avoid it:
1. Ensure that the caller is in a different activation group from the ILE RPG proce-
dure.
2. Enable an ILE condition handler in the RPG procedure. In the handler, if the
message is one that you want to ignore, indicate that the message should be
handled. Otherwise, indicate that it should be percolated.
You could also make this handler more generic, and have it ignore all mes-
sages with a severity of 0 (information) and 1 (warning).
| Figure 115 on page 249 shows an example of a ILE condition handler that
| ignores CPF4906.
*----------------------------------------------------------------
* Actions
*----------------------------------------------------------------
D Handle C 10
D Percolate C 20
*----------------------------------------------------------------
* Severities
*----------------------------------------------------------------
D Info C 0
D Warning C 1
D Error C 2
D Severe C 3
D Critical C 4
C *ENTRY PLIST
C PARM Token
C PARM dummy 1
C PARM Action
*----------------------------------------------------------------
* If this is CPF4906, handle the notify msg, otherwise percolate
*----------------------------------------------------------------
C IF Prefix = 'CPF' AND
C MsgNo = X'4906'
C EVAL Action = Handle
C ELSE
C EVAL Action = Percolate
C ENDIF
C RETURN
| Figure 116 on page 250 shows how you would code the calculations if you
| wanted to ignore all status and notify messages. Escape messages and func-
| tion checks have a severity of 2 (Error) or higher.
C ELSE
C EVAL Action = Percolate
C ENDIF
C RETURN
The formatted dump includes field contents, data structure contents, array and table
contents, the file information data structures, and the program status data structure.
The dump is written to the file called QPPGMDMP. (A system abnormal dump is
written to the file QPSRVDMP.)
If you respond to an ILE RPG run-time message with an F option, the dump also
includes the hexadecimal representation of the open data path (ODP, a data man-
agement control block).
The dump information includes the global data associated with the module.
Depending on whether the main procedure is active, the global data may not repre-
sent the values assigned during processing of the *INZSR. If a program consists of
more than one procedure, the information in the formatted dump also reflects infor-
mation about every procedure that is active at the time of the dump request. If a
procedure is not active, the values of variables in automatic storage will not be
valid. If a procedure has not been called yet, the static storage will not be initialized
yet. If a procedure has been called recursively, only the information for the most
recent invocation will be shown.
Note: To obtain a dump of variable data, the program object must have debug
data. That is, it must be created with any debug view except *NONE. If no
debug data is available, then the dump will still contain the PSDS and file
information.
The dump for this example is a full-formatted dump; that is, it was created when an
inquiry message was answered with an 'F'.
.A/ Procedure Identification: the procedure name, the program and library
name, and the module name.
.B/ Current status code.
.C/ Previous status code.
.D/ ILE RPG source statement in error.
Feedback Areas
PRINTER FEEDBACK:
Current Line Number. . . . . . . . . . : 1
Current Page . . . . . . . . . . . . . : 1
Major Return Code. . . . . . . . . . . : 00
Minor Return Code. . . . . . . . . . . : 00
Output Buffer:
0000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 * *
0020 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 * *
0040 00000000 00000000 00000000 00000000 * *
.I/ This is the file feedback section of the INFDS. Only fields applicable to
the file type are printed. The rest of the INFDS feedback sections are
not dumped, since they are only updated if they have been declared in
the program.
The common open data path and the feedback areas associated with the file are
included in the dump if you respond to an ILE RPG inquiry message with an F
option.
Data Information
.N/
NAME ATTRIBUTES VALUE
_QRNU_DSI_DS1 INT(10) 1 '00000001'X .O/
_QRNU_DSI_DS2 INT(10) 2 '00000002'X
_QRNU_NULL_ARR CHAR(1) DIM(8) .P/
(1-2) '1' 'F1'X
(3) '0' 'F0'X
(4) '1' 'F1'X
(5-6) '0' 'F0'X
(7) '1' 'F1'X
(8) '0' 'F0'X
_QRNU_NULL_FLDNULL CHAR(1) '1' 'F1'X
_QRNU_TABI_TABLEA INT(10) 1 '00000001'X .Q/
ARR CHAR(2) DIM(8)
(1-3) 'AB' 'C1C2'X
(4-7) ' ' '4040'X
(8) '1' 'F1'X
ARRY ZONED(3,2) DIM(2)
(1-2) 1.24 'F1F2F4'X
BASEONNULL CHAR(10) NOT ADDRESSABLE
BASEPTR POINTER SPP:E30095A62F001208
BASESTRING CHAR(6) 'ABCDEF' 'C1C2C3C4C5C6'X
BIGDATE DATE(10) '1994-09-30' 'F1F9F9F460F0F960F3F0'X
BIGTIME TIME(8) '12.00.00' 'F1F24BF0F04BF0F0'X
BIGTSTAMP TIMESTAMP(26) '9999-12-31-12.00.00.000000'
VALUE IN HEX 'F9F9F9F960F1F260F3F160F1F24BF0F04BF0F04BF0F0F0F0F0F0'X
BIN4D3 BIN(4,3) -4.321 'EF1F'X
BIN9D7 BIN(9,7) 98.7654321 '3ADE68B1'X
DBCSSTRING GRAPHIC(3) ' BBCCDD ' 'C2C2C3C3C4C4'X
In order for a program to perform any I/O operations, it must identify the file
description(s) the program is referencing, what type of I/O device is being used,
and how the data is organized. This chapter provides general information on:
¹ Associating file descriptions with input/output devices
¹ Defining externally described files
¹ Defining program-described files
¹ Data management operations
Each I/O device has a corresponding file description of one of the above types
which the program uses to access that device. The actual device association is
made when the file is processed: the data is read from or written to the device
when the file is used for processing.
RPG also allows access to files and devices not directly supported by the system,
through the use of SPECIAL files. With a SPECIAL file, you must provide a
program that handles the association of the name to the file, and the data manage-
ment for the file. With other types of files, this is handled by RPG and the operating
system.
To indicate to the operating system which file description(s) your program will use,
you specify a file name in positions 7 through 16 of a file description specification
for each file used. In positions 36 through 42 you specify an RPG device name.
The device name defines which RPG operations can be used with the associated
file. The device name can be one of: DISK, PRINTER, WORKSTN, SEQ, or
Note that it is the file name, not the device name (specified in positions 36 through
42) which points to the OS/400 file description that contains the specifications for
the actual device.
The RPG device types correspond to the above file types as follows:
Table 14. Correlation of RPG Device Types with AS/400 File Types
RPG Device Type AS/400 File Type
DISK database, save, DDM files
PRINTER printer files
WORKSTN display, ICF files
SEQ tape, diskette, save, printer, database
SPECIAL N/A
Figure 122 illustrates the association of the RPG file name FILEX, as coded in
Figure 121, with a system file description for a display file.
At compilation time, certain RPG operations are valid only for a specific RPG
device name. In this respect, the RPG operation is device dependent. One example
of device dependency is that the EXFMT operation code is valid only for a
WORKSTN device.
Other operation codes are device independent, meaning that they can be used with
any device type. For example, WRITE is a device-independent operation.
The device SEQ is an independent device type. Figure 123 on page 263 illustrates
the association of the RPG file name FILEY with a system file description for a
sequential device. When the program is run, the actual I/O device is specified in the
description of FILEY. For example, the device might be PRINTER.
Although the file name and file type are coded in the RPG program, in many cases
you can change the type of file or the device used in a program without changing
the program. To find out how, see “Overriding and Redirecting File Input and
Output” on page 273.
Naming Files
On the AS/400 system, files are made up of members. These files are organized
into libraries. The convention for naming files is library-name/file-name.
In an ILE RPG program, file names are identified in positions 7 through 16 in file
description specifications. File names can be up to ten characters long and must be
unique.
You do not qualify the file name with a library within a program. At run time, the
system searches the library list associated with your job to find the file. If you wish
to change the name, member, or specify a particular library, you can use a file
override command. See “Overriding and Redirecting File Input and Output” on
page 273 for more information on file overrides.
At compile time, the compiler uses the field descriptions in the input or/and output
specifications. It does not retrieve the external descriptions.
Figure 124. Typical Relationships between an RPG Program and Files on the AS/400 System
.1/ The program uses the field-level description of a file that is defined to
the operating system. An externally described file is identified by an E in
position 22 of the file description specifications. At compilation time, the
compiler copies in the external field-level description.
The information the compiler retrieves from the external description is printed on
the compiler listing as long as OPTION(*EXPDDS) is specified on either the
CRTRPGMOD or CRTBNDRPG command when compiling the source member.
(The default for both of these commands is OPTION(*EXPDDS).)
To rename a record-format name, use the RENAME keyword on the file description
specifications for the externally described file as shown in Figure 125. The format
is RENAME(old name:new name).
Figure 125. RENAME Keyword for Record Format Names in an Externally Described File
The RENAME keyword is generally used if the program contains two files which
have the same record-format names. In Figure 125, the record format
ITEMFORMAT in the externally described file ITMMSTL is renamed MSTITM for
use in this program.
Figure 126. Prefix Keyword for Record Format Names in an Externally Described File
The file must have more than one record format, and not all of them can be
ignored; at least one must remain. Except for that requirement, any number of
record formats can be ignored for a file.
Ignored record-format names appear on the cross-reference listing, but they are
flagged as ignored.
Alternatively, the INCLUDE keyword can be used to include only those record
format names that are to be used in a program. All other record formats contained
in the file will be excluded.
Figure 127. IGNORE Keyword for Record Formats in an Externally Described File
You cannot use the input specifications to override field locations in an externally
described file. The fields in an externally described file are placed in the records in
the order in which they are listed in the data description specifications. Also,
device-dependent functions such as forms control, are not valid in an RPG program
for externally described files.
Note: You can explicitly rename a field on an input specification, even when the
PREFIX keyword is specified for a file. The compiler will recognize (and
require) the name that is first used in your program. For example, if you
specify the prefixed name on an input specification to associate the field
You can use output specification to control when the data is to be written, or to
specify selective fields that are to be written. The valid entries for the field-
description line for an externally described file are output indicators (positions 21 -
29), field name (positions 30 - 43), and blank after (position 45). Edit words and
edit codes for fields written to an externally described file are specified in the DDS
for the file. Device-dependent functions such as fetch overflow (position 18) or
space/skip (positions 40 - 51) are not valid in an RPG program for externally
described files. The overflow indicator is not valid for externally described files
either. For a description of how to specify editing in the DDS, see the DDS Refer-
ence.
If output specifications are used for an externally described file, the record-format
name is specified in positions 7 - 16 instead of the file name.
If all the fields in an externally described file are to be placed in the output record,
enter *ALL in positions 30 through 43 of the field-description line. If *ALL is speci-
fied, you cannot specify other field description lines for that record.
If you want to place only certain fields in the output record, enter the field name in
positions 30 through 43. The field names you specify in these positions must be the
field names defined in the external record description, unless the field was renamed
on the input specifications. See Figure 130 on page 270.
You should know about these considerations for using the output specifications for
an externally described file:
¹ In the output of an update record, only those fields specified in the output field
specifications and meeting the conditions specified by the output indicators are
placed in the output record to be rewritten. Fields not specified in the output
specifications are rewritten using the values that were read. This technique
offers a good method of control as opposed to the UPDATE operation code
that updates all fields.
.1/ For an update file, all fields in the record are written to the externally
described record ITMREC using the current values in the program for all
fields in the record.
For the creation of a new record, all fields in the record are written to
the externally described record ITMREC using the current values in the
program for the fields in the record.
.2/ To update a record, the fields SLSNAM and COMRAT are written to the
externally described record SLSREC when indicator 30 is on. The field
BONUS is written to the SLSREC record when indicators 30 and 15 are
on. All other fields in the record are written with the values that were
read.
To create a new record, the fields SLSNAM and COMRAT are written to
the externally described record SLSREC when indicator 30 is on. The
field BONUS is written when indicators 30 and 15 are on. All other fields
in the record are written as default values, which depend on their data
type (for example: a blank for character fields; zero for numeric fields).
Level Checking
HLL programs are dependent on receiving, at run time, an externally described file
whose format agrees with what was copied into the program at compilation time.
For this reason, the system provides a level-check function that ensures that the
format is the same.
The RPG compiler always provides the information required by level checking when
an externally described DISK, WORKSTN, or PRINTER file is used. The level-
check function can be requested on the create, change, and override file com-
mands. The default on the create file command is to request level checking.
Level checking occurs on a record-format basis when the file is opened unless you
specify LVLCHK(*NO) when you issue a file override command or create a file. If
the level-check values do not match, the program is notified of the error. The RPG
program then handles the OPEN error as described in Chapter 12, “Handling
Exceptions” on page 217.
For more information on how to specify level checking, see the Data Management
manual.
A program-described file must exist on the system, and be in your library list,
before the program can run. To create a file, use one of the Create File commands,
which can be found in the CL Reference.
READ
By relative READ, CHAIN
record number
By key READ, READE, CHAIN, primary and
secondary file
Sequential READ
Previous READP, READPE
Next READ, READE
Invited Device READ
WRITE-READ EXFMT
WRITE
By relative WRITE
record number
By key WRITE, EXCEPT, primary and secondary file
Sequential WRITE, EXCEPT
FEOD FEOD
UPDATE
By relative UPDATE, primary and secondary file
record number
By key UPDATE, primary and secondary file
DELETE
By relative DELETE, primary and secondary file
record number
By key DELETE, primary and secondary file
ACQUIRE ACQ
RELEASE REL
COMMIT COMMIT
ROLLBACK ROLBK
FILEY
RPG program
Override Command:
File name = FILEY OVRDBF FILE (FILEY) TOFILE (FILEA)
Device = DISK
FILEA
File type = Diskette
DEVICE
Execution
Time Device type =
DISKETTE
To override a file at run time, you must make sure that record names in both files
are the same. The RPG program uses the record-format name on the input/output
operations, such as a READ operation where it specifies what record type is
expected.
Not all file redirections or overrides are valid. At run time, checking ensures that the
specifications within the RPG program are valid for the file being processed. The
OS/400 system allows some file redirections even if device specifics are contained
The default scope for overrides is the activation group. For job-level scope, specify
OVRSCOPE(*JOB) on the override command. For call-level scope, specify
OVRSCOPE(*CALLLVL) on the override command.
See the Data Management manual for more detailed information on valid file redi-
rections and file overrides. ILE Concepts also contains information about overrides
and activation group vs. job level scope.
RPG program
File Locking
The OS/400 system allows a lock state (exclusive, exclusive allow read, shared for
update, shared no update, or shared for read) to be placed on a file used during
the execution of a job. Programs within a job are not affected by file lock states. A
file lock state applies only when a program in another job tries to use the file con-
currently. The file lock state can be allocated with the CL command ALCOBJ (Allo-
cate Object). For more information on allocating resources and lock states, see the
Data Management manual.
The OS/400 system places the following lock states on database files when it
opens the files:
The shared-for-read lock state allows another user to open the file with a lock state
of shared for read, shared for update, shared no update, or exclusive allow read,
but the user cannot specify the exclusive use of the file. The shared-for-update lock
state allows another user to open the file with shared-for-read or shared-for-update
lock state.
The lock state placed on the file by the RPG program can be changed if you use
the Allocate Object command.
In RPG IV programs, you use an update file to read records for update. A record
read from a file with a type other than update can be read for inquiry only. By
default, any record that is read from an update file will be read for update. For
update files, you can specify that a record be read for input by using one of the
input operations CHAIN, READ, READE, READP, or READPE and specifying an
operation code extender (N) in the operation code field following the operation code
name.
When a record is locked by an RPG IV program, that lock remains until one of the
following occurs:
¹ the record is updated.
¹ the record is deleted.
¹ another record is read from the file (either for inquiry or update).
¹ a SETLL or SETGT operation is performed against the file
¹ an UNLOCK operation is performed against the file.
¹ an output operation defined by an output specification with no field names
included is performed against the file.
Note: An output operation that adds a record to a file does not result in a
record lock being released.
If your program reads a record for update and that record is locked through another
program in your job or through another job, your read operation will wait until the
record is unlocked (except in the case of shared files, see “Sharing an Open Data
Path” on page 277). If the wait time exceeds that specified on the WAITRCD
parameter of the file, an exception occurs. If your program does not handle this
exception (RNX1218) then the default error handler is given control when a record
lock timeout occurs, an RNQ1218 inquiry message will be issued. One of the
options listed for this message is to retry the operation on which the timeout
occurred. This will cause the operation on which the timeout occurred to be re-
issued, allowing the program to continue as if the record lock timeout had not
occurred. Note that if the file has an INFSR specified in which an I/O operation is
performed on the file before the default error handler is given control, unexpected
results can occur if the input operation that is retried is a sequential operation,
since the file cursor may have been modified.
Note: Subprocedures do not get inquiry message, and so this situation should be
handled by using an error indicator on the read operation and checking for
status 1218 following the read.
If no changes are required to a locked record, you can release it from its locked
state, without modifying the file cursor, by using the UNLOCK operation or by proc-
essing output operations defined by output specifications with no field names
(There are exceptions to these rules when operating under commitment control.
See “Using Commitment Control” on page 307 for more information.)
The position of the current record is kept in the open data path for all programs
using the file. If you read a record in one program and then read a record in a
called program, the record retrieved by the second read depends on whether the
open data path is shared. If the open data path is shared, the position of the
current record in the called program is determined by the current position in the
calling program. If the open data path is not shared, each program has an inde-
pendent position for the current record.
If your program holds a record lock in a shared file and then calls a second
program that reads the shared file for update, you can release the first program's
lock by :
¹ performing a READ operation on the update file by the second program, or
¹ using the UNLOCK or the read-no-lock operations.
In ILE, shared files are scoped to either the job level or the activation group level.
Shared files that are scoped to the job level can be shared by any programs
running in any activation group within the job. Shared files that are scoped to the
activation group level can be shared only by the programs running in the same
activation group.
The default scope for shared files is the activation group. For job-level scope,
specify OVRSCOPE(*JOB) on the override command.
ILE RPG offers several enhancements in the area of shared ODPs. If a program or
procedure performs a read operation, another program or procedure can update the
record as long as SHARE(*YES) is specified for the file in question. In addition,
when using multiple-device files, if one program acquires a device, any other
program sharing the ODP can also use the acquired device. It is up to the pro-
grammer to ensure that all data required to perform the update is available to the
called program.
Sharing an open data path improves performance because the OS/400 system
does not have to create a new open data path. However, sharing an open data
path can cause problems. For example, an error is signaled in the following cases:
¹ If a program sharing an open data path attempts file operations other than
those specified by the first open (for example, attempting input operations
although the first open specified only output operations)
When several files in one program are overridden to one shared file at run time, the
file opening order is important. In order to control the file opening order, you should
use a programmer-controlled open or use a CL program to open the files before
calling the program.
If a program shares the open data path for a primary or secondary file, the program
must process the detail calculations for the record being processed before calling
another program that shares that open data path. Otherwise, if lookahead is used
or if the call is at total time, sharing the open data path for a primary or secondary
file may cause the called program to read data from the wrong record in the file.
You must make sure that when the shared file is opened for the first time, all of the
open options that are required for subsequent opens of the file are specified. If the
open options specified for subsequent opens of a shared file are not included in
those specified for the first open of a shared file, an error message is sent to the
program.
Table 16 details the system open options allowed for each of the open options you
can specify.
Table 16. System Open Options Allowed with User Open Options
RPG User System
Open Options Open Options
INPUT INPUT
OUTPUT OUTPUT (program created file)
UPDATE INPUT, UPDATE, DELETE
ADD OUTPUT (existing file)
For additional information about sharing an open data path, see the DB2 for
AS/400 Database Programming manual. ILE Concepts also contains information
about sharing open data paths and activation group versus job level scope.
Spooling
Spooling is a system function that puts data into a storage area to wait for proc-
essing. The AS/400 system provides for the use of input and output spooling func-
tions. Each AS/400 file description contains a spool attribute that determines
whether spooling is used for the file at run time. The RPG program is not aware
that spooling is being used. The actual physical device from which a file is read or
to which a file is written is determined by the spool reader or the spool writer. For
more detailed information on spooling, see the Data Management manual.
Spooled
File
Execution Time
Start
Printer
writer
Start Printer
writer Time
Device
File override commands can be used at run time to override the spooling options
specified in the file description, such as the number of copies to be printed. In addi-
tion, AS/400 spooling support allows you to redirect a file after the program has
run. You can direct the same printed output to a different device such as a diskette.
You should decide whether to use SRTSEQ for your RPG program based on how
you want operations such as IFxx, COMP, and SORTA, to work on your character
data, not on what was specified when creating your files.
DISK files of an ILE RPG program also associate with distributed data management
(DDM) files, which allow you to access files on remote systems as database files.
Database Files
Database files are objects of type *FILE on the AS/400. They can be either phys-
ical or logical files and either externally described or program-described. You
access database files by associating the file name with the device DISK in positions
36 through 42 of the file description specifications.
Database files can be created by OS/400 Create File commands. For more infor-
mation on describing and creating database files, refer to the DB2 for AS/400 Data-
base Programming manual and the DDS Reference.
A physical file can have a keyed sequence access path. This means that data is
presented to a program in a sequence based on one or more key fields in the file.
Logical files do not contain data. They contain a description of records found in
one or more physical files. A logical file is a view or representation of one or more
physical files. Logical files that contain more than one format are referred to as
multi-format logical files.
If your program processes a logical file which contains more than one record
format, you can use a read by record format to set the format you wish to use.
Usually, database files that contain source programs are made up of more than one
member. Organizing source programs into members within database files allows
you to better manage your programs. The source member contains source state-
ments that the system uses to create program objects.
These specifications result from the DDS for the file and the OS/400 create file
command that is used for the file.
For a complete list of the DDS keywords that are valid for a database file, see the
DB2 for AS/400 Database Programming.
Figure 134 on page 283 shows an example of the DDS for a database file, and
Figure 135 on page 284 for a field-reference file that defines the attributes for the
fields used in the database file. See the DDS Reference for more information on a
field-reference file.
Access Path
The description of an externally described file contains the access path that
describes how records are to be retrieved from the file. Records can be retrieved
based on an arrival sequence (non-keyed) access path or on a keyed-sequence
access path.
The arrival sequence access path is based on the order in which the records are
stored in the file. Records are added to the file one after another.
For the keyed-sequence access path, the sequence of records in the file is based
on the contents of the key field that is defined in the DDS for the file. For example,
in the DDS shown in Figure 134 on page 283, CUST is defined as the key field.
The keyed-sequence access path is updated whenever records are added, deleted,
or when the contents of a key field change.
For a complete description of the access paths for an externally described data-
base file, see the DB2 for AS/400 Database Programming manual.
Figure 134. Example of the Data Description Specifications for a Database File
The sample DDS are for the customer master logical file CUSMSTL. The file con-
tains one record format CUSREC (customer master record). The data for this file is
contained in the physical file CUSMSTP, which is identified by the keyword PFILE.
The UNIQUE keyword is used to indicate that duplicate key values are not allowed
for this file. The CUST field is identified by a K in position 17 of the last line as the
key field for this record format.
The fields in this record format are listed in the order they are to appear in the
record. The attributes for the fields are obtained from the physical file CUSMSTP.
The physical file, in turn, refers to a field-reference file to obtain the attributes for
the fields. The field-reference file is shown in Figure 135 on page 284.
This example of a field-reference file shows the definitions of the fields that are
used by the CUSMSTL (customer master logical) file as shown in Figure 134 on
page 283. The field-reference file normally contains the definitions of fields that are
used by other files. The following text describes some of the entries for this field-
reference file.
.1/ The BASDAT field is edited by the Y edit code, as indicated by the
keyword EDTCDE(Y). If this field is used in an externally described
output file for an ILE RPG program, the edit code used is the one speci-
fied in this field-reference file; it cannot be overridden in the ILE RPG
program. If the field is used in a program-described output file for an ILE
The key for a file is determined by the valid keys for the record types in that file.
The file’s key is determined in the following manner:
¹ If all record types in a file have the same number of key fields defined in the
DDS that are identical in attributes, the key for the file consists of all fields in
the key for the record types. (The corresponding fields do not have to have the
same name.) For example, if the file has three record types and the key for
each record type consists of fields A, B, and C, the file’s key consists of fields
A, B, and C. That is, the file’s key is the same as the records’ key.
¹ If all record types in the file do not have the same key fields, the key for the file
consists of the key fields common to all record types. For example, a file has
three record types and the key fields are defined as follows:
– REC1 contains key field A.
– REC2 contains key fields A and B.
– REC3 contains key fields A, B, and C.
The file’s key is field A–the key field common to all record types.
¹ If no key field is common to all record types, there is no key for the file.
In an ILE RPG program, you can specify a search argument on certain file opera-
tion codes to identify the record you want to process. The ILE RPG program com-
pares the search argument with the key of the file or record, and processes the
specified operation on the record whose key matches the search argument.
For an operation to a file name, the maximum number of fields that you can specify
in a search argument is equal to the total number of key fields valid for the file’s
key. For example, if all record types in a file do not contain all of the same key
fields, you can use a key list (KLIST) to specify a search argument that is com-
posed only of the number of fields common to all record types in the file. If a file
contains three record types, the key fields are defined as follows:
The search argument can only be a single field with attributes identical to field A
because field A is the only key field common to all record types. The search argu-
ment cannot contain a floating point, variable length, or null-capable field.
For an operation to a record name, the maximum number of fields that you can
specify in a search argument is equal to the total number of key fields valid for that
record type.
If the search argument consists of one field, you can specify a literal, a field name,
or a KLIST name with one KFLD. If the search argument is composed of more than
one field (a composite key), you must specify a KLIST with multiple KFLDs. To
process null-valued keys a KLIST must be used.
The attributes of each field in the search argument must be identical to the attri-
butes of the corresponding field in the file or record key. The attributes include the
length, the data type and the number of decimal positions. The attributes are listed
in the key-field-information data table of the compiler listing. See the example in
“Key Field Information” on page 433.
In all these file operations (CHAIN, DELETE, READE, READPE, SETGT, and
SETLL), you can also specify a search argument that contains fewer than the total
number of fields valid for the file or record. Such a search argument refers to a
partial key.
If a search argument refers to a partial key, the file is positioned at the first record
that satisfies the search argument or the record retrieved is the first record that
satisfies the search argument. For example, the SETGT and SETLL operations
position the file at the first record on the access path that satisfies the operation
and the search argument. The CHAIN operation retrieves the first record on the
access path that satisfies the search argument. The DELETE operation deletes the
first record on the access path that satisfies the search argument. The READE
operation retrieves the next record if the portion of the key of that record (or the
record of the specified type) on the access path matches the search argument. The
READPE operation retrieves the prior record if the portion of the key of that record
(or the record of the specified type) on the access path matches the search argu-
ment. For more information on the above operation codes, see the ILE RPG for
AS/400 Reference.
The RPG compiler generates object program code to block and unblock records for
all SEQ or DISK files that satisfy the above conditions. Certain OS/400 system
restrictions may prevent blocking and unblocking. In those cases, performance is
not improved.
You can explicitly request record blocking by specifying the keyword BLOCK(*YES)
on the file-description specification for the file. The only difference between the
default record blocking and user-requested record blocking is that when
BLOCK(*YES) is specified for input files, then the operations SETLL, SETGT and
CHAIN can be used with the input file (see condition 3c above) and blocking will
still occur. If the BLOCK keyword is not specified and these operations are used,
no record blocking will occur.
You can also prevent the default blocking of records by specifying the keyword
BLOCK(*NO) on the file-description specification. If BLOCK(*NO) is specified, then
The input/output and device-specific feedback of the file information data structure
are not updated after each read or write (except for the RRN and Key information
on block reads) for files in which the records are blocked and unblocked by the
RPG compiler. The feedback area is updated each time a block of records is trans-
ferred. (For further details on the file information data structure see the ILE RPG for
AS/400 Reference.)
You can obtain valid updated feedback information by preventing the file from being
blocked and unblocked. Use one of the following ways to prevent blocking:
¹ Specify BLOCK(*NO) on the file description specification.
¹ At run time, use the CL command OVRDBF (Override with Database File) with
SEQONLY(*NO) specified.
Indexed File
An indexed file is a program-described DISK file whose access path is built on key
values. You must create the access path for an indexed file by using data
description specifications.
The key fields identify the records in an indexed file. You specify the length of the
key field in positions 29 through 33, the format of the key field in position 34, and
the starting location of the key field in the KEYLOC keyword of the file description
specifications.
The DDS specifies the fields to be used as a key field. The KEYLOC keyword of
the file description specifications specify the starting position of the first key field.
The entry in positions 29 through 33 of the file description specifications must
specify the length of the key as defined in the DDS.
Figure 136 on page 289 and Figure 137 on page 289 show examples of how to
use the DDS to describe the access path for indexed files.
Figure 136. DDS and corresponding File-Description Specification Detail Flow of RPG IV
Exception/Error Handling
You must use data description specifications to create the access path for a
program-described indexed file.
In the DDS for the record format FORMATA for the logical file ORDDTLL, the field
ORDER, which is five digits long, is defined as the key field, and is in packed
format. The definition of ORDER as the key field establishes the keyed access for
this file. Two other fields, FLDA and FLDB, describe the remaining positions in this
record as character fields.
Figure 137. (Part 1 of 2). Using Data Description Specifications to Define the Access Path
(Composite Key) for an Indexed File
In this example, the data description specifications define two key fields for the
record format FORMAT in the logical file ORDDTLL. For the two fields to be used
as a composite key for a program described indexed file, the key fields must be
contiguous in the record.
Figure 138. (Part 2 of 2). Using Data Description Specifications to Define the Access Path
(Composite Key) for an Indexed File
When the DDS specifies a composite key, you must build a search argument in the
program to CHAIN to the file. (A KLIST cannot be used for a program-described
file.) One way is to create a data structure (using definition specifications) with sub-
fields equal to the key fields defined in the DDS. Then, in the calculations, set the
subfields equal to the value of the key fields, and use the data-structure name as
the search argument in the CHAIN operation.
In this example, the MOVE operations set the subfields K1 and K2 equal to the
value of ORDER and ITEM, respectively. The data-structure name (KEY) is then
used as the search argument in the CHAIN operation.
Sequential File
Sequential files are files where the order of the records in the file is based on the
order the records are placed in the file (that is, in arrival sequence). For example,
the tenth record placed in the file occupies the tenth record position.
Limits Records
For sequential-within-limits processing, the record-address file contains limits
records. A limits record contains the lowest record key and the highest record key
of the records in the file to be read.
With Keys
Without Keys
Sequentially Blank A, D, G, P, I
T, Z, or F
Randomly Blank A, D, G, P, I
T, Z, or F
Sequential within limits L A, D, G, P, I
(by record-address file) T, Z, or F
Without Keys
Consecutive Processing
During consecutive processing, records are read in the order they appear in the file.
For output and input files that do not use random functions (such as SETLL,
SETGT, CHAIN, or ADD), the ILE RPG compiler defaults to or operates as though
SEQONLY(*YES) had been specified on the CL command OVRDBF (Override with
Database File). (The ILE RPG compiler does not operate as though
SEQONLY(*YES) had been specified for update files.) SEQONLY(*YES) allows
multiple records to be placed in internal data management buffers; the records are
then passed to the ILE RPG compiler one at a time on input.
For more information on sequential only processing, see the DB2 for AS/400 Data-
base Programming.
Sequential-by-Key Processing
For the sequential-by-key method of processing, records are read from the file in
key sequence.
For output files and for input files that do not use random functions (such as
SETLL, SETGT, CHAIN, or ADD) and that have only one record format, the ILE
RPG compiler defaults to or operates as though SEQONLY(*YES) had been speci-
fied on the CL command OVRDBF. (The ILE RPG compiler does not operate as
though SEQONLY(*YES) had been specified for update files.) SEQONLY(*YES)
allows multiple records to be placed in internal data management buffers; the
records are then passed to the ILE RPG compiler one at a time on input.
If, in the same job, two files use the same physical file, and one file is processed
sequentially and one is processed for random update, a record could be updated
that has already been placed in the buffer that is presented to the program. In this
case, when the record is processed from the sequential file, the record does not
reflect the updated data. To prevent this problem, use the CL command OVRDBF
and specify the option SEQONLY(*NO), which indicates that you do not want mul-
tiple records transferred for a sequentially processed file.
For more information on sequential only processing, see the DB2 for AS/400 Data-
base Programming manual.
A*****************************************************************
A* DESCRIPTION: This is the DDS for the physical file TRWEEK. *
A* It contains one record format called RCWEEK. *
A* This file contains all weekly entries made to *
A* the time reporting system. *
A*****************************************************************
A*
A R RCWEEK
A ENUM 5 0 TEXT('EMPLOYEE NUMBER')
A WEEKNO 2 0 TEXT('WEEK NUMBER OF CURRENT YEAR')
A EHWRK 4 1 TEXT('EMPLOYEE HOURS WORKED')
A K ENUM
A K WEEKNO
A*****************************************************************
A* RELATED FILES: EMPMST (Physical File) *
A* TRWEEK (Physical File) *
A* DESCRIPTION: This is the DDS for the logical file EMPL1. *
A* It contains two record formats called *
A* EMPREC and RCWEEK. *
A*****************************************************************
A R EMPREC PFILE(EMPMST)
A K ENUM
A*
A R RCWEEK PFILE(TRWEEK)
A K ENUM
A K WEEKNO
*****************************************************************
* PROGRAM NAME: YTDRPT1 *
* RELATED FILES: EMPL1 (Logical File) *
* PRINT (Printer File) *
* DESCRIPTION: This program shows an example of processing *
* records using the sequential-by-key method. *
* This program prints out each employee's *
* information and weekly hours worked. *
*****************************************************************
FPRINT O F 80 PRINTER
FEMPL1 IP E K DISK
IEMPREC 01
I*
IRCWEEK 02
I*
C SETOFF 12
C 01 MOVE ENUM EMPNO 5 0
C*
C IF (*IN02='1') AND (ENUM=EMPNO)
C SETON 12
C ENDIF
OPRINT H 1P 2 6
O 40 'EMPLOYEE WEEKLY WORKING '
O 52 'HOURS REPORT'
O H 01 1
O 12 'EMPLOYEE: '
O ENAME 32
O H 01 1
O 12 'SERIAL #: '
O ENUM 17
O 27 'DEPT: '
O EDEPT 30
O 40 'TYPE: '
O ETYPE 41
O H 01 1
O 20 'WEEK #'
O 50 'HOURS WORKED'
O D 12 1
O WEEKNO 18
O EHWRK 3 45
*****************************************************************
* PROGRAM NAME: YTDRPT2 *
* RELATED FILES: EMPL1 (Logical File) *
* PRINT (Printer File) *
* DESCRIPTION: This program shows an example of processing *
* records using the read operation code. *
* This program prints out each employee's *
* information and weekly hours worked. *
*****************************************************************
FPRINT O F 80 PRINTER
FEMPL1 IF E K DISK
* The two records (EMPREC and RCWEEK) are contained in the same
* file, and a record-identifying indicator is assigned to each
* record. The record-identifying indicators are used to control
* processing for the different record types. No control levels
* or match fields can be specified for a full-procedural file.
IEMPREC 01
I*
IRCWEEK 02
I*
* The READ operation code reads a record from the EMPL1 file. An
* end-of-file indicator is specified in positions 58 and 59. If
* the end-of-file indicator 99 is set on by the READ operation,
* the program branches to the EOFEND tag and processes the end-of-
* file routine.
C SETOFF 12
C READ EMPL1 99
C 99 GOTO EOFEND
C*
C 01 MOVE ENUM EMPNO 5 0
C*
C IF (*IN02='1') AND (ENUM=EMPNO)
C SETON 12
C ENDIF
C EOFEND TAG
C 99 SETON LR
*****************************************************************
* PROGRAM NAME: YTDRPT5 *
* RELATED FILES: EMPMST (Physical File) *
* TRWEEK (Physical File) *
* PRINT (Printer File) *
* DESCRIPTION: This program shows an example of processing *
* records using the matching record method. *
* This program prints out each employee's *
* information, weekly worked hours and amount *
* of overtime. *
*****************************************************************
FPRINT O F 80 PRINTER
FEMPMST IP E K DISK
FTRWEEK IS E K DISK
IEMPREC 01
I ENUM M1
IRCWEEK 02
I ENUM M1
OPRINT H 1P 2 6
O 50 'YTD PAYROLL SUMMARY'
O D 01 1
O 12 'EMPLOYEE: '
O ENAME 32
O D 01 1
O 12 'SERIAL #: '
O ENUM 17
O 27 'DEPT: '
O EDEPT 30
O 40 'TYPE: '
O ETYPE 41
O D 02 MR 1
O 8 'WEEK #'
O WEEKNO 10
O 32 'HOURS WORKED = '
O EHWRK 3 38
O D 01NMR 1
O 70 'YTD HOURS WORKED = '
O TOTHRS 3 78
O D 01NMR 1
O 70 'YTD OVERTIME HOURS = '
O TOTHRS 3 78
O T 01 12 1
O OR LR 12
O 70 'YTD HOURS WORKED = '
O TOTHRS 3 78
O T 01 12 1
O OR LR 12
O 70 'YTD OVERTIME HOURS = '
O TOTOVT 3 78
The random-by-key method of processing is valid for a full procedural file desig-
nated as an input file or an update file.
For an externally described file, position 34 of the file description specification must
contain a K, which indicates that the file is processed according to an access path
that is built on keys.
The data description specifications (DDS) for the file specifies the field that contains
the key value (the key field). Position 35 of the file description specification must be
blank.
A*****************************************************************
A* RELATED PGMS: EMSTUPD *
A* DESCRIPTIONS: This is the DDS for the physical file CHANGE. *
A* It contains one record format called CHGREC. *
A* This file contains new data that is used to *
A* update the EMPMST file. *
A*****************************************************************
A*
A R CHGREC
A ENUM 5 0 TEXT('EMPLOYEE NUMBER')
A NNAME 20 TEXT('NEW NAME')
A NTYPE 1 TEXT('NEW TYPE')
A NDEPT 3 0 TEXT('NEW DEPARTMENT')
A NNHRS 3 1 TEXT('NEW NORMAL WEEK HOURS')
A K ENUM
FCHANGE IP E K DISK
FEMPMST UF E K DISK
Sequential-within-Limits Processing
Sequential-within-limits processing by a record-address file is specified by an L in
position 28 of the file description specifications and is valid for a file with a keyed
access.
To process a file sequentially within limits from a record-address file, the program
reads:
¹ A limits record from the record-address file
The program repeats this procedure until the end of the record-address file is
reached.
Figure 139 on page 294 shows the data description specifications (DDS) for the
physical file used by the program ESWLIM1 ( Figure 147 on page 302) and
ESWLIM2 ( Figure 149 on page 303).
IEMPMST NS 01
I P 1 3 0ENUM
I 4 23 ENAME
I 24 24 ETYPE
I P 25 26 0EDEPT
OPRINT H 1P 1
O 12 'SERIAL #'
O 22 'NAME'
O 45 'DEPT'
O 56 'TYPE'
O D 01 1
O ENUM 10
O ENAME 35
O EDEPT 45
O ETYPE 55
A*****************************************************************
A* RELATED PROGRAMS: ESWLIM *
A* DESCRIPTION: This is the DDS for the physical file *
A* LIMITS. *
A* It contains a record format named LIMIT. *
A*****************************************************************
A
A R LIMIT
A LOW 5 0
A HIGH 5 0
Figure 148. DDS for record address file LIMITS (physical file)
*****************************************************************
* PROGRAM NAME: ESWLIM2 *
* RELATED FILES: EMPMST (Physical File) *
* LIMITS (Physical File) *
* PRINT (Printer File) *
* DESCRIPTION: This program shows the processing of an *
* externally described file sequentially *
* within limits. *
* This program prints out information for the *
* employees whose employee numbers are within *
* the limits given in the file LIMITS. *
*****************************************************************
IEMPREC 01
OPRINT H 1P 1
O 12 'SERIAL #'
O 22 'NAME'
O 45 'DEPT'
O 56 'TYPE'
O D 01 1
O ENUM 10
O ENAME 35
O EDEPT 45
O ETYPE 55
O*
Relative-Record-Number Processing
Random input or update processing by relative record number applies to full proce-
dural files only. The desired record is accessed by the CHAIN operation code.
Relative record numbers identify the positions of the records relative to the begin-
ning of the file. For example, the relative record numbers of the first, fifth, and
seventh records are 1, 5, and 7, respectively.
When you update or add a record to a file by relative record number, the record
must already have a place in the member. For an update, that place must be a
valid existing record; for a new record, that place must be a deleted record.
You can use the CL command INZPFM to initialize records for use by relative
record number. The current relative record number is placed in the RECNO field for
all retrieval operations or operations that reposition the file (for example, SETLL,
CHAIN, READ).
Before running your program, you can override a file to another file. In particular,
you can override a sequential file in your program to an externally described, keyed
file. (The file is processed as a sequential file.) You can also override a keyed file
in your program to another keyed file, providing the key fields are compatible. For
example, the overriding file must not have a shorter key field than you specified in
your program.
Note: When a database record is deleted, the physical record is marked as
deleted. Deleted records can occur in a file if the file has been initialized
with deleted records using the Initialize Physical File Member (INZPFM)
command. Once a record is deleted, it cannot be read. However, you can
use the relative record-number to position to the record and then write over
its contents.
The LCKLVL(Lock Level) parameter allows you to select the level at which records
are locked under commitment control. See “Commitment Control Locks” on
page 308 and the CL Programming manual for further details on lock levels.
You can make commitment control conditional, in the sense that the decision
whether to process a file under commitment control is made at run time. For further
information, see “Specifying Conditional Commitment Control” on page 311.
When you complete a group of changes with a COMMIT operation, you can specify
a label to identify the end of the group. In the event of an abnormal job end, this
identification label is written to a file, message queue, or data area so that you
know which group of changes is the last group to be completed successfully. You
specify this file, message queue, or data area on the STRCMTCTL command.
Before you call any program that processes files specified for commitment control,
issue the STRCMTCTL command. If you call a program that opens a file specified
The CL command ENDCMTCTL notifies the system that your activation group or
job has finished processing files under commitment control. See the CL Reference
for further information on the STRCMTCTL and ENDCMTCTL commands.
The COMMIT and ROLBK operations release the locks on the records. The
UNLOCK operation will not release records locked using commitment control. See
the CL Reference for details on lock levels.
The number of entries that can be locked under commitment control before the
COMMIT or ROLBK operations are required may be limited. For more information,
see the Backup and Recovery – Advanced manual.
Note: The SETLL and SETGT operations will lock a record in the same cases
where a read operation (not for update) would lock a record for commitment
control.
The scope for commitment definition indicates which programs within the job use
that commitment definition. A commitment definition can be scoped at the activation
group level or at the job level.
You specify the scope for a commitment definition on the commitment scope
(CMTSCOPE) parameter of the STRCMTCTL command. For further information on
the commitment control scope within ILE, refer to "Data Management Scoping" in
ILE Concepts, and also the Data Management manual.
When a program specifies commitment control for a file, the specification applies
only to the input and output operations made by this program for this file. Commit-
ment control does not apply to operations other than input and output operations. It
does not apply to files that do not have commitment control specified in the
program doing the input or output operation.
When more than one program accesses a file as a shared file, all or none of the
programs must specify the file to be under commitment control.
If the system fails, it implicitly issues a ROLBK operation. You can check the iden-
tity of the last successfully completed group of changes using the label you specify
in factor 1 of the COMMIT operation code, and the notify-object you specify on the
STRCMTCTL command.
At the end of an activation group or job, or when you issue the ENDCMTCTL
command, the OS/400 system issues an implicit ROLBK, which eliminates any
changes since the last ROLBK or COMMIT operation that you issued. To ensure
that all your file operations have effect, issue a COMMIT operation before ending
an activation group or job operating under commitment control.
The OPEN operation permits input and output operations to be made to a file and
the CLOSE operation stops input and output operations from being made to a file.
However, the OPEN and CLOSE operations do not affect the COMMIT and ROLBK
operations. A COMMIT or ROLBK operation affects a file, even after the file has
been closed. For example, your program may include the following steps:
1. Issue COMMIT (for files already opened under commitment control).
2. Open a file specified for commitment control.
3. Perform some input and output operations to this file.
4. Close the file.
The changes made at step 3 are rolled back by the ROLBK operation at step 5,
even though the file has been closed at step 4. The ROLBK operation could be
issued from another program in the same activation group or job.
A program does not have to operate all its files under commitment control, and to
do so may adversely affect performance. The COMMIT and ROLBK operations
have no effect on files that are not under commitment control.
Note: When multiple devices are attached to an application program, and commit-
ment control is in effect for the files this program uses, the COMMIT or
ROLBK operations continue to work on a file basis and not by device. The
database may be updated with partially completed COMMIT blocks or
changes that other users have completed may be eliminated. It is your
responsibility to ensure this does not happen.
To prepare for using commitment control, you issue the following CL commands:
1. CRTJRNRCV JRNRCV (RECEIVER)
This command creates a journal receiver RECEIVER.
2. CRTJRN JRN(JOURNAL) JRNRCV(RECEIVER)
This command creates a journal JOURNAL and attaches the journal receiver
RECEIVER.
3. STRJRNPF FILE(MASTER TRANS) JRN(JOURNAL)
This command directs journal entries for the file MASTER and the file TRANS
to the journal JOURNAL.
In your program, you specify COMMIT for the file MASTER and the file TRANS:
To operate your program (named REVISE) under commitment control, you issue
the commands:
1. STRCMTCTL LCKLVL(*ALL)
This command starts commitment control with the highest level of locking.
2. CALL REVISE
This command calls the program REVISE.
3. ENDCMTCTL
This command ends commitment control and causes an implicit Roll Back oper-
ation.
The COMMIT keyword has an optional parameter which allows you to specify con-
ditional commitment control. You enter the COMMIT keyword in the keyword
section of the file description specifications for the file(s) in question. The ILE RPG
compiler implicitly defines a one-byte character field with the same name as the
one specified as the parameter. If the parameter is set to '1', the file will run under
commitment control.
The COMMIT keyword parameter must be set prior to opening the file. You can set
the parameter by passing in a value when you call the program or by explicitly
setting it to '1' in the program.
For shared opens, if the file in question is already open, the COMMIT keyword
parameter has no effect, even if it is set to '1'.
C IF COMITFLAG = '1'
C IF *IN90 OR *IN91
C ROLBK
C ELSE
C COMMIT
C ENDIF
C ENDIF
C*
A DDM file is created by a user or program on a local (source) system. This file
(with object type *FILE) identifies a file that is kept on a remote (target) system.
The DDM file provides the information needed for a local system to locate a remote
system and to access the data in the source file. For more information about using
DDM and creating DDM files, refer to the Distributed Data Management manual.
| This may give different results than expected when DDS features are used that
| cause more than one search argument to match a given key in the file. For
| example, if ABSVAL is used on a numeric key, both -1 and 1 would succeed as
| search arguments for a key in the file with a value of 1. Using the hexadecimal
| collating sequence, a search argument of -1 will not succeed for an actual key of 1.
Some of the DDS features that cause the key comparison to differ are:
¹ ALTSEQ specified for the file
¹ ABSVAL, ZONE, UNSIGNED, or DIGIT keywords on key fields
¹ Variable length, Date, Time, or Timestamp key fields
¹ The SRTSEQ for the file is not *HEX
¹ ALWNULL(*USRCTL) was specified on the creation command and a key in the
record or the search argument has a null value (this applies only to externally
described files)
In addition, if the sign of a numeric field is different from the system preferred sign,
the key comparison will also differ.
The first time that the key comparison is not done at the Data Management level on
a pre-V3R1 DDM file during the READE, READPE, or SETLL operation or during
sequential-within-limits processing by a record address file, an informational
message (RNI2002) will be issued.
Note: The performance of I/O operations that have the possibility of not finding a
record (SETLL, CHAIN, SETGT, READE, READPE), will be slower than the
pre-Version 3 Release 1.0 equivalent.
This chapter describes how to access externally attached devices using RPG
device names PRINTER, SEQ, and SPECIAL. For information on display stations
and ICF devices see Chapter 18, “Using WORKSTN Files” on page 331
You use the device files listed in Table 20 to access the associated externally
attached devices:
Table 20. AS/400 Device Files, Related CL commands, and RPG Device Name
Device Associated Externally Attached Device CL com- RPG
File mands Device
Name
Printer Provide access to printer devices and CRTPRTF PRINTER
Files describe the format of printed output. CHGPRTF
OVRPRTF
Tape Files Provide access to data files which are CRTTAPF SEQ
stored on tape devices. CHGTAPF
OVRTAPF
Diskette Provide access to data files which are CRTDKTF DISK
Files stored on diskette devices. CHGDKTF
OVRDKTF
Display Provide access to display devices. CRTDSPF WORKSTN
Files CHGDSPF
OVRDSPF
ICF Files Allow a program on one system to com- CRTICFF WORKSTN
municate with a program on the same CHGICFF
system or another system. OVRICFF
The device file contains the file description, which identifies the device to be used;
it does not contain data.
Printer files allow you to print output files. This chapter provides information on how
to specify and use printer files in ILE RPG programs.
For an externally-described PRINTER file, you can specify the DDS keyword
INDARA. If you try to use this keyword for a program-described PRINTER file, you
get a run-time error.
You can use the CL command CRTPRTF (Create Print File) to create a printer file
(see the CL Reference for further information on the CRTPRTF command); or you
can also use the IBM-supplied file names. See the Data Management manual for
more information on these file names.
The file operation codes that are valid for a PRINTER file are WRITE, OPEN,
CLOSE, and FEOD. For a complete description of these operation codes, see the
ILE RPG for AS/400 Reference.
For both program-described and externally-described files, the line number and
page number are available in the printer feedback section of the INFDS for the file.
To access this information specify the INFDS keyword on the file specification. On
the specification, define the line number in positions 367-368 and define the page
number in positions 369-372 of the data structure. Both the line number and the
page number fields must be defined as binary with no decimal positions. Because
the INFDS will be updated after every output operation to the printer file, these
fields can be used to determine the current line and page number without having
line-count logic in the program.
Note: If you override a printer file to a different device, such as a disk, the printer
feedback section of the INFDS will not be updated, and your line count logic
will not be valid.
The compiler sets on an overflow indicator only the first time an overflow condition
occurs on a page. An overflow condition exists whenever one of the following
occurs:
¹ A line is printed past the overflow line.
¹ The overflow line is passed during a space operation.
¹ The overflow line is passed during a skip operation.
Table 21 on page 319 shows the results of the presence or absence of an over-
flow indicator on the file description and output specifications.
The second line allows printing of headings on the new page only at the beginning
of a new control group (L2 is on). This way, duplicate headings caused by both L2
and OA being on at the same time do not occur. The second line allows headings
to be printed on the first page after the first record is read because the first record
always causes a control break (L2 turns on) if control fields are specified on the
record.
The fetch-overflow routine allows you to alter the basic ILE RPG overflow logic to
prevent printing over the perforation and to let you use as much of the page as
possible. During the regular program cycle, the compiler checks only once, imme-
diately after total output, to see if the overflow indicator is on. When the fetch over-
flow function is specified, the compiler checks overflow on each line for which fetch
overflow is specified.
Figure 154 on page 321 shows the normal processing of overflow printing when
fetch overflow is set on and when it is set off.
Total
0A 0A
Calculations
Print
Total
0A 0A
Output
Print
Overflow
Printing
T = Total
H = Heading Print Print Print Print
D = Detail
E = Exception
Detail
0A 0A
Calculations
Print
Heading
and
Detail 0A 0A
Output Print
Set Off
Overflow
Indicators
Off Off Off Off Off Off Off Off
.A/ When fetch overflow is not specified, the overflow lines print after total
output. No matter when overflow occurs (OA is on), the overflow indi-
cator OA remains on through overflow output time and is set off after
heading and detail output time.
.B/ When fetch overflow is specified, the overflow lines are written before
the output line for which fetch overflow was specified, if the overflow
indicator OA is on. When OA is set on, it remains on until after heading
and detail output time. The overflow lines are not written a second time
During output, the conditioning indicators on an output line are tested to determine
if the line is to be written. If the line is to be written and an F is specified in position
18, the compiler tests to determine if the overflow indicator is on. If the overflow
indicator is on, the overflow routine is fetched and the following operations occur:
1. Only the overflow lines for the file with the fetch specified are checked for
output.
2. All total lines conditioned by the overflow indicator are written.
3. Forms advance to a new page when a skip to a line number less than the line
number the printer is currently on is specified in a line conditioned by an over-
flow indicator.
4. Heading, detail, and exception lines conditioned by the overflow indicator are
written.
5. The line that fetched the overflow routine is written.
6. Any detail and total lines left to be written for that program cycle are written.
You can specify two types of PRTCTL data structures in your source: an
OPM-defined data structure, or an ILE data structure. The default is to use the ILE
data structure layout which is shown in Table 22. To use the OPM-defined data
structure layout, specify PRTCTL(data-structure name:*COMPAT). The OPM
PRTCTL data structure layout is shown in Table 23 on page 324.
The ILE PRTCTL data structure must be defined on the Definition specifications. It
requires a minimum of 15 bytes and must contain at least the following five sub-
fields specified in the following order:
The OPM PRTCTL data structure must be defined on the Definition specifications
and must contain at least the following five subfields specified in the following
order:
The values contained in the first four subfields of the ILE PRTCTL data structure
are the same as those allowed in positions 40 through 51 (space and skip entries)
of the output specifications. If the space/skip entries (positions 40 through 51) of
the output specifications are blank, and if subfields 1 through 4 are also blank, the
default is to space 1 after. If the PRTCTL keyword is specified, it is used only for
the output records that have blanks in positions 40 through 51. You can control the
space and skip value (subfields 1 through 4) for the PRINTER file by changing the
values in these subfields of the PRTCTL data structure while the program is
running.
Subfield 5 contains the current line count value. The compiler does not initialize
subfield 5 until after the first output line is printed. The compiler then changes sub-
field 5 after each output operation to the file.
On the file description specifications, the PRTCTL keyword is specified for the
PRINT file. The name of the associated data structure is LINE.
The LINE data structure is defined on the input specifications as having only those
subfields that are predefined for the PRTCTL data structure. The first four subfields
in positions 1 through 12 are used to supply space and skip information that is
generally specified in positions 40 through 51 of the output specifications. The
PRTCTL keyword allows you to change these specifications within the program.
In this example, the value in the SpAfter subfield is changed to 3 when the value in
the CurLine (current line count value) subfield is equal to 10. (Assume that indi-
cator 01 was set on as a record identifying indicator.)
Read variable-length records from tape just like you would read records from any
sequentially organized file. Ensure the record length specified on the file description
specification accommodates the longest record in the file.
See Chapter 18, “Using WORKSTN Files” on page 331 for a discussion on how to
use WORKSTN files.
The file name of the SEQ file in the file description specifications points to an
AS/400 file. The file description of the AS/400 file specifies the actual I/O device
e.g. tape, printer and diskette.
You can also use the CL override commands, for example OVRDBF, OVRDKTF
and OVRTAPF, to specify the actual I/O device when the program is run.
The following figure shows the operation codes allowed for a SEQ file.
A SEQ device is specified for the PAYOTIME file. When the program is run, you
can use a OS/400 override command to specify the actual device (such as printer,
tape, or diskette) to be associated with the file while the program is running. For
example, diskette can be specified for some program runs while printer can be
specified for others. The file description, pointed to by the file name, can specify the
actual device, in which case an override command need not be used.
ILE RPG calls this user-written routine to open the file, read and write the records,
and close the file. ILE RPG also creates a parameter list for use by the user-written
routine. The parameter list contains:
¹ option code parameter (option)
¹ return status parameter (status)
¹ error-found parameter (error)
¹ record area parameter (area).
This parameter list is accessed by the ILE RPG compiler and by the user-written
routine; it cannot be accessed by the program that contains the SPECIAL file.
You can add additional parameters to the RPG-created parameter list. Specify the
keyword PLIST(parameter list name) on the file description specifications for the
SPECIAL file. See Figure 158 on page 329. Then use the PLIST operation in the
calculation specifications to define the additional parameters.
The user-written routine, specified by the keyword PGMNAME of the file description
specifications for the SPECIAL file, must contain an entry parameter list that
includes both the RPG-created parameters and the user-specified parameters.
Table 25 on page 329 shows the file operation codes that are valid for a SPECIAL
file.
*----------------------------------------------------------------*
* The first 4 parameters are ILE RPG created parameter list. *
* The rest are defined by the programmer-defined PLIST. *
*----------------------------------------------------------------*
C *ENTRY PLIST
C PARM OPTION 1
C PARM STATUS 1
C PARM ERROR 5 0
C PARM AREA 20
C PARM FLD1 1
*----------------------------------------------------------------*
* The user written program will perform the file I/O according *
* to the option passed. *
*----------------------------------------------------------------*
C SELECT
C WHEN OPTION = 'O'
C* perform OPEN operation
C WHEN OPTION = 'W'
C* perform WRITE operation
C WHEN OPTION = 'C'
C* perform CLOSE operation
C ENDSL
C RETURN
The I/O operations for the SPECIAL device are controlled by the user-written
program USERIO. The parameters specified for the programmer-defined
PLIST(SPCL) are added to the end of the RPG-created parameter list for the
SPECIAL device. The programmer-specified parameters can be accessed by the
user ILE RPG program and the user-written routine USERIO; whereas the
RPG-created parameter list can be accessed only by internal ILE RPG logic and
the user-written routine.
Display files are objects of type *FILE with attribute of DSPF on the AS/400
system. You use display files to communicate interactively with users at display ter-
minals. Like database files, display files can be either externally-described or
program-described.
ICF files are objects of type *FILE with attribute of ICFF on the AS/400 system.
You use ICF files to communicate with (send data to and receive data from) other
application programs on remote systems (AS/400 or non-AS/400). An ICF file con-
tains the communication formats required for sending and receiving data between
systems. You can write programs that use ICF files which allow you to communi-
cate with (send data to and receive data from) other application programs on
remote systems.
When a file in an RPG program is identified with the WORKSTN device name then
that program can communicate interactively with a work-station user or use the
Intersystem Communications Function (ICF) to communicate with other programs.
This chapter describes how to use:
¹ Intersystem Communications Function (ICF)
¹ Externally-described WORKSTN files
¹ Program-described WORKSTN files
¹ Multiple-device files.
You code for ICF by using the ICF as a file in your program. The ICF is similar to a
display file and it contains the communications formats required for the sending and
receiving of data between systems.
If you specify the keyword INDARA in the DDS for a WORKSTN file, the RPG
program passes indicators to the WORKSTN file in a separate indicator area, and
not in the input/output buffer.
Figure 160 on page 333 shows an example of the DDS for a display-device file.
Figure 160. Example of the Data Description Specifications for a Display Device File
This display device file contains two record formats: PROMPT and RESPONSE.
.1/ The attributes for the fields in this file are defined in the DSTREF field
reference file.
.2/ The OVERLAY keyword is used so that both record formats can be
used on the same display.
.3/ Function key 3 is associated with indicator 98, which is used by the pro-
grammer to end the program.
.4/ The PUTRETAIN keyword allows the value that is entered in the ITEM
field to be kept in the display. In addition, the ITEM field is defined as an
input field by the I in position 38. ITEM is the only input field in these
record formats. All of the other fields in the record are output fields since
position 38 is blank for each of them.
.5/ The ERRMSG keyword identifies the error message that is displayed if
indicator 61 is set on in the program that uses this record format.
.6/ The LOCK keyword prevents the work-station user from using the key-
board when the RESPONSE record format is initially-displayed.
.7/ The constants such as ‘Description’, ‘Price’, and ‘Warehouse Location’
describe the fields that are written out by the program.
.8/ The line and position entries identify where the fields or constants are
written on the display.
The function key indicators relate to the function keys as follows: function key indi-
cator KA corresponds to function key 1, KB to function key 2 ... KX to function key
23, and KY to function key 24.
Function keys are specified in the DDS with the CFxx (command function) or CAxx
(command attention) keyword. For example, the keyword CF01 allows function key
1 to be used. When you press function key 1, function key indicator KA is set on in
the RPG program. If you specify the function key as CF01 (99), both function key
indicator KA and indicator 99 are set on in the RPG program. If the work-station
user presses a function key that is not specified in the DDS, the OS/400 system
informs the user that an incorrect key was pressed.
If the work-station user presses a specified function key, the associated function
key indicator in the RPG program is set on when fields are extracted from the
record (move fields logic) and all other function key indicators are set off. If a func-
tion key is not pressed, all function key indicators are set off at move fields time.
The function key indicators are set off if the user presses the Enter key.
Command keys are processed by an RPG program whenever the compiler proc-
esses a READ or an EXFMT operation on a record format for which the appropriate
keywords are specified in the DDS. When the command keys are in effect and a
command key is pressed, the OS/400 system returns control to the RPG program.
If a response indicator is specified in the DDS for the command selected, that indi-
cator is set on and all other response indicators that are in effect for the record
format and the file are set off.
If a response indicator is not specified in the DDS for a command key, the following
happens:
¹ For the Print key without *PGM specified, the print function is processed.
¹ For the Roll Up and Roll Down keys used with subfiles, the displayed subfile
rolls up or down, within the subfile. If you try to roll beyond the start or end of a
subfile, you get a run-time error.
¹ For the Print Key specified with *PGM, Roll Up and Roll Down keys used
without subfiles, and for the Clear, Help, and Home keys, one of the *STATUS
values 1121-1126 is set, respectively, and processing continues.
When the program requests an output operation, it passes the output record to the
OS/400 system. The OS/400 system provides the necessary device-control infor-
mation to display the record. It also adds any constant information specified for the
record format when the record is displayed.
When a record is passed to a program, the fields are arranged in the order in which
they are specified in the DDS. The order in which the fields are displayed is based
on the display positions (line numbers and position) assigned to the fields in the
DDS. The order in which the fields are specified in the DDS and the order in which
they appear on the screen need not be the same.
For more information on processing WORKSTN files, see “Valid WORKSTN File
Operations” on page 341.
Using Subfiles
Subfiles can be specified in the DDS for a display-device file to allow you to handle
multiple records of the same type on the display. (See Figure 161 on page 336.) A
subfile is a group of records that is read from or written to a display-device file. For
example, a program reads records from a database file and creates a subfile of
output records. When the entire subfile has been written, the program sends the
entire subfile to the display device in one write operation. The work-station user can
change data or enter additional data in the subfile. The program then reads the
entire subfile from the display device into the program and processes each record
in the subfile individually.
Records that you want to be included in a subfile are specified in the DDS for the
file. The number of records that can be included in a subfile must also be specified
in the DDS. One file can contain more than one subfile, and up to 12 subfiles can
be active concurrently. Two subfiles can be displayed at the same time.
The DDS for a subfile consists of two record formats: a subfile-record format and a
subfile control-record format. The subfile-record format contains the field information
that is transferred to or from the display file under control of the subfile control-
record format. The subfile control-record format causes the physical read, write, or
control operations of a subfile to take place. Figure 162 on page 337 shows an
example of the DDS for a subfile-record format, and Figure 163 on page 338
shows an example of the DDS for a subfile control-record format.
For a description of how to use subfile keywords, see the DDS Reference.
To use a subfile for a display device file in an RPG program, you must specify the
SFILE keyword on a file description specification for the WORKSTN file. The format
of the SFILE keyword is SFILE(record format name:RECNO field name). The
WORKSTN file must be an externally-described file (E in position 22).
You must specify for the SFILE keyword the name of the subfile record format (not
the control-record format) and the name of the field that contains the relative record
number to be used in processing the subfile.
Use the CHAIN, READC, UPDATE, or WRITE operation codes with the subfile
record format to transfer data between the program and the subfile. Use the READ,
WRITE, or EXFMT operation codes with the subfile control-record format to transfer
data between the program and the display device or to process subfile control oper-
ations.
If a WORKSTN file has an associated subfile, all implicit input operations and
explicit calculation operations that refer to the file name are processed against the
main WORKSTN file. Any operations that specify a record format name that is not
designated as a subfile are processed on the main WORKSTN file.
If you press a specified function key during a read of a non-subfile record, subse-
quent reads of a subfile record will cause the corresponding function key indicator
to be set on again, even if the function key indicator has been set off between the
reads. This will continue until a non-subfile record is read from the WORKSTN file.
The data description specifications (DDS) for a subfile record format describe the
records in the subfile:
.1/ The attributes for the fields in the record format are contained in the field
reference file DSTREF as specified by the REF keyword.
.2/ The SFL keyword identifies the record format as a subfile.
.3/ The line and position entries define the location of the fields on the
display.
Use of Subfiles
Some typical ways you can make use of subfiles include:
¹ Display only. The work-station user reviews the display.
¹ Display with selection. The user requests more information about one of the
items on the display.
¹ Modification. The user changes one or more of the records.
¹ Input only, with no validity checking. A subfile is used for a data entry function.
¹ Input only, with validity checking. A subfile is used for a data entry function, but
the records are checked.
¹ Combination of tasks. A subfile can be used as a display with modification, plus
the input of new records.
The subfile control-record format defines the attributes of the subfile, the search
input field, constants, and function keys. The keywords you can use indicate the
following:
¹ SFLCTL names the associated subfile (SUBFIL).
¹ SFLCLR indicates when the subfile should be cleared (when indicator 70 is off).
¹ SFLDSPCTL indicates when to display the subfile control record (when indi-
cator 70 is on).
¹ SFLDSP indicates when to display the subfile (when indicator 71 is on).
¹ SFLSIZ indicates the total number of records to be included in the subfile (15).
¹ SFLPAG indicates the total number of records in a page (15).
¹ ROLLUP indicates that indicator 97 is set on in the program when the user
presses the Roll Up key.
¹ HELP allows the user to press the Help key for a displayed message that
describes the valid function keys.
¹ PUTRETAIN allows the value that is entered in the SRHCOD field to be kept in
the display.
In addition to the control information, the subfile control-record format also defines
the constants to be used as column headings for the subfile record format.
If a format name is used, input and output specifications must be used to describe
the input and output records.
Output Specifications
On the output specifications, you must specify the WORKSTN file name in positions
7 through 16. The format name, which is the name of the DDS record format, is
specified as a literal or named constant in positions 53 through 80 on the suc-
ceeding field description line. K1 through K10 must be specified (right-adjusted) in
positions 47 through 51 on the line containing the format name. The K identifies the
entry as a length rather than an end position, and the number indicates the length
of the format name. For example, if the format name is CUSPMT, the entry in posi-
tions 47 through 51 is K6. (Leading zeros following the K are allowed.) The format
name cannot be conditioned (indicators in positions 21 through 29 are not valid).
Output fields must be located in the output record in the same order as defined in
the DDS; however, the field names do not have to be the same. The end position
entries for the fields refer to the end position in the output record passed from the
RPG program to data management, and not to the location of the fields on the
screen.
A record identifying indicator should be assigned to each record in the file to iden-
tify the record that has been read from the WORKSTN file. A hidden field with a
default value can be specified in the DDS for the record identification code.
Calculation Specifications
The operation code READ is valid for a program-described WORKSTN file that is
defined as a combined, full-procedural file. See Table 26 on page 341. The file
name must be specified in factor 2 for this operation. A format must exist at the
device before any input operations can take place. This requirement can be satis-
fied on a display device by conditioning an output record with 1P or by writing the
first format to the device in another program (for example, in the CL program). The
EXFMT operation is not valid for a program-described WORKSTN file. You can
also use the EXCEPT operation to write to a WORKSTN file.
Additional Considerations
When using a format name with a program-described WORKSTN file, you must
also consider the following:
¹ The name specified in positions 53 through 80 of the output specifications is
assumed to be the name of a record format in the DDS that was used to create
the file.
¹ If a Kn specification is present for an output record, it must also be used for
any other output records for that file. If a Kn specification is not used for all
output records to a file, a run-time error will occur.
When you create the display file by using the Create Display File command, the file
has the following attributes:
¹ A variable record length can be specified; therefore, the actual record length
must be specified in the using program. (The maximum record length allowed is
the screen size minus one.)
Input File
For an input file, the input record, which is treated by the OS/400 device support as
a single input field, is initialized to blanks when the file is opened. The cursor is
positioned at the beginning of the field, which is position 2 on the display.
Output File
For an output file, the OS/400 device support treats the output record as a string of
characters to be sent to the display. Each output record is written as the next
sequential record in the file; that is, each record displayed overlays the previous
record displayed.
Combined File
For a combined file, the record, which is treated by the OS/400 device support as a
single field, appears on the screen and is both the output record and the input
record. Device support initializes the input record to blanks, and the cursor is
placed in position 2.
The following further explains the EXFMT, READ, and WRITE operation codes
when used to process a WORKSTN file.
READ Operation
The READ operation is valid for a full-procedural combined file or a full-procedural
input file that uses externally-described data or program-described data. The READ
operation retrieves a record from the display. However, a format must exist at the
device before any input operations can occur. This requirement can be satisfied on
a display device by conditioning an output record with the 1P indicator, by writing
the first format to the device from another program, or, if the read is by record-
format name, by using the keyword INZRCD on the record description in the DDS.
WRITE Operation
The WRITE operation writes a new record to a display and is valid for a combined
file or an output file. Output specifications and the EXCEPT operation can also be
used to write to a WORKSTN file. See the ILE RPG for AS/400 Referencefor a
complete description of each of these operation codes.
Multiple-Device Files
Any RPG WORKSTN file with at least one of the keywords DEVID, SAVEIND,
MAXDEV(*FILE) or SAVEDS specified on the file description specification is a
multiple-device file. Through a multiple-device file, your program may access more
than one device.
The RPG program accesses devices through program devices, which are symbolic
mechanisms for directing operations to an actual device. When you create a file
(using the DDS and commands such as the create file commands), you consider
such things as which device is associated with a program device, whether or not a
file has a requesting program device, which record formats will be used to invite
devices to respond to a READ-by-file-name operation, and how long this READ
operation will wait for a response. For detailed information on the options and
requirements for creating a multiple-device file, see the chapter on display files in
Data Management manual, and information on ICF files in ICF Programming
manual, and the manuals you are referred to in these two publications.
With multiple-device files, you make particular use of the following operation codes:
¹ In addition to opening a file, the OPEN operation implicitly acquires the device
you specify when you create the file.
¹ The ACQ (acquire) operation acquires any other devices for a multiple-device
file.
¹ The REL (release) operation releases a device from the file.
¹ The WRITE operation, when used with the DDS keyword INVITE, invites a
program device to respond to subsequent read-from-invited- program-devices
See the ILE RPG for AS/400 Reference for details of the RPG operation codes.
On the file description specification you can specify several keywords to control the
processing of multiple-device files.
¹ The MAXDEV keyword indicates whether it is a single or multiple device file.
Specify MAXDEV(*FILE) to process a multiple device file with the maximum
number of devices taken from the definition of the file being processed.
Specify MAXDEV(*ONLY) to process only one device.
¹ The DEVID keyword allows you to specify the name of a program device to
which input and output operations are directed.
When a read-from-one-program-device or WRITE operation is issued, the
device used for the operation is the device specified as the parameter to the
DEVID keyword. This field is initialized to blanks and is updated with the name
of the device from which the last successful input operation occurred. It can
also be set explicitly by moving a value to it. The ACQ operation code does not
affect the value of this field. If the DEVID keyword is not specified, the input
operation is performed against the device from which the last successful input
operation occurred. A blank device name is used if a read operation has not
yet been performed successfully from a device.
When a read-from-one-program device or WRITE operation is issued with a
blank device name, the RPG compiler implicitly uses the device name of the
requestor device for the program. If you call an RPG program interactively and
acquire an ICF device against which you want to perform one of these oper-
ations, you must explicitly move the device name of the ICF device into the
field name specified with the DEVID keyword prior to performing the operation.
If this is not done, the device name used will either be blank (in which case the
interactive requestor device name is used), or the device name used is the one
from the last successful input operation. Once you have performed an I/O oper-
The application program presented in this chapter consists of four modules. Each
module illustrates a common use for WORKSTN files. The first module (CUSMAIN)
provides the main menu for the program. Based on the user's selection, it calls the
procedure in the appropriate module which provides the function requested.
Each module uses a WORKSTN file to prompt the user for input and display infor-
mation on the screen. Each module, except for the main module CUSMAIN, also
uses a logical file which presents a view of the master database file. This view
consists of only the fields of the master file which the module requires for its proc-
essing.
Note: Each module, except CUSMAIN, can be compiled as a free standing
program, that is, they can each be used as an independent program.
Figure 164. DDS for master database file CUSMST (physical file)
The HDRSCN record format contains the constant 'CUSTOMER MAIN INQUIRY',
which identifies the display. It also contains the keywords TIME and DATE, which
will display the current time and date on the screen. The CA keywords define the
function keys that can be used and associate the function keys with indicators in
the RPG program.
In addition to describing the constants, fields, line numbers, and horizontal positions
for the screen, the record formats also define the display attributes for these
entries.
Note: Normally, the field attributes are defined in a field-reference file rather than
in the DDS for a file. The attributes are shown on the DDS so you can see
what they are.
FMAINMENU CF E WORKSTN
C EXFMT HDRSCN
C*
C DOW NOT *IN03
C SELECT
C WHEN *IN05
C CALLB 'CUSMNT'
C WHEN *IN06
C CALLB 'SCHZIP'
C WHEN *IN07
C CALLB 'SCHNAM'
C ENDSL
C EXFMT HDRSCN
C ENDDO
C*
C SETON LR
This module illustrates the use of the CALLB opcode. The appropriate RPG module
(CUSMNT, SCHZIP, or SCHNAM) is called by CUSMAIN depending on the user's
menu item selection.
Note: The *FIRST option specifies that the first module in the list, CUSMAIN,
is selected as the program entry procedure.
3. Call the program by entering:
CALL MYPROG
F3 End Job
F5 Maintain Customer File
F6 Search Customer by Zip Code
F7 Search Customer by Name
Figure 167. Customer Main Inquiry prompt screen
File Maintenance
The following illustrates a maintenance program using the WORKSTN file. It allows
you to add, delete, update, and display records of the master customer file.
A*****************************************************************
A* FILE NAME: CUSMSTL1 *
A* RELATED PGMS: CUSMNT *
A* RELATED FILES: CUSMST (PHYSICAL FILE) *
A* DESCRIPTION: THIS IS LOGICAL FILE CUSMSTL1. *
A* IT CONTAINS ONE RECORD FORMAT CALLED CMLREC1. *
A* LOGICAL VIEW OF CUSTOMER MASTER FILE (CUSMST) *
A* BY CUSTOMER NUMBER (CUST) *
A*****************************************************************
A R CMLREC1 PFILE(CUSMST)
A CUST
A NAME
A ADDR1
A ADDR2
A CITY
A STATE
A ZIP
A K CUST
The DDS for the database file used by this program describe one record format:
CMLREC1. Each field in the record format is described, and the CUST field is iden-
tified as the key field for the record format.
A*****************************************************************
A* FILE NAME: MNTMENU *
A* RELATED PGMS: CUSMNT *
A* RELATED FILES: CUSMSTL1 (LOGICAL FILE) *
A* DESCRIPTION: THIS IS THE DISPLAY FILE MNTMENU. IT HAS 3 *
A* RECORD FORMATS. *
A*****************************************************************
A REF(CUSMSTL1)
A CHGINPDFT(CS)
A PRINT(QSYSPRT)
A INDARA
A R HDRSCN
A TEXT('PROMPT FOR CUST NUMBER')
A CA03(03 'END MAINTENANCE')
A CA05(05 'ADD MODE')
A CA06(06 'UPDATE MODE')
A CA07(07 'DELETE MODE')
A CA08(08 'DISPLAY MODE')
A MODE 8A O 1 4DSPATR(HI)
A 1 13'MODE'
A DSPATR(HI)
A 2 4TIME
A DSPATR(HI)
A 2 28'CUSTOMER FILE MAINTENANCE'
A DSPATR(HI RI)
A 2 70DATE
A EDTCDE(Y)
A DSPATR(HI)
A CUST R Y I 10 25DSPATR(CS)
A CHECK(RZ)
A 51 ERRMSG('CUSTOMER ALREADY ON +
A FILE' 51)
A 52 ERRMSG('CUSTOMER NOT ON FILE' +
A 52)
A 10 33'<--Enter Customer Number'
A DSPATR(HI)
A 23 4'F3 End Job'
A 23 21'F5 Add'
A 23 34'F6 Update'
A 23 50'F7 Delete'
A 23 66'F8 Display'
A R CSTINQ
A TEXT('DISPLAY CUST INFO')
A CA12(12 'PREVIOUS SCREEN')
Figure 169 (Part 1 of 2). DDS for display device file MNTMENU
Figure 169 (Part 2 of 2). DDS for display device file MNTMENU
The DDS for the MNTMENU display device file contains three record formats:
HDRSCN, CSTINQ, and CSTBLD. The HDRSCN record prompts for the customer
number and the mode of processing. The CSTINQ record is used for the Update,
The HDRSCN record format contains the constant 'Customer File Maintenance'.
The ERRMSG keyword defines the messages to be displayed if an error occurs.
The CA keywords define the function keys that can be used and associate the
function keys with indicators in the RPG program.
*****************************************************************
* PROGRAM NAME: CUSMNT *
* RELATED FILES: CUSMSTL1 (LF) *
* MNTMENU (DSPF) *
* DESCRIPTION: THIS PROGRAM SHOWS A CUSTOMER MASTER *
* MAINTENANCE PROGRAM USING A WORKSTN FILE. *
* THIS PROGRAM ALLOWS THE USER TO ADD, UPDATE, *
* DELETE AND DISPLAY CUSTOMER RECORDS. *
* PF3 IS USED TO QUIT THE PROGRAM. *
*****************************************************************
FCUSMSTL1 UF A E K DISK
FMNTMENU CF E WORKSTN
C CSTKEY KLIST
C KFLD CUST
********************************************************************
* MAINLINE *
********************************************************************
C ADDSUB BEGSR
C CSTKEY CHAIN CMLREC1 50
C IF NOT *IN50
C MOVE *ON *IN51
C ELSE
C MOVE *OFF *IN51
C MOVE *BLANK NAME
C MOVE *BLANK ADDR1
C MOVE *BLANK ADDR2
C MOVE *BLANK CITY
C MOVE *BLANK STATE
C Z-ADD *ZERO ZIP
C EXFMT CSTBLD
C IF NOT *IN12
C WRITE CMLREC1
C ENDIF
C ENDIF
C ENDSR
********************************************************************
* SUBROUTINE - UPDSUB *
* PURPOSE - UPDATE CUSTOMER MASTER RECORD *
********************************************************************
C UPDSUB BEGSR
C MOVE *OFF *IN04
C CSTKEY CHAIN CMLREC1 52
C IF NOT *IN52
C EXFMT CSTINQ
C IF NOT *IN12
C UPDATE CUSMSTL1
C ELSE
C UNLOCK CUSMSTL1
C ENDIF
C ENDIF
C ENDSR
C DELSUB BEGSR
C MOVE *ON *IN04
C CSTKEY CHAIN CMLREC1 52
C IF NOT *IN52
C EXFMT CSTINQ
C IF NOT *IN12
C DELETE CMLREC1
C ELSE
C UNLOCK CUSMSTL1
C ENDIF
C ENDIF
C ENDSR
********************************************************************
* SUBROUTINE - INQSUB *
* PURPOSE - DISPLAY CUSTOMER MASTER RECORD *
********************************************************************
C INQSUB BEGSR
C MOVE *ON *IN04
C CSTKEY CHAIN CMLREC1 52
C IF NOT *IN52
C EXFMT CSTINQ
C UNLOCK CUSMSTL1
C ENDIF
C ENDSR
********************************************************************
* SUBROUTINE - SETMOD *
* PURPOSE - SET MAINTENANCE MODE *
********************************************************************
C SETMOD BEGSR
C SELECT
C WHEN *IN05
C MOVE 'ADD ' MODE
C WHEN *IN06
C MOVE 'UPDATE ' MODE
C WHEN *IN07
C MOVE 'DELETE ' MODE
C WHEN *IN08
C MOVE 'DISPLAY ' MODE
C ENDSL
C*
C MOVE MODE MODE1
C ENDSR
This program maintains a customer master file for additions, changes, and
deletions. The program can also be used for inquiry.
The program first sets the default (display) mode of processing and displays the
customer maintenance prompt screen. The workstation user can press F3, which
turns on indicator 03, to request end of job. Otherwise, to work with customer infor-
mation, the user enters a customer number and presses Enter. The user can
To add a new record to the file, the program uses the customer number as the
search argument to chain to the master file. If the record does not exist in the file,
the program displays the CSTBLD screen to allow the user to enter a new cus-
tomer record. If the record is already in the file, an error message is displayed. The
user can press F12, which sets on indicator 12, to cancel the add operation and
release the record. Otherwise, to proceed with the add operation, the user enters
information for the new customer record in the input fields and writes the new
record to the master file.
To update, delete, or display an existing record, the program uses the customer
number as the search argument to chain to the master file. If a record for that cus-
tomer exists in the file, the program displays the customer file inquiry screen
CSTINQ. If the record is not in the file, an error message is displayed. If the mode
of processing is display or delete, the input fields are protected from modification.
Otherwise, to proceed with the customer record, the user can enter new information
in the customer record input fields. The user can press F12, which sets on indicator
12, to cancel the update or delete operation, and release the record. Display mode
automatically releases the record when Enter is pressed.
In Figure 171, the workstation user responds to the prompt by entering customer
number 00007 to display the customer record.
DISPLAY MODE
22:30:21 CUSTOMER FILE MAINTENANCE 9/30/94
Because the customer record for customer number 00007 exists in the Master File,
the data is displayed as show in Figure 172 on page 356.
Customer: 00007
Mikhail Yuri
1001 Bay Street
Suite 1702
Livonia
MI 11201
The workstation user responds to the add prompt by entering a new customer
number as shown in Figure 173.
ADD MODE
22:31:43 CUSTOMER FILE MAINTENANCE 9/30/94
In Figure 174 on page 357 a new customer is added to the Customer Master File.
Customer: 00012
The workstation user responds to the delete prompt by entering a customer number
as shown in Figure 175.
DELETE MODE
22:32:55 CUSTOMER FILE MAINTENANCE 9/30/94
A*****************************************************************
A* FILE NAME: CUSMSTL2 *
A* RELATED PGMS: SCHZIP *
A* RELATED FILES: CUSMST (PHYSICAL FILE) *
A* DESCRIPTION: THIS IS LOGICAL FILE CUSMSTL2. *
A* IT CONTAINS ONE RECORD FORMAT CALLED CMLREC2. *
A* LOGICAL VIEW OF CUSTOMER MASTER FILE (CUSMST) *
A* BY CUSTOMER ZIP CODE (ZIP) *
A*****************************************************************
A R CMLREC2 PFILE(CUSMST)
A ZIP
A NAME
A ARBAL
A K ZIP
The DDS for the database file used by this program describe one record format:
CMLREC2. The logical file CUSMSTL2 keyed by zip code is based on the physical
file CUSMST, as indicated by the PFILE keyword. The record format created by the
logical file will include only those fields specified in the logical file DDS. All other
fields will be excluded.
A*****************************************************************
A* FILE NAME: SZIPMENU *
A* RELATED PGMS: SCHZIP *
A* RELATED FILES: CUSMSTL2 (LOGICAL FILE) *
A* DESCRIPTION: THIS IS THE DISPLAY FILE SZIPMENU. IT HAS 6 *
A* RECORD FORMATS. *
A*****************************************************************
A REF(CUSMSTL2)
A CHGINPDFT(CS)
A PRINT(QSYSPRT)
A INDARA
A CA03(03 'END OF JOB')
A R HEAD
A OVERLAY
A 2 4TIME
A DSPATR(HI)
A 2 28'CUSTOMER SEARCH BY ZIP'
A DSPATR(HI RI)
A 2 70DATE
A EDTCDE(Y)
A DSPATR(HI)
A R FOOT1
A 23 6'ENTER - Continue'
A DSPATR(HI)
A 23 29'F3 - End Job'
A DSPATR(HI)
A R FOOT2
A 23 6'ENTER - Continue'
A DSPATR(HI)
A 23 29'F3 - End Job'
A DSPATR(HI)
A 23 47'F4 - RESTART ZIP CODE'
A DSPATR(HI)
A R PROMPT
A OVERLAY
A 4 4'Enter Zip Code'
A DSPATR(HI)
A ZIP R Y I 4 19DSPATR(CS)
A CHECK(RZ)
A 61 ERRMSG('ZIP CODE NOT FOUND' +
A 61)
A R SUBFILE SFL
A NAME R 9 4
A ARBAL R 9 27EDTCDE(J)
A R SUBCTL SFLCTL(SUBFILE)
Figure 178 (Part 1 of 2). DDS for display device file SZIPMENU
Figure 178 (Part 2 of 2). DDS for display device file SZIPMENU
The DDS for the SZIPMENU display device file contains six record formats: HEAD,
FOOT1, FOOT2, PROMPT, SUBFILE, and SUBCTL.
The PROMPT record format requests the user to enter a zip code. If the zip code is
not found in the file, an error message is displayed. The user can press F3, which
sets on indicator 03, to end the program.
The SUBFILE record format must be defined immediately preceding the subfile-
control record format SUBCTL. The subfile record format, which is defined with the
keyword SFL, describes each field in the record, and specifies the location where
the first record is to appear on the display (here, on line 9).
*****************************************************************
* PROGRAM NAME: SCHZIP *
* RELATED FILES: CUSMSTL2 (LOGICAL FILE) *
* SZIPMENU (WORKSTN FILE) *
* DESCRIPTION: THIS PROGRAM SHOWS A CUSTOMER MASTER SEARCH *
* PROGRAM USING WORKSTN SUBFILE PROCESSING. *
* THIS PROGRAM PROMPTS THE USER FOR THE ZIP CODE*
* AND DISPLAYS THE CUSTOMER MASTER RECORD BY *
* ZIP CODE. *
* ROLL UP KEY CAN BE USED TO LOOK AT ANOTHER *
* PAGE. PF3 IS USED TO QUIT THE PROGRAM. *
*****************************************************************
FCUSMSTL2 IF E K DISK
FSZIPMENU CF E WORKSTN SFILE(SUBFILE:RECNUM)
C CSTKEY KLIST
C KFLD ZIP
********************************************************************
* MAINLINE *
********************************************************************
C WRITE FOOT1
C WRITE HEAD
C EXFMT PROMPT
C*
C DOW NOT *IN03
C MOVE *OFF *IN61
C CSTKEY SETLL CMLREC2 20
C IF NOT *IN20
C MOVE *ON *IN61
C ELSE
C EXSR SFLPRC
C END
C IF (NOT *IN03) AND (NOT *IN04)
C IF NOT *IN61
C WRITE FOOT1
C WRITE HEAD
C ENDIF
C EXFMT PROMPT
C ENDIF
C ENDDO
C*
C SETON LR
C SFLPRC BEGSR
C NXTPAG TAG
C EXSR SFLCLR
C EXSR SFLFIL
C SAMPAG TAG
C WRITE FOOT2
C WRITE HEAD
C EXFMT SUBCTL
C IF *IN95
C IF NOT *IN71
C GOTO NXTPAG
C ELSE
C GOTO SAMPAG
C ENDIF
C ENDIF
C ENDSR
********************************************************************
* SUBROUTINE - SFLFIL *
* PURPOSE - FILL SUBFILE *
********************************************************************
C SFLFIL BEGSR
C DOW NOT *IN21
C ZIP READE CMLREC2 71
C IF *IN71
C MOVE *ON *IN21
C ELSE
C ADD 1 RECNUM
C WRITE SUBFILE 21
C ENDIF
C ENDDO
C ENDSR
********************************************************************
* SUBROUTINE - SFLCLR *
* PURPOSE - CLEAR SUBFILE RECORDS *
********************************************************************
C SFLCLR BEGSR
C MOVE *ON *IN55
C WRITE SUBCTL
C MOVE *OFF *IN55
C MOVE *OFF *IN21
C Z-ADD *ZERO RECNUM 5 0
C ENDSR
The file description specifications identify the disk file to be searched and the
display device file to be used (SZIPMENU). The SFILE keyword for the WORKSTN
file identifies the record format (SUBFILE) that is to be used as a subfile. The
relative-record-number field (RECNUM) specified controls which record within the
subfile is being accessed.
The SFLPRC subroutine handles the processing for the subfile: clearing, filling, and
displaying. The subfile is prepared for additional requests in subroutine SFLCLR. If
indicator 55 is on, no action occurs on the display, but the main storage area for
the subfile records is cleared. The SFLFIL routine fills the subfile with records. A
record is read from the CUSMSTL2 file. If the zip code is the same, the record
count (RECNUM) is incremented and the record is written to the subfile. This sub-
routine is repeated until either the subfile is full (indicator 21 on the WRITE opera-
tion) or end of file occurs on the CUSMSTL2 file (indicator 71 on the READE
operation). When the subfile is full or end of file occurs, the subfile is written to the
display by the EXFMT operation by the subfile-control record control format. The
user reviews the display and decides whether:
¹ To end the program by pressing F3.
¹ To restart the zip code by pressing F4. The PROMPT record format is not dis-
played, and the subfile is displayed starting over with the same zip code.
¹ To fill another page by pressing ROLL UP. If end of file has occurred on the
CUSMSTL2 file, the current page is re-displayed; otherwise, the subfile is
cleared and the next page is displayed.
¹ To continue with another zip code by pressing ENTER. The PROMPT record
format is displayed. The user can enter a zip code or end the program.
In Figure 180, the user enters a zip code in response to the prompt.
22:34:38 CUSTOMER SEARCH BY ZIP 9/30/94
The subfile is written to the screen as shown in Figure 181 on page 364.
A*****************************************************************
A* FILE NAME: CUSMSTL3 *
A* RELATED PGMS: SCHNAM *
A* RELATED FILES: CUSMST *
A* DESCRIPTION: THIS IS THE LOGICAL FILE CUSMSTL3. IT HAS *
A* ONE RECORD FORMAT CALLED CUSREC. *
A* LOGICAL VIEW OF CUSTOMER MASTER FILE (CUSMST) *
A* BY NAME (NAME) *
A*****************************************************************
A R CUSREC PFILE(CUSMST)
A K NAME
A*
A*****************************************************************
A* NOTE: SINCE THE RECORD FORMAT OF THE PHYSICAL FILE (CUSMST) *
A* HAS THE SAME RECORD-FORMAT-NAME, NO LISTING OF FIELDS *
A* IS REQUIRED IN THIS DDS FILE. *
A*****************************************************************
The DDS for the database file used in this program defines one record format
named CUSREC and identifies the NAME field as the key fields.
A 55 SFLCLR
A N55 SFLDSPCTL
A N55 SFLDSP
A ROLLUP(95 'ROLL UP')
A OVERLAY
A CA04(04 'RESTART SEARCH NAME')
A 5 4'Search Name'
A SRCNAM R O 5 17REFFLD(NAME CUSMSTL3)
A DSPATR(HI)
A 7 6'Select'
A DSPATR(HI)
A 8 6' "X" Customer Name '
A DSPATR(HI)
A DSPATR(UL)
A 8 42' Number Zip Code '
A DSPATR(HI)
A DSPATR(UL)
A R CUSDSP
A OVERLAY
A CA04(04 'RESTART ZIP CDE')
A 6 25'Customer'
A CUST 5S 0O 6 35DSPATR(HI)
A 8 25'Name'
A NAME 20A O 8 35DSPATR(HI)
A 10 25'Address'
A ADDR1 20A O 10 35DSPATR(HI)
A ADDR2 20A O 11 35DSPATR(HI)
A 13 25'City'
A CITY 20A O 13 35DSPATR(HI)
A 15 25'State'
A STATE 2A O 15 35DSPATR(HI)
A 15 41'Zip Code'
A ZIP 5S 0O 15 50DSPATR(HI)
A 17 25'A/R Balance'
A ARBAL 10Y 2O 17 42DSPATR(HI)
A EDTCDE(J)
The DDS for the SNAMMENU display device file contains seven record formats:
HEAD, FOOT1, FOOT2, PROMPT, SUBFILE, SUBCTL, and CUSDSP.
The PROMPT record format requests the user to enter a zip code and search
name. If no entry is made, the display starts at the beginning of the file. The user
can press F3, which sets on indicator 03, to end the program.
The SUBFILE record format must be defined immediately preceding the subfile-
control record format SUBCTL. The subfile-record format defined with the keyword
SFL, describes each field in the record, and specifies the location where the first
record is to appear on the display (here, on line 9).
The subfile-control record format SUBCTL contains the following unique keywords:
¹ SFLCTL identifies this format as the control record format and names the asso-
ciated subfile record format.
¹ SFLCLR describes when the subfile is to be cleared of existing records (when
indicator 55 is on). This keyword is needed for additional displays.
The CUSDSP record format displays information for the selected customers.
*****************************************************************
* PROGRAM NAME: SCHNAM *
* RELATED FILES: CUSMSTL3 (LOGICAL FILE) *
* SNAMMENU (WORKSTN FILE) *
* DESCRIPTION: THIS PROGRAM SHOWS A CUSTOMER MASTER SEARCH *
* PROGRAM USING WORKSTN SUBFILE PROCESSING. *
* THIS PROGRAM PROMPTS THE USER FOR THE CUSTOMER*
* NAME AND USES IT TO POSITION THE CUSMSTL3 *
* FILE BY THE SETLL OPERATION. THEN IT DISPLAYS *
* THE RECORDS USING SUBFILES. *
* TO FILL ANOTHER PAGE, PRESS THE ROLL UP KEY. *
* TO DISPLAY CUSTOMER DETAIL, ENTER 'X' BESIDE *
* THAT CUSTOMER AND PRESS ENTER. *
* TO QUIT THE PROGRAM, PRESS PF3. *
*****************************************************************
FCUSMSTL3 IF E K DISK
FSNAMMENU CF E WORKSTN SFILE(SUBFILE:RECNUM)
C CSTKEY KLIST
C KFLD SRCNAM
C ZIPKEY KLIST
C KFLD NAME
C WRITE FOOT1
C WRITE HEAD
C EXFMT PROMPT
C DOW NOT *IN03
C CSTKEY SETLL CUSREC
C EXSR SFLPRC
C EXSR SFLCHG
C IF (NOT *IN03) AND (NOT *IN04)
C WRITE FOOT1
C WRITE HEAD
C EXFMT PROMPT
C ENDIF
C ENDDO
C*
C SETON LR
********************************************************************
* SUBROUTINE - SFLPRC *
* PURPOSE - PROCESS SUBFILE AND DISPLAY *
********************************************************************
C SFLPRC BEGSR
C NXTPAG TAG
C EXSR SFLCLR
C EXSR SFLFIL
C SAMPAG TAG
C WRITE FOOT2
C WRITE HEAD
C EXFMT SUBCTL
C IF *IN95
C IF NOT *IN71
C GOTO NXTPAG
C ELSE
C GOTO SAMPAG
C ENDIF
C ENDIF
C ENDSR
********************************************************************
* SUBROUTINE - SFLFIL *
* PURPOSE - FILL SUBFILE *
********************************************************************
C SFLFIL BEGSR
C DOW NOT *IN21
C READ CUSREC 71
C IF *IN71
C MOVE *ON *IN21
C ELSE
C ADD 1 RECNUM
C MOVE *BLANK SEL
C WRITE SUBFILE 21
C ENDIF
C ENDDO
C ENDSR
C SFLCLR BEGSR
C MOVE *ON *IN55
C WRITE SUBCTL
C MOVE *OFF *IN55
C MOVE *OFF *IN21
C Z-ADD *ZERO RECNUM 5 0
C ENDSR
********************************************************************
* SUBROUTINE - SFLCHG *
* PURPOSE - CUSTOMER RECORD SELECTED *
********************************************************************
C SFLCHG BEGSR
C READC SUBFILE 98
C IF NOT *IN98
C ZIPKEY CHAIN CUSREC 71
C EXFMT CUSDSP
C ENDIF
C ENDSR
The file description specifications identify the disk file to be searched and the
display device file to be used (SNAMMENU). The SFILE keyword for the
WORKSTN file identifies the record format (SUBFILE) to be used as a subfile. The
relative-record-number field (RECNUM) specifies which record within the subfile is
being accessed.
The program displays the PROMPT record format and waits for the workstation
user's response. F3 sets on indicator 03, which controls the end of the program.
The name (NAME) is used as the key to position the CUSMSTL3 file by the SETLL
operation. Notice that the record format name CUSREC is used in the SETLL oper-
ation instead of the file name CUSMSTL3.
The SFLPRC subroutine handles the processing for the subfile: clearing, filling, and
displaying. The subfile is prepared for additional requests in subroutine SFLCLR. If
indicator 55 is on, no action occurs on the display, but the main storage area for
the subfile records is cleared. The SFLFIL routine fills the subfile with records. A
record is read from the CUSMSTL3 file, the record count (RECNUM) is incre-
mented, and the record is written to the subfile. This subroutine is repeated until
either the subfile is full (indicator 21 on the WRITE operation) or end of file occurs
on the CUSMSTL3 file (indicator 71 on the READ operation). When the subfile is
full or end of file occurs, the subfile is written to the display by the EXFMT opera-
tion by the subfile-control record control format. The user reviews the display and
decides:
¹ To end the program by pressing F3.
¹ To restart the subfile by pressing F4. The PROMPT record format is not dis-
played, and the subfile is displayed starting over with the same name.
In Figure 185, the user responds to the initial prompt by entering a customer name.
22:35:26 CUSTOMER SEARCH & INQUIRY BY NAME 9/30/94
Select
"X" Customer Name Number Zip Code
X JUDAH GOULD 00012 70068
JUDAH GOULD 00209 31088
The detailed information for the customer selected is shown in Figure 187. At this
point the user selects the appropriate function key to continue or end the inquiry.
23:39:48 CUSTOMER SEARCH & INQUIRY BY NAME 9/30/94
Customer 00012
City YORKTOWN
Compiling
1. If you specify CVTOPT(*NONE) in OPM RPG, all externally described fields
that are of a type or with attributes not supported by RPG will be ignored. If you
specify CVTOPT(*NONE) in ILE RPG, all externally described fields will be
brought into the program with the same type as specified in the external
description.
2. In RPG IV there is no dependency between DATEDIT and DECEDIT in the
control specification.
3. Regarding the ILE RPG create commands (CRTBNDRPG and CRTRPGMOD):
¹ The IGNDECERR parameter on the CRTRPGPGM command has been
replaced by the FIXNBR parameter on the ILE RPG create commands.
¹ There is a new parameter, TRUNCNBR, for controlling whether numeric
overflow is allowed.
¹ There are no auto report features or commands in RPG IV.
¹ You cannot request an MI listing from the compiler.
4. In a compiler listing, line numbers start at 1 and increment by 1 for each line of
source or generated specifications. Source IDs are numeric, that is, there are
no more AA000100 line numbers for /COPY members or expanded DDS.
5. RPG IV requires that all compiler directives appear before compile-time data,
including /TITLE. When RPG IV encounters a /TITLE directive, it will treat it as
data. (RPG III treats /TITLE specifications as compiler directives anywhere in
the source.)
The Conversion Aid will remove any /TITLE specifications it encounters in
compile-time data.
6. ILE RPG is more rigorous in detecting field overlap in data structures. For
some calculation operations involving overlapping operands, ILE RPG issues a
message while the OPM compiler does not.
7. In ILE RPG the word NOT cannot be used as a variable name. NOT is a
special word that is used as an operator in expressions.
8. At compile time, the source is read using the CCSID of the main source file,
while for OPM RPG, the source is read using the CCSID of the job.
Running
1. The FREE operation is not supported by RPG IV.
2. Certain MCH messages may appear in the job log that do not appear under
OPM (for example, MCH1202). The appearance of these messages does not
indicate a change in the behavior of the program.
I/O
1. In ILE RPG you can read a record in a file opened for update, and created or
overridden with SHARE(*YES), and then update this locked record in another
program that has opened the same file for update.
2. You cannot modify the MR indicator using the MOVE or SETON operations.
(RPG III only prevents using SETON with MR.)
3. The File Type entry on the File specification no longer dictates the type of I/O
operations that must be present in the calculation specifications.
For example, in RPG III, if you define a file as an update file, then you must
have an UPDAT operation later in the program. This is no longer true in RPG
IV. However, your file definition still must be consistent with the I/O operations
present in the program. So if you have an UPDATE operation in your source,
the file must be defined as an update file.
4. ILE RPG will allow record blocking even if the COMMIT keyword is specified on
the file description specification.
5. In RPG IV, a file opened for update will also be opened as delete capable.
You do not need any DELETE operations to make it delete capable.
6. In RPG IV, you do not have to code an actual number for the number of
devices that will be used by a multiple-device file. If you specify
MAXDEV(*FILE) on a file description specification, then the number of save
areas created for SAVEDS and SAVEIND is based on the number of devices
that your file can handle. (The SAVEDS, SAVEIND, and MAXDEV keywords on
an RPG IV file description specification correspond to the SAVDS, IND, and
NUM options on a RPG III file description specification continuation line,
respectively.)
In ILE RPG, the total number of program devices that can be acquired by the
program cannot be different from the maximum number of devices defined in
the device file. OPM RPG/400 allows this through the NUM option.
7. In ILE RPG, the ACQ and REL operation codes can be used with single device
files.
8. In ILE RPG, the relative record number and key fields in the database-specific
feedback section of the INFDS are updated on each input operation when
doing blocked reads.
9. When a referential constraint error occurs in OPM RPG/400, the status code is
set to "01299" (I/O error). In ILE RPG, the status code is set to "01022",
"01222", or "01299", depending on the type of referential constraint error that
occurs:
| ¹ If data management is not able to allocate a record due to a referential
| constraint error, a CPF502E notify message is issued. ILE RPG will set the
Appendix A. Behavioral Differences Between OPM RPG/400 and ILE RPG for AS/400 375
| status code to "01222" and OPM RPG/400 will set the status code to
| "01299".
| If you have no error indicator, 'E' extender, or INFSR error subroutine, ILE
| RPG will issue the RNQ1222 inquiry message, and OPM RPG/400 will
| issue the RPG1299 inquiry message. The main difference between these
| two messages is that RNQ1222 allows you to retry the operation.
| ¹ If data management detects a referential constraint error that has caused it
| to issue either a CPF503A, CPF502D, or CPF502F notify message, ILE
| RPG will set the status code to "01022" and OPM RPG/400 will set the
| status code to "01299".
| If you have no error indicator, 'E' extender, or INFSR error subroutine, ILE
| RPG will issue the RNQ1022 inquiry message, and OPM RPG will issue
| the RPG1299 inquiry message.
¹ All referential constraint errors detected by data management that cause
data management to issue an escape message will cause both OPM and
ILE RPG to set the status code to "01299".
10. In ILE RPG, the database-specific feedback section of the INFDS is updated
regardless of the outcome of the I/O operation. In OPM RPG/400, this feedback
section is not updated if the record-not-found condition is encountered.
11. ILE RPG relies more on data-management error handling than does OPM
RPG/400. This means that in some cases you will find certain error messages
in the job log of an ILE RPG program, but not an OPM RPG/400 program.
Some differences you will notice in error handling are:
¹ When doing an UPDATE on a record in a database file that has not been
locked by a previous input operation, both ILE RPG and OPM RPG/400 set
the status code to "01211". ILE RPG detects this situation when data man-
agement issues a CPF501B notify message and places it in the job log.
¹ When handling WORKSTN files and trying to do I/O to a device that has
not been acquired or defined, both ILE and OPM RPG will set the status to
"01281". ILE RPG detects this situation when data management issues a
CPF5068 escape message and places it in the job log.
12. When doing READE, REDPE (READPE in ILE), SETLL on a database file, or
when doing sequential-within-limits processing by a record-address-file, OPM
| RPG/400 does key comparisons using the *HEX collating sequence. This may
| give different results than expected when DDS features are used that cause
| more than one search argument to match a given key in the file. For example,
| if ABSVAL is used on a numeric key, both -1 and 1 would succeed as search
| arguments for a key in the file with a value of 1. Using the hexadecimal col-
| lating sequence, a search argument of -1 will not succeed for an actual key of
| 1.
ILE RPG does key comparisons using *HEX collating sequence only for
pre-V3R1 DDM files. See “Using Pre-V3R1 DDM Files” on page 313. for more
information.
13. ILE RPG allows the To File and the From File specified for prerun-time arrays
and tables to be different. In OPM RPG, both file names must be the same; if
they are different the diagnostic message QRG3038 is issued.
14. When translation of a RAF-Controlled file is specified, the results using ILE
RPG may differ from OPM RPG/400, depending on the translation table. This is
Appendix A. Behavioral Differences Between OPM RPG/400 and ILE RPG for AS/400 377
378 ILE RPG for AS/400 Programmer's Guide
Appendix B. Using the RPG III to RPG IV Conversion Aid
The RPG IV source specification layouts differ significantly from the System/38
environment RPG III and the OPM RPG/400 layouts. For example, the positions of
entries on the specifications have changed and the types of specifications available
have also changed. The RPG IV specification layouts are not compatible with the
previous layouts. To take advantage of RPG IV features, you must convert RPG III
and RPG/400 source members in your applications to the RPG IV source format.
Note: The valid types of source members you can convert are RPG, RPT,
RPG38, RPT38, SQLRPG, and blank. The Conversion Aid does not support
conversion of RPG36, RPT36, and other non-RPG source member types.
If you are in a hurry and want to get started, go to “Converting Your Source”
on page 382 and follow the general directions.
Conversion Overview
You convert source programs to the RPG IV source format by calling the Conver-
sion Aid through the CL command Convert RPG Source (CVTRPGSRC). The Con-
version Aid converts:
¹ A single member
¹ All members in a source physical file
¹ All members with a common member-name prefix in the same file
To minimize the likelihood of there being conversion problems, you can optionally
have the /COPY members included in the converted source code. For convenience
in reading the code, you can also optionally include specification templates in the
converted source code.
The Conversion Aid converts each source member on a line-by-line basis. After
each member conversion, it updates a log file on the status of the conversion if you
specified a log file on the command. You can also obtain a conversion report that
includes information such as conversion errors, /COPY statements, CALL oper-
ations, and conversion status.
The Conversion Aid assumes that your source code is free of any compilation
errors. If this is the case, then it will successfully convert most of your source code.
In some cases, there may be a small amount of code that you may have to convert
manually. Some of these cases are identified by the Conversion Aid. Others are not
detected until you attempt to compile the converted source. To see which ones the
Conversion Aid can identify, you can run the Conversion Aid using the unconverted
member as input, and specify a conversion report but no output member. For infor-
mation on the types of coding that cannot be converted, see “Resolving Conversion
Problems” on page 398.
If the source member type is 'blank', then the Conversion Aid will assume it has a
member type of RPG. If the source member type is blank for an auto report source
member, then you should assign the correct source member type (RPT or RPT38)
to the member before converting it. If you do, then the Conversion Aid will automat-
ically expand the auto report source member so that it can be converted properly.
The expansion is necessary since ILE RPG does not support auto report source
members.
For more information on converting auto report source members, see “Converting
Auto Report Source Members” on page 389.
12 80 20
The name of the converted source member(s) depends on whether you are con-
verting one or several members. If you are converting one member, the default is to
give the converted source member the same name as the unconverted member.
You can, of course, specify a different name for the output member. If you are con-
verting all source members in a file, or a group of them using a generic name, then
the members will automatically be given the same name as the unconverted source
members.
Note that specifying the file, library and member name for the converted output is
optional. If you do not specify any of these names, the converted output will be
placed in the file QRPGLESRC and have a member name the same as the uncon-
verted member name. (The library list will be searched for the file QRPGLESRC.)
If you specify that a log file is to be updated, then its record format must match the
format of the IBM-suppled "model" database file QARNCVTLG in library QRPGLE.
Figure 195 on page 397 shows the DDS for this file. Use the following
CRTDUPOBJ command to create a copy of this model in your own library, referred
to here as MYLIB. You may want to name your log file QRNCVTLG, as this is the
default log file name for the Conversion Aid.
CRTDUPOBJ OBJ(QARNCVTLG) FROMLIB(QRPGLE) OBJTYPE(*FILE)
TOLIB(MYLIB) NEWOBJ(QRNCVTLG)
You must have object management, operational and add authority to the log file
that is accessed by the Conversion Aid.
For information on using the log file see “Using the Log File” on page 396.
To convert your source code to the RPG IV format, follow these general steps:
1. If you use a data area as a control specification, you must create a new data
area in the RPG IV format. Refer to the chapter on control specifications in ILE
RPG for AS/400 Reference for more information.
2. Create a log file, if necessary.
Unless you specify LOGFILE(*NONE), there must be a log file for the Conver-
sion Aid to access. If you do not have one, then you can create one by using
the CRTDUPOBJ command. For more information, see “The Log File” on
page 381 and “Using the Log File” on page 396.
3. Create the file for the converted source members.
The Conversion Aid will not create any files. You must create the output file for
the converted source prior to running the CVTRPGSRC command. The recom-
mended name and record length for the output file is QRPGLESRC and 112
characters respectively. For additional file information see “File Considerations”
on page 380.
4. Convert your source using the CVTRPGSRC command.
You need to enter the name of the file and member to be converted. If you
accept the defaults, you will get a converted member in the file QRPGLESRC.
The name of the member will correspond to the name of the unconverted
source member. /COPY members will not be expanded in the converted source
member, unless it is of type RPT or RPT38. A conversion report will be gener-
ated.
See “The CVTRPGSRC Command” on page 383 for more information.
Table 29. CVTRPGSRC Parameters and Their Default Values Grouped by Function
Program Identification
FROMFILE Identifies library and file name of RPG source to be
converted
FROMMBR Identifies which source members are to be converted
TOFILE(*LIBL/QRPGLESRC) Identifies library and file name of converted output
TOMBR(*FROMMBR) Identifies file member names of converted source
Conversion Processing
TOMBR If *NONE is specified, then no file members are saved
EXPCPY(*NO) Determines if /COPY statements are included in con-
verted output
INSRTPL(*NO) Indicates if specification templates are to be included in
converted output
Conversion Feedback
CVTRPT(*YES) Determines whether to produce conversion report
SECLVL(*NO) Determines whether to include second-level message
text
LOGFILE(*LIBL/QRNCVTLG) Identifies log file for audit report
LOGMBR(*FIRST) Identifies which member of the log file to use for audit
report
The parameters and their possible values follow the syntax diagram. If you need
prompting, type CVTRPGSRC and press F4. The CVTRPGSRC screen appears,
lists the parameters, and supplies default values. For a description of a parameter
on the display, place your cursor on the parameter and press F1. Extended help
for all of the parameters is available by pressing F1 on any parameter and then
pressing F2.
FROMFILE
Specifies the name of the source file that contains the RPG III or RPG source
code to be converted and the library where the source file is stored. This is a
required parameter; there is no default file name.
source-file-name
Enter the name of the source file that contains the source member(s) to be
converted.
*LIBL
The system searches the library list to find the library where the source file
is stored.
*CURLIB
The current library is used to find the source file. If you have not specified a
current library, then the library QGPL is used.
library-name
Enter the name of the library where the source file is stored.
FROMMBR
Specifies the name(s) of the member(s) to be converted. This is a required
parameter; there is no default member name.
source-file-member-name
Enter the name of the source member to be converted.
*ALL
The command converts all the members in the source file specified.
generic*-member-name
Enter the generic name of members having the same prefix in their names
followed by a '*' (asterisk). The command converts all the members having
the generic name in the source file specified. For example, specifying
FROMMBR(PR*) will result in the conversion of all members whose names
begin with 'PR'.
(See the CL Programmer's Guide for more information on the generic
name.)
TOFILE
Specifies the name of the source file that contains converted source members
and the library where the converted source file is stored. The converted source
file must exist and should have a record length of 112 characters: 12 for the
sequence number and date, 80 for the code and 20 for the comments.
QRPGLESRC
The default source file QRPGLESRC contains the converted source
member(s).
*NONE
No converted member is generated. The TOMBR parameter value is
ignored. CVTRPT(*YES) must also be specified or the conversion will end
immediately.
This feature allows you to find some potential problems without having to
create the converted source member.
source-file-name
Enter the name of the converted source file that contains the converted
source member(s).
The TOFILE source file name must be different from the FROMFILE source
file name if the TOFILE library name is the same as the FROMFILE library.
*LIBL
The system searches the library list to find the library where the converted
source file is stored.
*CURLIB
The current library is used to find the converted source file. If you have not
specified a current library, then the library QGPL is used.
library-name
Enter the name of the library where the converted source file is stored.
*FROMMBR
The member name specified in the FROMMBR parameter is used as the
converted source member name. If FROMMBR(*ALL) is specified, then all
the source members in the FROMFILE are converted. The converted
source members have the same names as those of the original source
members. If a generic name is specified in the FROMMBR parameter, then
all the source members specified having the same prefix in their names are
converted. The converted source members have the same names as those
of the original generic source members.
source-file-member-name
Enter the name of the converted source member. If the member does not
exist it will be created.
EXPCPY
Specifies whether or not /COPY member(s) is expanded into the converted
source member. EXPCPY(*YES) should be specified only if you are having
conversion problems pertaining to /COPY members.
Note: If the member is of type RPT or RPT38, EXPCPY(*YES) or
EXPCPY(*NO) has no effect because the auto report program will
always expand the /COPY members.
*NO
Do not expand the /COPY file member(s) into the converted source.
*YES
Expands the /COPY file member(s) into the converted source.
CVTRPT
Specifies whether or not a conversion report is printed.
*YES
The conversion report is printed.
*NO
The conversion report is not printed.
SECLVL
Specifies whether second-level text is printed in the conversion report in the
message summary section.
*NO
Second-level message text is not printed in the conversion report.
*YES
Second-level message text is printed in the conversion report.
INSRTPL
Specifies if the ILE RPG specification templates (H-, F-, D-, I-, C- and/or
O-specification template), are inserted in the converted source member(s). The
default value is *NO.
*YES
A specification template is inserted in the converted source member. Each
specification template is inserted at the beginning of the appropriate specifi-
cation section.
LOGFILE
Specifies the name of the log file that is used to track the conversion informa-
tion. Unless *NONE is specified, there must be a log file. The file must already
exist, and it must be a physical data file. Create the log file by using the CPYF
command with the "From object" file QARNCVTLG in library QRPGLE and the
"New object" file QRNCVTLG in your library.
QRNCVTLG
The default log file QRNCVTLG is used to contain the conversion informa-
tion.
*NONE
Conversion information is not written to a log file.
log-file-name
Enter the name of the log file that is to be used to track the conversion
information.
*LIBL
The system searches the library list to find the library where the log file is
stored.
library-name
Enter the name of the library where the log file is stored.
LOGMBR
Specifies the name of the log file member used to track conversion information.
The new information is added to the existing data in the specified log file
member.
If the log file contains no members, then a member having the same name as
the log file is created.
*FIRST
The command uses the first member in the specified log file.
*LAST
The command uses the last member in the specified log file.
log-file-member-name
Enter the name of the log file member used to track conversion information.
This will result in the conversion of the specified source member. The output will be
placed in the file QRPGLESRC in whichever library in the library list contains this
For example, if you want to convert all source members in the file QRPGSRC to
the file QRPGLESRC, you would enter:
CVTRPGSRC FROMFILE(OLDRPG/QRPGSRC)
FROMMBR(*ALL)
TOFILE(NEWRPG/QRPGLESRC)
TOMBR(*FROMMBR)
This command converts all of the source members in library OLDRPG in the source
physical file QRPGSRC. The new members are created in library NEWRPG in the
source physical file QRPGLESRC.
If you prefer to keep all source (DDS source, RPG source, etc.) in the same file,
you can still convert the RPG source members in one step, by specifying
FROMMBR(*ALL). The Conversion Aid will only convert members with a valid RPG
type (see Table 28 on page 380).
For example, if you want to convert all members with a prefix of PAY, you would
enter:
CVTRPGSRC FROMFILE(OLDRPG/QRPGSRC)
FROMMBR(PAY*)
TOFILE(NEWRPG/QRPGLESRC)
TOMBR(*FROMMBR)
This command converts all of the source members in library OLDRPG in the source
physical file QRPGSRC. The new members are created in library NEWRPG in the
source physical file QRPGLESRC.
For example, to perform a trial conversion on the source member PAYROLL, type:
CVTRPGSRC FROMFILE(OLDRPG/QRPGSRC)
FROMMBR(PAYROLL)
TOFILE(*NONE)
Using the TOFILE(*NONE) parameter stops the Conversion Aid from generating a
converted member, but still allows it to produce a conversion report. For more infor-
mation on the conversion report, see “Analyzing Your Conversion” on page 393.
The conversion error messages provide you with suggestions on how to correct the
error. In addition, any CALL operations and /COPY directives in the unconverted
source are flagged to help you in identifying the various parts of the application you
are converting. In general, you should convert all RPG components of an applica-
tion at the same time.
The auto report program produces a spooled file each time it is called by the Con-
version Aid. You may want to check this file to see if any errors occurred on the
auto report expansion, since these errors will not be in the conversion report.
In particular, you may want to check the auto report spooled file for an error
message indicating that /COPY members were not found. The Conversion Aid will
not know if these files are missing. However, without these files, it may not be able
to successfully convert your source.
The first part of the listing includes a summary of the command options used by
CVTRPGSRC. Figure 191 shows the command summary for a sample conversion.
| 5769RG1 V4R2M0 980228RN IBM ILE RPG AS400S01 12/30/97 20:41:35 Page 1
Command . . . . . . . . . . . . : CVTRPGSRC
Issued by . . . . . . . . . . : DAVE
To file. . . . . . . . . . . . . : QRPGLESRC
Library . . . . . . . . . . . : MYLIB
To member . . . . . . . . . . . : *FROMMBR
The source section includes lines that have informational, warning, or error mes-
sages associated with them. These lines have an asterisk (*) in column 1 for ease
of browsing in SEU. The message summary contains all three message types.
All /COPY members in an program must be converted in order for the corre-
sponding ILE RPG program to compile without errors. Similarly, you may want to
convert all members related by CALL at the same time. Use this part of the report
to assist you in identifying these members. Figure 192 on page 395 shows the
source section for the sample conversion.
C o n v e r s i o n R e p o r t
* * * * * E N D O F S O U R C E * * * * *
The message summary of the listing shows you the different messages that were
issued. If you specify SECLVL(*YES), second-level messages will appear in the
message summary. Figure 193 shows the messages section for the sample con-
version, including second-level messages.
| 5769RG1 V4R2M0 980228RN IBM ILE RPG AS400S01 12/30/97 20:41:35 Page 2
M e s s a g e S u m m a r y
* * * * * E N D O F M E S S A G E S U M M A R Y * * * * *
F i n a l S u m m a r y
Message Totals:
Information (00) . . . . . . . : 2
Warning (10) . . . . . . . : 0
Severe Error (30+) . . . . . . : 1
--------------------------------- -------
Total . . . . . . . . . . . . . : 3
Source Totals:
Original Records Read . . . . . . : 3
Converted Records Written . . . . : 4
Highest Severity Message Issued . : 30
* * * * * E N D O F F I N A L S U M M A R Y * * * * *
* * * * * E N D O F C O N V E R S I O N * * * * *
For example, if no errors are found, the conversion status is set to 0. If severe
errors are found, the status is set to 30.
If you try to convert a member with an unsupported member type or a member that
already exists, then the conversion will not take place, as this is a severe error
(severity 40 or higher). A record will be added to the log file with the conversion
status set to 40. The TOFILE, TOMBR, and TO LIBRARY will be set to blank to
indicate that a TOMBR was not generated (as the conversion did not take place).
The log file is an externally described, physical database file. A "model" of this file
is provided in library QRPGLE in file QARNCVTLG. It has one record format called
QRNCVTLG. All field names are six characters in length and follow the naming
convention LGxxxx, where xxxx describes the fields. Figure 195 on page 397
shows the DDS for this file.
| Use the following CRTDUPOBJ command to create a copy of this model in your
| own library, referred to here as MYLIB. You may want to name your log file
| QRNCVTLG, as this is the default log file name for the Conversion Aid.
CPYF FROMFILE(QRPGLE/QARNCVTLG) TOFILE(MYLIB/QRNCVTLG)
CRTFILE(*YES)
Figure 195. DDS for model log file QARNCVTLG in library QRPGLE
Since the auto report function is not supported, the Conversion Aid will automat-
ically expand these programs (that is, call auto report) prior to performing the con-
version if the type is RPT or RPT38.
You must replace the FREE or DEBUG operation code with equivalent logic either
before or after conversion.
If you specify the CVTRPT(*YES) option on the CVTRPGSRC command, you will
receive a conversion report that identifies most of these types of problems.
For further information on converting auto report members, see “Converting Auto
Report Source Members” on page 389. For further information on differences
between RPG III and RPG IV, see Appendix A, “Behavioral Differences Between
OPM RPG/400 and ILE RPG for AS/400” on page 373.
Now suppose that the RPG III member TEST1 was split into two members, TEST2
and COPYDS1, where the data structure DS1 and the named constant CONST1
are in a copy member COPYDS1. This copy member is included in source TEST2.
Figure 196 and Figure 197 show the source for TEST2 and COPYDS1 respec-
tively.
H TSTPGM
FFILE1 IF E DISK COMM1
FQSYSPRT O F 132 OF LPRINTER
LQSYSPRT 60FL 56OL
E ARR1 3 3 1 COMM2
E ARR2 3 3 1
IFORMAT1
I OLDNAME NAME
/COPY COPYDS1
C ARR1,3 DSPLY
C READ FORMAT1 01
C NAME DSPLY
C SETON LR
C EXCPTOUTPUT
OQSYSPRT E 01 OUTPUT
O ARR2,3 10
**
123
**
456
In this situation, the Conversion Aid would convert both member TEST2 and the
copy member COPYDS1 correctly. However, when the copy member is included at
compile time, it will be inserted below FORMAT1, because this is where the /COPY
directive is located. As a result, all source lines in the copy member COPYDS1 will
get a "source record is out of sequence" error. In RPG IV, definition specifications
must precede input specifications.
Note that the Conversion Aid could not move the /COPY directive above FORMAT1
because the contents of /COPY member are unknown.
Context-Sensitive Problems
In RPG III, there are occasions when it is impossible to determine the type of spec-
ifications in a /COPY member without the context of the surrounding specifications
of the primary source member. There are two instances of this problem:
¹ In data structure subfields or program-described file fields
Figure 198. RPG III /COPY file with input fields only
In the above two instances, a data structure is assumed and definition specifica-
tions are produced. A block of comments containing the input specification code is
also produced. For example, the Conversion Aid will convert the source in
Figure 198 on page 400 to the code shown in Figure 200. If Input specification
code is required, delete the definition specifications and blank out the asterisks
from the corresponding Input specifications.
| Figure 200. RPG IV source after converting source with input fields only
Remember that you have two ways of correcting these types of problems. Either
use the EXPCPY(*YES) option of the CVTRPGSRC command, or manually correct
the code after conversion.
These problems are related to the use of externally described data structures.
Because these problems will generate compile-time errors, you can use the infor-
mation in the ILE RPG compiler listing and the ILE RPG for AS/400 Reference to
correct them.
For example, the field ARRAY in Figure 201 is included twice in Figure 202. It is
included once as a standalone array and once in the externally described data
structure EXTREC. When converted, the RPG IV source generated is shown in
Figure 203. This code will not compile since ARRAY is defined twice. In order to
correct this problem, delete the standalone array and add a subfield with the
keywords to data structure DSONE as shown in Figure 204.
A R RECORD
A CHARACTER 10
A ARRAY 10
E ARRAY 10 1
IDSONE E DSEXTREC
C CHAR DSPLY
C SETON LR
| Figure 202. RPG III source using external data structure with array
D ARRAY S 1 DIM(10)
D DSONE E DS EXTNAME(EXTREC)
C CHAR DSPLY
C SETON LR
| Figure 203. RPG IV source with two definitions for the array
D DSONE E DS EXTNAME(EXTREC)
D ARRAY E DIM(10)
C CHAR DSPLY
C SETON LR
| Figure 204. Corrected RPG IV source with a single definition for the array
Figure 205. RPG III source with renamed and initialized external subfield
D DSONE E DS EXTNAME(EXTREC)
D CHAR E EXTFLD(CHARACTER)
D CHAR E INZ('XYZ')
C CHAR DSPLY
C SETON LR
Figure 206. RPG IV source with two definitions for renamed subfield
D DSONE E DS EXTNAME(EXTREC)
D CHAR E EXTFLD(CHARACTER) INZ('XYZ')
C CHAR DSPLY
C SETON LR
Run-time Differences
If you have prerun-time arrays that overlap in data structures, the order of loading
these arrays at run time may be different in RPG III and in RPG IV. This difference
in order can cause the data in the overlapping section to differ. The order in which
the arrays are loaded is the order in which they are encountered in the source. This
order may have changed when the arrays were been merged with the subfields
during conversion.
In general, you should avoid situations where an application consists of OPM and
ILE programs that are split across the OPM default activation group and a named
activation group. When spilt across these two activation groups, you are mixing
OPM behavior with ILE behavior and your results may be hard to predict. Refer to
Chapter 3, “Program Creation Strategies” on page 23 or ILE Concepts for further
information.
For information on the Create Program and Create Service Program commands,
see the CL Reference.
Using CL Commands
Control Language (CL) commands, parameters, and keywords can be entered
in either uppercase or lowercase characters. In the syntax diagram they are shown
in uppercase (for example, PARAMETER, PREDEFINED-VALUE). Variables
appear in lowercase italic letters (for example, user-defined-value). Variables are
user-defined names or values.
55──PARAMETER──(──┬──────────────────┬──user-defined-value──)───────────────────────────5%
└─PREDEFINED-VALUE─┘
Read the syntax diagram from left to right, and from top to bottom, following the
path of the line.
The ───5 symbol indicates that the statement syntax is continued on the next line.
The 5─── symbol indicates that a statement is continued from the previous line.
The ──(──)── symbol indicates that the parameter or value must be entered in
parentheses.
Required parameters appear on the base line and must be entered. Optional
parameters appear below the base line and do not need to be entered. In the fol-
lowing sample, you must enter REQUIRED-PARAMETER and a value for it, but
you do not need to enter OPTIONAL-PARAMETER or a value for it.
Default values appear above the base line and do not need to be entered. They
are used when you do not specify a parameter. In the following sample, you can
enter DEFAULT-VALUE, OTHER-PREDEFINED-VALUE, or nothing. If you enter
nothing, DEFAULT-VALUE is assumed.
┌─DEFAULT-VALUE──────────┐
55──PARAMETER──(──┴─OTHER-PREDEFINED-VALUE─┴──)─────────────────────────────────────────5%
Optional values are indicated by a blank line. The blank line indicates that a value
from the first group (OPTIONAL-VALUE1, OPTIONAL-VALUE2, user-defined-value)
does not need to be entered. For example, based on the syntax below, you could
enter KEYWORD(REQUIRED-VALUE).
┌─OPTIONAL-VALUE1────┐
55──PARAMETER──(──┼────────────────────┼────REQUIRED-VALUE────)─────────────────────────5%
├─OPTIONAL-VALUE2────┤
└─user-defined-value─┘
Repeated values can be specified for some parameters. The comma (,) in the fol-
lowing sample indicates that each user-defined-value must be separated by a
comma.
┌─,────────────────────┐
55──KEYWORD──(───6──user-defined-value──┴──)─────────────────────────────────────────────5%
CRTBNDRPG Command
The Create Bound RPG (CRTBNDRPG) command performs the combined tasks of
the Create RPG Module (CRTRPGMOD) and Create Program (CRTPGM) com-
mands by creating a temporary module object from the source code, and then cre-
ating the program object. Once the program object is created, CRTBNDRPG
deletes the module object it created. The entire syntax diagram for the
CRTBNDRPG command is shown below.
55──CRTBNDRPG──┬────────────────────────────────────────────────┬────────────────────────────5
│ ┌─*CURLIB/──────┐ ┌─*CTLSPEC─────┐ │
└─PGM──(──┼───────────────┼──┴─program-name─┴──)─┘
└─library-name/─┘
OPTION Details:
┌─*XREF───┐ ┌─*GEN───┐ ┌─*NOSECLVL─┐ ┌─*SHOWCPY───┐ ┌─*EXPDDS───┐ ┌─*EXT───┐
├──┼─────────┼──┼────────┼──┼───────────┼──┼────────────┼──┼───────────┼──┼────────┼─────────5
└─*NOXREF─┘ └─*NOGEN─┘ └─*SECLVL───┘ └─*NOSHOWCPY─┘ └─*NOEXPDDS─┘ └─*NOEXT─┘
┌─*NOSHOWSKP─┐ ┌─*NOEVENTF─┐
5──┼────────────┼──┼───────────┼─────────────────────────────────────────────────────────────┤
└─*SHOWSKP───┘ └─*EVENTF───┘
PGM
Specifies the program name and library name for the program object (*PGM)
you are creating. The program name and library name must conform to AS/400
naming conventions. If no library is specified, the created program is stored in
the current library.
*CTLSPEC
The name for the compiled program is taken from the name specified in the
DFTNAME keyword of the control specification. If the program name is not
specified on the control specification and the source member is from a
database file, the member name, specified by the SRCMBR parameter, is
used as the program name. If the source is not from a database file then
the program name defaults to RPGPGM.
program-name
Enter the name of the program object.
*CURLIB
The created program object is stored in the current library. If you have not
specified a current library, QGPL is used.
library-name
Enter the name of the library where the created program object is to be
stored.
SRCFILE
Specifies the name of the source file that contains the ILE RPG source
member to be compiled and the library where the source file is located. The
recommended source physical file length is 112 characters: 12 for the
sequence number and date, 80 for the code and 20 for the comments. This is
the maximum amount of source that is shown on the compiler listing.
QRPGLESRC
The default source file QRPGLESRC contains the ILE RPG source member
to be compiled.
source-file-name
Enter the name of the source file that contains the ILE RPG source
member to be compiled.
*CURLIB
The current library is used to find the source file. If you have not specified a
current library, QGPL is used.
library-name
Enter the name of the library where the source file is stored.
SRCMBR
Specifies the name of the member of the source file that contains the ILE RPG
source program to be compiled.
*PGM
Use the name specified by the PGM parameter as the source file member
name. The compiled program object will have the same name as the
source file member. If no program name is specified by the PGM param-
eter, the command uses the first member created in or added to the source
file as the source member name.
source-file-member-name
Enter the name of the member that contains the ILE RPG source program.
GENLVL
Controls the creation of the program object. The program object is created if all
errors encountered during compilation have a severity level less than or equal
to the generation severity level specified.
severity-level-value
Enter a number, 0 through 20 inclusive. For errors greater than severity 20,
the program object will not be generated.
TEXT
Allows you to enter text that briefly describes the program and its function. The
text appears whenever program information is displayed.
*SRCMBRTXT
The text of the source member is used.
*BLANK
No text appears.
'description'
Enter the text that briefly describes the function of the source specifications.
The text can be a maximum of 50 characters and must be enclosed in
apostrophes. The apostrophes are not part of the 50-character string. Apos-
trophes are not required if you are entering the text on the prompt screen.
DFTACTGRP
Specifies whether the created program is intended to always run in the default
activation group.
*NO
The program is associated with the activation group specified by the
ACTGRP parameter. Static binding is allowed when *NO is specified.
If ACTGRP(*CALLER) is specified and this program is called by a program
running in the default activation group, then this program will behave
according to ILE semantics in the areas of file sharing, file scoping and
RCLRSC.
DFTACTGRP(*NO) is useful when you intend to take advantage of ILE
concepts; for example, running in a named activation group or binding to a
service program.
OPTION
Specifies the options to use when the source member is compiled. You can
specify any or all of the options in any order. Separate the options with one or
more blank spaces. If an option is specified more than once, the last one is
used.
*XREF
Produces a cross-reference listing (when appropriate) for the source
member.
*NOXREF
A cross-reference listing is not produced.
*GEN
Create a program object if the highest severity level returned by the com-
piler does not exceed the severity specified in the GENLVL option.
*NOGEN
Do not create a program object.
*NOSECLVL
Do not print second-level message text on the line following the first-level
message text.
*SECLVL
Print second-level message text on the line following the first-level message
text in the Message Summary section.
*NOSHOWCPY
Do not show source records of members included by the /COPY compiler
directive.
*EXPDDS
Show the expansion of externally described files in the listing and display
key field information.
*NOEXPDDS
Do not show the expansion of externally described files in the listing or
display key field information.
*EXT
Show the list of external procedures and fields referenced during the
compile on the listing.
*NOEXT
Do not show the list of external procedures and fields referenced during the
compilation on the listing.
*NOSHOWSKP
Do not show ignored statements in the source part of the listing. The com-
piler ignores statements as a result of /IF, /ELSEIF or /ELSE directives.
*SHOWSKP
Show all statements in the source part of the listing, regardless of whether
or not the compiler has skipped them.
*NOEVENTF
Do not create an Event File for use by CoOperative Development
Environment/400 (CODE/400). CODE/400 uses this file to provide error
feedback integrated with the CODE/400 editor. An Event File is normally
created when you create a module or program from within CODE/400.
*EVENTF
Create an Event File for use by CoOperative Development
Environment/400 (CODE/400). The Event File is created as a member in
file EVFEVENT in the library where the created module or program object
is to be stored. If the file EVFEVENT does not exist it is automatically
created. The Event File member name is the same as the name of the
object being created.
CODE/400 uses this file to provide error feedback integrated with the
CODE/400 editor. An Event File is normally created when you create a
module or program from within CODE/400.
DBGVIEW
Specifies which level of debugging is available for the compiled program object,
and which source views are available for source-level debugging.
*STMT
Allows the program object to be debugged using the Line Numbers shown
on the left-most column of the source section of the compiler listing.
*LIST
Generates the listing view for debugging the compiled program object. The
information contained in the listing view is dependent on whether
*SHOWCPY and *EXPDDS are specified for the OPTION parameter.
Note: The listing view will not show any indentation which you may have
requested using the Indent option.
*COPY
Generates the source and copy views for debugging the compiled program
object. The source view for this option is the same source view generated
for the *SOURCE option. The copy view is a debug view which has all the
/COPY source members included. These views will not be available if the
root source member is a DDM file. Also, if changes are made to any source
members after the compile and before attempting to debug the program,
the views for those source members may not be usable.
*ALL
Generates the listing, source and copy views for debugging the compiled
program object. The information contained in the listing view is dependent
on whether *SHOWCPY and *EXPDDS are specified for the OPTION
parameter.
*NONE
Disables all of the debug options for debugging the compiled program
object.
OUTPUT
Specifies if a compiler listing is generated.
*PRINT
Produces a compiler listing, consisting of the ILE RPG program source and
all compile-time messages. The information contained in the listing is
dependent on whether *XREF, *SECLVL, *SHOWCPY, *SHOWSKP,
*EXPDDS, and *EXT are specified for the OPTION parameter.
*NONE
Do not generate the compiler listing.
OPTIMIZE
Specifies the level of optimization, if any, of the program.
*NONE
Generated code is not optimized. This is the fastest in terms of translation
time. It allows you to display and modify variables while in debug mode.
*BASIC
Some optimization is performed on the generated code. This allows user
variables to be displayed but not modified while the program is in debug
mode.
INDENT
Specifies whether structured operations should be indented in the source listing
for enhanced readability. Also specifies the characters that are used to mark
the structured operation clauses.
Note: Any indentation that you request here will not be reflected in the listing
debug view that is created when you specify DBGVIEW(*LIST).
*NONE
Structured operations will not be indented in the source listing.
character-value
The source listing is indented for structured operation clauses. Alignment of
statements and clauses are marked using the characters you choose. You
can choose any character string up to 2 characters in length. If you want to
use a blank in your character string, you must enclose the string in single
quotation marks.
Note: The indentation may not appear as expected if there are errors in
the program.
CVTOPT
Specifies how the ILE RPG compiler handles date, time, timestamp, graphic
data types, and variable-length data types which are retrieved from externally
described database files.
*NONE
Ignores variable-length database data types and use the native RPG date,
time, timestamp and graphic data types.
*DATETIME
Specifies that date, time, and timestamp database data types are to be
declared as fixed-length character fields.
*GRAPHIC
Specifies that double-byte character set (DBCS) graphic data types are to
be declared as fixed-length character fields.
*VARCHAR
Specifies that variable-length character data types are to be declared as
fixed-length character fields.
*VARGRAPHIC
Specifies that variable-length double-byte character set (DBCS) graphic
data types are to be declared as fixed-length character fields.
SRTSEQ
Specifies the sort sequence table that is to be used in the ILE RPG source
program.
*HEX
No sort sequence table is used.
*JOBRUN
Use the SRTSEQ value for the job when the *PGM is run.
*LANGIDUNQ
Use a unique-weight table. This special value is used in conjunction with
the LANGID parameter to determine the proper sort sequence table.
*LANGIDSHR
Use a shared-weight table. This special value is used in conjunction with
the LANGID parameter to determine the proper sort sequence table.
sort-table-name
Enter the qualified name of the sort sequence table to be used with the
program.
*LIBL
The system searches the library list to find the library where the sort
sequence table is stored.
*CURLIB
The current library is used to find the sort sequence table. If you have not
specified a current library, QGPL is used.
library-name
Enter the name of the library where the sort sequence table is stored.
LANGID
Specifies the language identifier to be used when the sort sequence is
*LANGIDUNQ and *LANGIDSHR. The LANGID parameter is used in conjunc-
tion with the SRTSEQ parameter to select the sort sequence table.
*JOBRUN
Use the LANGID value associated with the job when the RPG program is
executed.
*JOB
Use the LANGID value associated with the job when the RPG program is
created.
language-identifier
Use the language identifier specified. (For example, FRA for French and
DEU for German.)
REPLACE
Specifies if a new program is created when a program of the same name
already exists in the specified (or implied) library. The intermediate module
created during the processing of the CRTBNDRPG command are not subject to
the REPLACE specifications, and have an implied REPLACE(*NO) against the
QTEMP library. The intermediate modules is deleted once the CRTBNDRPG
command has completed processing.
*YES
A new program is created in the specified library. The existing program of
the same name in the specified library is moved to library QRPLOBJ.
USRPRF
Specifies the user profile that will run the created program object. The profile of
the program owner or the program user is used to run the program and to
control which objects can be used by the program (including the authority the
program has for each object). This parameter is not updated if the program
already exists. To change its value, you must delete the program and recompile
using the new value (or, if the constituent *MODULE objects exist, you may
choose to invoke the CRTPGM command).
*USER
The program runs under the user profile of the program's user.
*OWNER
The program runs under the user profile of both the program's user and
owner. The collective set of object authority in both user profiles are used
to find and access objects while the program is running. Any objects
created during the program are owned by the program's user.
AUT
Specifies the authority given to users who do not have specific authority to the
object, who are not on the authorization list, and whose user group has no spe-
cific authority to the object. The authority can be altered for all users or for
specified users after the program is created with the CL commands Grant
Object Authority (GRTOBJAUT) or Revoke Object Authority (RVKOBJAUT). For
further information on these commands, see the CL Reference
*LIBCRTAUT
The public authority for the object is taken from the CRTAUT keyword of
the target library (the library that contains the object). The value is deter-
mined when the object is created. If the CRTAUT value for the library
changes after the create, the new value will not affect any existing objects.
*ALL
Authority for all operations on the program object, except those limited to
the owner or controlled by authorization list management authority. The
user can control the program object's existence, specify this security for it,
change it, and perform basic functions on it, but cannot transfer its owner-
ship.
*CHANGE
Provides all data authority and the authority to perform all operations on the
program object except those limited to the owner or controlled by object
authority and object management authority. The user can change the object
and perform basic functions on it.
*USE
Provides object operational authority and read authority; that is, authority
for basic operations on the program object. The user is prevented from
changing the object.
*EXCLUDE
The user is prevented from accessing the object.
TRUNCNBR
Specifies if the truncated value is moved to the result field or an error is gener-
ated when numeric overflow occurs while running the program.
Note: The TRUNCNBR option does not apply to calculations performed within
expressions. (Expressions are found in the Extended-Factor 2 field.) If
overflow occurs for these calculations, an error will always occur. In
addition, overflow is always signalled for any operation where the value
that is assigned to an integer or unsigned field is out of range.
*YES
Ignore numeric overflow and move the truncated value to the result field.
*NO
When numeric overflow is detected, a run time error is generated with error
code RNX0103.
| FIXNBR
| Specifies whether decimal data that is not valid is fixed by the compiler.
| *NONE
| Indicates that decimal data that is not valid will result in decimal data errors
| during run time if used.
| *ZONED
| Zoned-decimal data that is not valid will be fixed by the compiler on the
| conversion to packed data. Blanks in numeric fields will be treated as
| zeroes. Each decimal digit will be checked for validity. If a decimal digit is
| not valid, it is replaced with zero. If a sign is not valid, the sign will be
| forced to a positive sign code of hex 'F'. If the sign is valid, it will be
| changed to either a positive sign hex 'F' or a negative sign hex 'D', as
| appropriate. If the resulting packed data is not valid, it will not be fixed.
| *INPUTPACKED
| Indicates that if packed decimal data that is not valid is encountered while
| processing input specifications, the internal variable will be set to zero.
TGTRLS
Specifies the release level of the operating system on which you intend to use
the object being created. In the examples given for the *CURRENT and *PRV
values, and when specifying the target-release value, the format VxRxMx is
used to specify the release, where Vx is the version, Rx is the release, and Mx
| is the modification level. For example, V4R2M0 is version 4, release 2, modifi-
| cation level 0.
Valid values for this parameter change every release.
*CURRENT
| The object is to be used on the release of the operating system currently
| running on your system. For example, if V4R2M0 is running on the system,
| *CURRENT means you intend to use the object on a system with V4R2M0
| installed. You can also use the object on a system with any subsequent
| release of the operating system installed.
*PRV
The object is to be used on the previous release with modification level 0 of
the operating system. For example, if V2R3M5 is running on your system,
*PRV means you intend to use the object on a system with V2R2M0
installed. You can also use the object on a system with any subsequent
release of the operating system installed.
target-release
Specify the release in the format VxRxMx. You can use the object on a
system with the specified release or with any subsequent release of the
operating system installed.
Valid values depend on the current version, release, and modification level,
and they change with each new release. If you specify a target-release that
is earlier than the earliest release level supported by this command, an
error message is sent indicating the earliest supported release.
ALWNULL
Specifies how the ILE RPG module will be allowed to use records containing
null-capable fields from externally described database files.
*NO
Specifies that the ILE RPG module will not process records with null-value
fields from externally-described files. If you attempt to retrieve a record con-
taining null values, no data in the record is accessible to the ILE RPG
module and a data-mapping error occurs.
*INPUTONLY
Specifies that the ILE RPG module can successfully read records with null-
capable fields containing null values from externally-described input-only
database files. When a record containing null values is retrieved, no data-
mapping errors occur and the database default values are placed into any
fields that contain null values. The module cannot do any of the following:
*USRCTL
Specifies that the ILE RPG module can read, write, and update records
with null values from externally-described database files. Records with null
keys can be retrieved using keyed operations. The module can determine
whether a null-capable field is actually null, and it can set a null-capable
field to be null for output or update. The programmer is responsible for
*YES
Same as *INPUTONLY.
BNDDIR
Specifies the list of binding directories that are used in symbol resolution.
*NONE
No binding directory is specified.
binding-directory-name
Specify the name of the binding directory used in symbol resolution.
The directory name can be qualified with one of the following library values:
*LIBL
The system searches the library list to find the library where the binding
directory is stored.
*CURLIB
The current library for the job is searched. If no library is specified as the
current library for the job, library QGPL is used.
*USRLIBL
Only the libraries in the user portion of the job's library list are searched.
library-name
Specify the name of the library to be searched.
ACTGRP
Specifies the activation group this program is associated with when it is called.
QILE
When this program is called, it is activated into the named activation group
QILE.
*NEW
When this program is called, it is activated into a new activation group.
*CALLER
When this program is called, it is activated into the caller's activation group.
activation-group-name
Specify the name of the activation group to be used when this program is
called.
ENBPFRCOL
Specifies whether performance collection is enabled.
*PEP
Performance statistics are gathered on the entry and exit of the program
entry procedure only. This applies to the actual program-entry procedure for
a program, not to the main procedure of the modules within the program.
This is the default.
*NEW
When this program is called, it is activated into a new activation group.
*FULL
Performance statistics are gathered on entry and exit of all procedures.
Also, statistics are gathered before and after each call to an external proce-
dure.
DEFINE
| Specifies condition names that are defined before the compilation begins.
| Using the parameter DEFINE(condition-name) is equivalent to coding the
| /DEFINE condition-name directive on the first line of the source file.
| *NONE
| No condition names are defined. This is the default.
| condition-name
| Up to 32 condition names can be specified. Each name can be up to 50
| characters long. The condition names will be considered to be defined at
| the start of compilation.
| PRFDTA
| Specifies the program profiling data attribute for the program. Program profiling
| is an advanced optimization technique used to reorder procedures and code
| within the procedures based on statistical data (profiling data).
| *NOCOL
| This program is not enabled to collect profiling data. This is the default.
| *COL
| The program is enabled to collect profiling data. *COL can be specified only
| when the optimization level of the module is *FULL.
CRTRPGMOD Command
The Create RPG Module (CRTRPGMOD) command compiles ILE RPG source
code to create a module object (*MODULE). The entire syntax diagram for the
CRTRPGMOD command is shown below.
55──CRTRPGMOD──┬──────────────────────────────────────────────────┬──────────────────────────5
│ ┌─*CURLIB/──────┐ ┌─*CTLSPEC────┐ │
└─MODULE──(──┼───────────────┼──┴─module-name─┴──)─┘
└─library-name/─┘
5──┬────────────────────────────────────────────────────────┬────────────────────────────────5
│ ┌─*LIBL/────────┐ ┌─QRPGLESRC────────┐ │
└─SRCFILE──(──┼───────────────┼──┴─source-file-name─┴──)─┘
├─*CURLIB/──────┤
└─library-name/─┘
(P) ──────────────────────────────────────────5
5──┬───────────────────────────────────────────┬───
│ ┌─*MODULE─────────────────┐ │
└─SRCMBR──(──┴─source-file-member-name─┴──)─┘
5──┬────────────────────────────────────────┬──┬───────────────────────────────┬─────────────5
│ ┌─10───────────────────┐ │ │ ┌─*SRCMBRTXT────┐ │
└─GENLVL──(──┴─severity-level-value─┴──)─┘ └─TEXT──(──┼─*BLANK────────┼──)─┘
└─'description'─┘
OPTION Details:
┌─*XREF───┐ ┌─*GEN───┐ ┌─*NOSECLVL─┐ ┌─*SHOWCPY───┐ ┌─*EXPDDS───┐ ┌─*EXT───┐
├──┼─────────┼──┼────────┼──┼───────────┼──┼────────────┼──┼───────────┼──┼────────┼─────────5
└─*NOXREF─┘ └─*NOGEN─┘ └─*SECLVL───┘ └─*NOSHOWCPY─┘ └─*NOEXPDDS─┘ └─*NOEXT─┘
┌─*NOSHOWSKP─┐ ┌─*NOEVENTF─┐
5──┼────────────┼──┼───────────┼─────────────────────────────────────────────────────────────┤
└─*SHOWSKP───┘ └─*EVENTF───┘
Prologue
The prologue section summarizes the command parameters and their values as
they were processed by the CL command analyzer. If *CURLIB or *LIBL was speci-
fied, the actual library name is listed. Also indicated in the prologue is the effect of
overrides. Figure 209 on page 425 illustrates how to interpret the Prologue section
of the listing for the program MYSRC, which was compiled using the CRTRPGMOD
command.
Command . . . . . . . . . . . . : CRTBNDRPG
Issued by . . . . . . . . . . : MYUSERID
Source Section
The source section shows records that comprise the ILE RPG source specifica-
tions. The root source member records are always shown. If OPTION(*EXPDDS) is
also specified, then the source section shows records generated from externally
described files, and marks them with a '=' in the column beside the line number.
These records are not shown if *NOEXPDDS is specified. If OPTION(*SHOWCPY)
is specified, then it also shows the records from /COPY members specified in the
source, and marks them with a '+' in the column beside the line number. These
records are not shown if *NOSHOWCPY is specified.
The source section also shows the conditional compilation process. All lines with
/IF, /ELSEIF, /ELSE and /ENDIF directives and source lines selected by the /IF
groups are printed and given a listing line number. If OPTION(*SHOWSKP) is spec-
ified, it shows all statements that have been excluded by the /IF, /ELSEIF, and
/ELSE directives, and marks them with a '-------' in the column beside the state-
ment. Line numbers in the listing are not incremented for excluded lines. All
skipped statements are printed exactly as specified, but are not interpreted in any
way. For example, an excluded statement with an /EJECT directive does not cause
a page break. Similarly, /SPACE, /TITLE, /COPY and /EOF compiler directives are
ignored if they are encountered in excluded lines. These statements are not shown
if the default OPTION(*NOSHOWSKP) is specified; instead a message is printed
giving the number of lines excluded.
The source section identifies any syntax errors in the source, and includes a match-
field table, when appropriate.
Note that the line numbers in the listing reflect the compiled source. For example,
Program MYSRC has a /COPY statement in line 26. In the root source member,
the next line is a DOWEQ operation. In the listing, however, the DOWEQ operation
is on line 30. The three intervening lines shown in the listing are from the /COPY
source member.
Figure 210 on page 427 shows the source section for MYSRC.
16=IINREC 2 1
*--------------------------------------------------------------------------------------------* 2
* RPG record format . . . . : INREC * 2
* External format . . . . . : INREC : MYLIB/INFILE * 2
*--------------------------------------------------------------------------------------------* 2
17=I 1 25 FLDA 2 2
18=I 26 90 FLDB 2 3
19=IREC1 3 1
*--------------------------------------------------------------------------------------------* 3
* RPG record format . . . . : REC1 * 3
* External format . . . . . : REC1 : MYLIB/KEYL6 * 3
*--------------------------------------------------------------------------------------------* 3
20=I *ISO-D 1 10 FLD12 3 2
21=I 11 13 FLD13 3 3
22=I 14 17 FLD14 3 4
23=I 18 22 FLD15 3 5
24=IREC2 4 1
*--------------------------------------------------------------------------------------------* 4
* RPG record format . . . . : REC2 * 4
* External format . . . . . : REC2 : MYLIB/KEYL6 * 4
*--------------------------------------------------------------------------------------------* 4
25=I *ISO-D 1 10 FLD22 4 2
26=I 11 13 FLD23 4 3
27=I 14 17 FLD24 4 4
28=I 18 22 FLD25 4 5
Line Number
Starts at 1 and increments by 1 for each source or generated
record. Use this number when debugging using statement
numbers.
Ruler Line
This line adjusts when indentation is specified.
Do Number
Identifies the level of the structured operations. This number
will not appear if indentation is requested.
Page Line
Shows the first 5 columns of the source record.
Source Id
Identifies the source (either /COPY or DDS) of the record.
For /COPY members, it can be used to obtain the external
member name from the /COPY member table.
Sequence Number
Shows the SEU sequence number of the record from a
member in a source physical file. Shows an incremental
number for records from a member in a physical file or
records generated from DDS.
| .2/ Compiler Options in Effect
| Identifies the compiler options in effect. Displayed when compile-option
| keywords are specified on the control specification.
.3/ File/Record Information
Identifies the externally described file and the records it contains.
.4/ DDS Information
Identifies from which externally described file the field information is
extracted. Shows the prefix value, if specified. Shows the format record
text if specified in the DDS.
.5/ Generated Specifications
Shows the specifications generated from the DDS, indicated by '='
beside the Line Number. Shows up to 50 characters of field text if it is
specified in the DDS.
.6/ /COPY Member Information
Identifies which /COPY member is used. Shows the member text, if any.
Shows the date and time of the last change to the member.
A d d i t i o n a l D i a g n o s t i c M e s s a g e s
* * * * * E N D O F A D D I T I O N A L D I A G N O S T I C M E S S A G E S * * * * *
O u t p u t B u f f e r P o s i t i o n s
Line Start End Field or Constant
Number Pos Pos
80 1 3 RPTNUM
81 4 103 RPTNAME
82 104 203 RPTADDR
83 204 209 AMOUNT
84 210 219 DUEDATE
* * * * * E N D O F O U T P U T B U F F E R P O S I T I O N * * * * *
/ C o p y M e m b e r s
Line Src RPG name <-------- External name -------> CCSID <- Last change ->
Number Id Library File Member Date Time
26 5 MYCPY MYLIB QRPGLESRC MYCPY 37 95/12/30 11:55:20
* * * * * E N D O F / C O P Y M E M B E R S * * * * *
Compile-Time Data
The Compile-Time Data section includes information on ALTSEQ or NLSS tables,
and on tables and arrays. In this example, there is an alternate collating sequence
and two arrays, as shown in Figure 214 on page 432.
27 ** 940609 001800
*--------------------------------------------------------------------*
* Alternate Collating Sequence Table Data: *
*--------------------------------------------------------------------*
31 ALTSEQ 1122ACAB4B7C36F83A657D73 940609 001900
*--------------------------------------------------------------------*
* Alternate Collating Sequence Table: *
* Number of characters with an altered sequence . . . . . . : 6 .1/ *
* .2/ 0_ 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_ 9_ A_ B_ C_ D_ E_ F_ *
* _0 . . . . . . . . . . . . . . . . _0 *
* _1 . 22 .3/. . . . . . . . . . . . . _1 *
* _2 . . . . . . . . . . . . . . . . _2 *
* _3 . . . . . . . . . . . . . . . . _3 *
* _4 . . . . . . . . . . . . . . . . _4 *
* _5 . . . . . . . . . . . . . . . . _5 *
* _6 . . . F8 . . . . . . . . . . . . _6 *
* _7 . . . . . . . . . . . . . . . . _7 *
* _8 . . . . . . . . . . . . . . . . _8 *
* _9 . . . . . . . . . . . . . . . . _9 *
* _A . . . 65 . . . . . . . . . . . . _A *
* _B . . . . 7C . . . . . . . . . . . _B *
* _C . . . . . . . . . . AB . . . . . _C *
* _D . . . . . . . 73 . . . . . . . . _D *
* _E . . . . . . . . . . . . . . . . _E *
* _F . . . . . . . . . . . . . . . . _F *
* 0_ 1_ 2_ 3_ 4_ 5_ 6_ 7_ 8_ 9_ A_ B_ C_ D_ E_ F_ *
*--------------------------------------------------------------------*
32 ** 000000 002000
*--------------------------------------------------------------------*
| * Array . . . : BLUE .4/ Alternating Array . . . . : GREEN *
*--------------------------------------------------------------------*
33 1234ZZ 000000 002100
34 ABCDYY 000000 002200
35 5432XX 000000 002300
36 EDCBWW 000000 002400
*RNF8042 00 37 Not enough source records provided to load array or table.
37 ** 940608 002500
*--------------------------------------------------------------------*
* Array . . . : RED *
*--------------------------------------------------------------------*
38 3861 940608 002600
39 TKJL 940608 002700
* * * * * E N D O F C O M P I L E T I M E D A T A * * * * *
K e y F i e l d I n f o r m a t i o n
* * * * * E N D O F K E Y F I E L D I N F O R M A T I O N * * * * *
Cross-Reference Table
The Cross-Reference table contains at least three lists:
¹ files and records
¹ global fields
¹ indicators
In addition, it contains the local fields that are used by each subprocedure. Use this
table to check where files, fields and indicators are used within the
module/program.
Note that the informational message RNF7031, which is issued when an identifier is
not referenced, will only appear in the cross-reference section of the listing and in
the message summary. It does not appear in the source section of the listing.
Names longer than 122 characters, will appear in the cross-reference section of the
listing split across multiple lines. The entire name will be printed with the characters
'...' at the end of the lines. If the final portion of the name is longer than 17 charac-
ters, the attributes and line numbers will be listed starting on the following line.
Figure 216 on page 434 shows an example for the module TRANSRPT, which has
two subprocedures.
The statically bound procedures portion contains the procedure name, and the ref-
erences to the name on a CALLB operation or %PADDR built-in function, or the
name of a prototyped bound procedure called by CALLP or within an expression.
The imported fields and exported fields portions contain the field name, the dimen-
sion if it is an array, the field attribute and its definition reference. Figure 217 on
page 435 shows an example.
Message Summary
The message summary contains totals by severity of the errors that occurred. If
OPTION(*SECLVL) is specified, it also provides second-level message text.
Figure 218 shows an example.
M e s s a g e S u m m a r y
* * * * * E N D O F M E S S A G E S U M M A R Y * * * * *
Final Summary
The final summary section provides final message statistics and source statistics. It
also specifies the status of the compilation. Figure 219 on page 436 shows an
example.
Message Totals:
Information (00) . . . . . . . : 17
Warning (10) . . . . . . . : 0
Error (20) . . . . . . . : 0
Severe Error (30+) . . . . . . : 0
--------------------------------- -------
Total . . . . . . . . . . . . . : 17
Source Totals:
Records . . . . . . . . . . . . : 50
Specifications . . . . . . . . : 39
Data records . . . . . . . . . : 7
Comments . . . . . . . . . . . : 0
* * * * * E N D O F F I N A L S U M M A R Y * * * * *
Program MYSRC placed in library MYLIB. 00 highest severity. Created on 95/12/30 at 17:44:55.
* * * * * E N D O F C O M P I L A T I O N * * * * *
The code generation error section will appear only if errors occur while the compiler
is generating code for the module object. Generally, this section will not appear.
The binding errors section will appear whenever there are messages arising during
the binding phase of the CRTBNDRPG command. A common error is the failure to
specify the location of all the external procedures and fields referenced in the
source at the time the CRTBNDRPG command was issued.
– Disk protection (device parity, mirrored, and ¹ DB2 for AS/400 SQL Programming, SC41-5611,
checksum) provides information about how to use DB2 for
AS/400 Query Manager and SQL Development kit
Provides performance information about backup licensed program. Shows how to access data in a
media and save/restore operations. Also includes database library and prepare, run, and test an appli-
advanced backup and recovery topics, such as cation program that contains embedded SQL state-
using save-while-active support, saving and
Bibliography 439
440 ILE RPG for AS/400 Programmer's Guide
Index
activation group (continued)
Special Characters deleting 112
/COPY statement identifying 82, 110
conversion problems 389, 398 managing 109
COPY debug view 168 named 82
in a conversion report 394 deleting 110
table in compiler listing 431 specifying 110
*CANCL 238 *NEW 82
*DETC 238 ending 110
*DETL 238 specifying 110
*GETIN 238 OPM default 111
*JOBRUN QILE 82, 110
language identifier, LANGID 414 role in exception handling 218
sort sequence, SRTSEQ 414 activation, program 109
*OFL 238 Add Reply List Entry (ADDRPLYE) command
*PSSR adding to system reply list 108
See program exception/error subroutine adding objects to a debug session 172
*TOTC 238 additional diagnostic messages section of compiler
*TOTL 238 listing 430
%ADDR (Get Address of Variable) ADDRPLYE command
omitted parameters 142 See Add Reply List Entry (ADDRPLYE) command
%ADDR debug built-in 206 ADTS 13
%INDEX debug built-in 206 ALLOC (allocate storage) operation code 113
%PARMS (Return Number of Parameters) allocating storage for a run-time array 120
checking for number of parameters 143 alternate collating sequence
%SUBSTR debug built-in debug considerations 184
changing values 208 ALWNULL parameter
examples 207 See also null value support
CRTBNDRPG command 58, 417
CRTRPGMOD command 74
Numerics analyzing your conversion 393
01-99 indicators
API
displaying while debugging 204
See application programming interface (API)
in a sample formatted dump 257
application design
See creating programs
A Application Development Manager 13
Application Development ToolSet 13
abnormal program/procedure end 155
access path Application Dictionary Services 14
example of 288 application programming interface (API)
for externally described DISK file 282 calling non-bindable 130
for indexed file 288 QMHSNDPM 374
ACTGRP parameter Retrieve Message (QMHRTVM) API 158
CRTBNDRPG command 58, 418 area parameter for SPECIAL PLIST 328
CRTPGM command 82 array
specifying 110 conversion problems 402
using 60 displaying while debugging 202
activation group loading 403
*NEW 155 prerun-time arrays 403
*CALLER 111 arrival sequence access path 282
running in OPM default 111 ATTR debug command
specifying 111 definition 164
definition 109 example 210
Index 443
CL commands (continued) compiling
WRKRPLYE 109 creating modules 73
clear command 334 differences between ILE RPG and OPM
CLEAR debug command RPG/400 373
definition 164 in ILE 17
removing all 187 using CRTBNDRPG command 57
using 179, 182, 186 compressing an object 88
code conversion constraints 398 condition handler 217
code generation errors in compiler listing 436 example 239
collating sequence overview 239
See alternate collating sequence percolate an exception 240
combined file 341 recursive calls 239
command attention (CA) keys 332 registering 239
command definition 108 conditional breakpoint
command function (CF) keys 332 definition 178
COMMIT (commit) operation code setting 182
commitment control 309 setting and removing for job 181
system considerations 309 setting and removing for thread 187
with multiple devices 309 using statement numbers 185
commitment control 307 conditional commitment control, specifying 311
COMMIT operation 309 conditioning output
conditional 311 overflow indicators 317
example 310 consecutive processing 292
in program cycle 312 control boundary 218
locks 308 control break
scoping 308 See also control field
specifying files 309 example 319
starting and ending 307 control field
communication See control break
accessing other programs and systems 331 control group
compatibility differences between OPM RPG/400 and See control break
ILE RPG 373 control language (CL) program
compilation errors, correcting 66 See also ILE CL
compile time array or table as module in ILE program 27
See also array commands used with ILE RPG 12
section in compiler listing 431 commonly used commands 12
compiler directives in OPM-compatible application 23
changing a listing heading 64 control specification keywords
compiler listing compile-option keywords
additional diagnostic messages 68 compiler listing example 424
browsing using SEU 68 control specifications
coordinating listing options with debug view conversion considerations 382
options 69 example 7
correcting compilation errors 66 general description 3
correcting run-time errors 68 control-record format, subfile 335
default information 63 Conversion Aid
in-line diagnostic messages 67 See converting to RPG IV
indenting structured operations 65 conversion reports
obtaining 63 obtaining 389
reading 423 sections of 394
sample listing 424 using 394
sections of 63, 424 conversion, analyzing 393
specifying the format of 64 converting to RPG IV
using 63 analyzing your conversion 393
using as documentation 69 constraints 382
conversion problems 398
Index 445
CVTOPT parameter DDM
CRTBNDRPG command 58, 413 See distributed data management (DDM)
CRTRPGMOD command 74 DEALLOC (free storage) operation code 113
CVTRPGSRC (Convert RPG Source) command debug commands
default parameter values 383 ATTR 210
example 388 CLEAR 179
parameter description 384 DISPLAY 175
syntax diagram 383 EQUATE 210
using the command defaults 387 equating with a name while debugging 210
CVTRPT parameter 386, 389, 394 EVAL 199, 208
cycle-free module 75 general discussion 164
cycle, program STEP 194, 195
commitment control 312 STEP INTO 196
fetch overflow logic 320 STEP OVER 195
general description 4 WATCH 188
last cycle 5 debug data
creating 166
effect on object size 166
D none 166
data areas removing from a module 88
RETURNCODE 70 debug view
data file, converting source from 390 changing while debugging 176
data management feedback area COPY source 168
See file information data structure default 169
data management operations 271 definition 166
data structures listing 168
multiple-occurrence root source 167
displaying while debugging 203 statement 169
subfields debugging
conversion problems 402 adding an object to a session 172
displaying while debugging 203 built-in functions
using EVAL debug command 203 %ADDR 206
database data %INDEX 206
updating while debugging 171 %SUBSTR 206
database file %VARS 206
See also DISK file changing values using %SUBSTR 208
data file 281 examples 207
field level description 281 general discussion 206
general discussion 281 changing field values 208
physical and logical files 281 changing modules while debugging 175
record level description 281 coordinating with listing options 69
source member 281 creating a program for debugging 59
DB2 for AS/400 SQL differences between ILE RPG and OPM
entering SQL statements 55 RPG/400 374
DBCS displaying attributes of 210
See also graphic data type displaying data addressed by pointers 206
in RPG IV character fields 377 displaying data and expressions 199
NLSS debug considerations 184 displaying fields as hexadecimal values 205
DBGVIEW parameter displaying fields in character format 205
coordinating with listing options 69 displaying indicators 204
CRTBNDRPG command 58, 411 displaying multiple-occurrence data structures 203
CRTRPGMOD command 74 displaying the contents of a table 202
preparing a program for debugging 166 displaying the contents of an array 202
using 59 general discussion 163
values for viewing source 174 National Language Support 211
NLSS considerations 184
Index 447
Display Module Source (DSPMODSRC) ending commitment control 307
command 171, 172, 173, 175 ENDSR (end of subroutine) operation code
Display Program (DSPPGM) command specifying a return point 238
determining optimization level 88 ENTMOD parameter 82
Display Program References (DSPPGMREF) entry module 28, 82
command 150 See also program entry procedure (PEP)
Display Service Program (DSPSRVPGM) *ENTRY PLIST 153
command 91 environment
displaying attributes of a field 210 See Integrated Language Environment (ILE)
displaying data and expressions while debugging 199 EQUATE debug command
distributed data management (DDM) definition 164
files 313 example 210
documentation of programs 69 using 210
double byte character set equating a name with a field, expression, or
See also graphic data type command 210
in RPG IV character fields 377 error handling
NLSS debug considerations 184 See exception/error handling
DSPMOD command error indicators
See Display Module (DSPMOD) command specifying 227
DSPMODSRC command error subroutines
See Display Module Source (DSPMODSRC) avoiding a loop 236
command for file errors 229
DSPPGM command program 233
See Display Program (DSPPGM) command using 228
DSPPGMREF command errors
See Display Program References (DSPPGMREF) See also exception
command correcting compilation 66
DSPSRVPGM command correcting run-time 68
See Display Service Program (DSPSRVPGM) file 220
command program 220
DUMP (program dump) operation code escape messages
obtaining a formatted dump 251 definition 218
using 251 unhandled 224
dump, formatted 251 EVAL debug command
dynamic array changing values 208
allocating storage during run-time 120 contents of a table 202
dynamic calls 19, 130 contents of an array 202
See also program/procedure call definition 164
dynamic storage 113 displaying data structures 203
example 200, 208
in character format 205
E indicators 204
edit source (STRSEU) command 52 rules for assigning values 208
eliminating errors in a program 163 using 199
ENBPFRCOL parameter event file for CODE/400 411
CRTBNDRPG command 58, 418 examples
CRTRPGMOD command 74 compiling
End Debug (ENDDBG) command 169 binding multiple modules 84
ending a program or procedure OPM-compatible program 61
abnormal end 155 program for source debugging 59
after system call 109 program with static binding 60
normal end 154 sample binder listing 100
return overview 153 service program 94
returning without ending 155 converting to RPG IV
using bindable APIs 156 all members in a file 388
performing a trial conversion 388
sample conversion 390
Index 449
field file information data structure (continued)
changing the value while debugging 208 using in an error subroutine 229
displaying attributes of while debugging 210 file locking 275
displaying while debugging file operations
as hexadecimal values 205 allowed with DISK file 306
in character format 205 allowed with PRINTER file 316
using EVAL 199 allowed with sequential file 326
equating with a name while debugging 210 allowed with SPECIAL file 328
maintaining current values while debugging 164 allowed with WORKSTN file 341
field-reference file, example of 283 file overrides 267
file example 274
device dependence 261 general discussion 273, 304
device independence 261 indicated in compiler listing 425
differences between ILE RPG and OPM file record length, conversion considerations 380
RPG/400 375 file sharing 277
DISK 281 final summary in compiler listing 435
externally described 261 FIND debug command 165
externally described disk 282 FIXNBR parameter
general considerations 261 CRTBNDRPG command 58, 416
indexed 288 CRTRPGMOD command 74
locking 275 flowchart
name fetch-overflow logic 320
externally described 261 format name 339
override 267 format of compiler listing, specifying 64
program-described 271 formatted dump 251
naming conventions 263 FREE (deactivate a program) operation code 397
open options 277 Free Storage (CEEFRST) bindable API 20
override 267 freeing resources of ILE programs 112
PRINTER 316 FROMFILE parameter 384
See also PRINTER file FROMMBR parameter 384, 388
processing charts function check
sequential file 326 definition 218
SPECIAL file 328 unhandled 225
WORKSTN file 342 function keys
program described 261, 271 indicators 334
redirection 262 with WORKSTN file 334
SEQ 290, 326
See also SEQ file
sharing 277 G
valid keys 285 GDDM 158
WORKSTN 331 generating a program
See also WORKSTN file See compiling
file description specifications See control specifications
commitment control 309 GENLVL parameter
for externally described files 265 CRTBNDRPG command 58, 409
general description 3 CRTRPGMOD command 74
file exception/error subroutine (INFSR) Get Descriptive Information About a String Argument
description 229 (CEESGI) 141
example 230 Get Heap Storage (CEEGTST) bindable API 20, 120
specifications for 229 graphic data type
file exception/errors NLSS debug considerations 184
definition 220 rules for assigning values using EVAL 208
example 230 graphic support 158
using an INFSR subroutine 229 Graphical Data Display Manager(GDDM) 158
file information data structure
example 230
Index 451
indicators (continued) keywords
using 5 DDS 281
INFDS EXPORT 84
See file information data structure for continuation line 281
INFSR CLEAR 334
See file exception/error subroutine (INFSR) HELP 334
input HOME 334
file 341 PRINT 334
input record ROLLDOWN 334
unblocking 287 ROLLUP 334
input specifications for display device file
See also indicators CLEAR 334
general description 3 HELP 334
inquiry messages HOME 334
list of 108 PRINT 334
replying to 108 ROLLDOWN 334
inserting specification templates 390 ROLLUP 334
INSRTPL parameter 386, 390 NOOPT 87, 226
integer format *OMIT 142
TRUNCNBR parameter 416
Integrated Language Environment (ILE)
effect on L
OPM-compatible program 24 LANGID parameter
program using CRTBNDRPG 26 CRTBNDRPG command 58, 414
ending an ILE program 109 CRTRPGMOD command 74
family of ILE compilers 17 languages, ILE 17
interlanguage calls 149 last record (LR) indicator
internal structure of program 81 used to end a program/procedure 154, 155
overview 17 length of record in a file, conversion
program call 19 considerations 380
program creation 17 level checking 270
program creation strategies 23, 25, 27 library, creating 51
program management 19 limits records 283
interlanguage calls 149 listing view, creating 168
Intersystem Communications Function (ICF) 331 listing, binder
as maintenance resource 86
basic 100
J creating 85
job attributes determining exports in service program 91
See *JOBRUN sections of 85
listing, compiler
additional diagnostic messages 68
K browsing using SEU 68
key coordinating listing options with debug view
See also search argument options 69
composite 286 correcting compilation errors 66
for a record or a file 285 correcting run-time errors 68
partial 286 default information 63
key field information in compiler listing 433 in-line diagnostic messages 67
keyed processing indenting structured operations 65
access path 282 obtaining 63
indexed file 288 reading 423
record-address limits file 290 sample listing 424
sequential-within-limits 300 sections of 63, 424
keyed-sequence access path 282 specifying the format of 64
using 63
Index 453
OUTPUT parameter
O CRTBNDRPG command 58, 412
observability 88 CRTRPGMOD command 74
obtaining a compiler listing 63 using 63
obtaining conversion reports 389 output record
OFL 238 blocking 287
*OMIT 141, 142 output specifications
omitted parameters 141 example 8
*OMIT 142 general description 3
one-step process of program creation 57 program-described WORKSTN file 339
online information with external descriptions 269
for create commands 408 output spooling 279
for ILE source debugger 165 overflow
open data path indicators 317
sharing 277 page 316
operation codes 341 overflow indicators
allowed with DISK file 306 conditioning output 317
allowed with PRINTER file 316 examples 319, 320
allowed with sequential file 326 fetch-overflow logic 320
allowed with SPECIAL file 328 general description 317
allowing 'E' extender 228 presence or absence of 317
allowing error indicators 228 relation to program cycle 320
general discussion 6 setting of 320
operational descriptors with PRINTER file 316
definition 140 overrides, file 267
example 94 example 274
OPM compatibility, maintaining 61, 111 general discussion 273, 304
OPM default activation group 23, 31 indicated in compiler listing 425
running in 111 overriding external description 267
optimization
definition 87
effect on fields when debugging 164 P
exception handling considerations 226 page headings 64
level of page number, in PRINTER file 316
changing a object's 87 page overflow, in PRINTER file 316
checking 88 parameter descriptions
OPTIMIZE parameter CRTBNDRPG command 408
CRTBNDRPG command 58, 412 CRTRPGMOD command 421
CRTRPGMOD command 74 CVTRPGSRC command 384
OPTION parameter parameter list
coordinating listing and debug view options 168 See also PARM (identify parmeters) operation code
coordinating with debug view options 69 created by PARM 153
CRTBNDRPG command 58, 410 identifying 133
CRTRPGMOD command 74 rules for specifying 153
using 64, 69 parameter table
OPTIONS keyword CRTBNDRPG command 58
*NOPASS 142 CRTRPGMOD command 74
*OMIT 142 CVTRPGSRC command 383
order of evaluation parameters
on prototyped call 148 checking number passed 143
output match data type requirements 140
specifications omitted 141
program-described WORKSTN file 339 operational descriptors 140
output buffer positions, in compiler listing 430 passing 133
output file 341 passing using the CL CALL command 103
specifying 151
Index 455
program (continued) program status data structure (continued)
program entry procedure 81 using in an error subroutine 233
reducing size 88 program-described file
related CL commands 85 as DISK file 288
removing observability 88 as WORKSTN file 338, 339, 340
returning from 153 definition 263
returning without ending 155 physical and logical files 281
running 103 valid search arguments 288
running from a menu-driven application 106 program/procedure call
running in the OPM default activation group 111 abnormal program/procedure end 155
running using a user-created command 108 call stack 131
setting watch conditions 188 calling bindable APIs 157
single-language 28 calling graphics 158
effect of ILE 26 calling procedures 130
stepping into 196 calling programs 130
stepping over 195 calling special routines 158
stepping through 194 fixed-form call 150
updating 87 free-form call 135, 136
viewing source while debugging 174 interlanguage calls 149
program activation 109 normal program/procedure end 154
program creation overview 129
coding considerations 45, 46 parameter passing methods 137
examples of 59, 60, 61, 84 recursive calls 132
OPM-compatible returning from a called program or procedure 153
creating 23 returning values 136
strategy to avoid 31 returning without ending 155
strategies for 23 static calls 130
CRTPGM command 82 using the CALL operation 150
ILE application using CRTRPGMOD 27 using the CALLB operation 150
OPM-compatible 23 within ILE 19
strategy to avoid 31 program/procedure end
using CRTBNDRPG 25 abnormal end 155
using CRTRPGMOD and CRTPGM 73 after system call 109
using the one-step process 57 normal end 154
program cycle return overview 153
commitment control 312 returning without ending 155
fetch overflow logic 320 using bindable APIs 156
general description 4 programming tips
last cycle 5 creating NOMAIN module 92
program entry procedure (PEP) setting subprocedure breakpoints 196
and the call stack 131 prologue section of compiler listing 424
definition 81 prototype
determining 82 description 34
program exception/error subroutine using 135
description 233 prototyped call
example 233 order of evaluation of parameters 148
program exception/errors prototyped program or procedure
avoiding a loop 236 prototyped call 34
definition 220 PRTCTL (printer control)
example 233, 239 example 324
using a *PSSR subroutine 233 general information 323
program management 19
program name
*FROMMBR parameter 386 Q
program status data structure QUAL debug command
example 151, 233 definition 164
Index 457
RETURN (return to caller) operation code (continued) SECLVL parameter 386
role in normal end 154 SEQ file
return (RT) indicator example 327
used to end a program/procedure 154, 155 file operation codes allowed 326
return points, specifying in ENDSR 238 general description 326
return status parameter 328 processing chart 326
return value restrictions 326
returning using expressions 136 variable-length 326
RETURNCODE data area 70 sequence checking
returning from a called main procedure 153 on input specifications 271
returning from a called procedure 153 sequential file 290
returning from a main procedure 153 sequential-by-key processing
returning from a subprocedure 156 examples 293
returning using ILE bindable APIs 156 general discussion 293
returning without ending 155 sequential-only processing 292, 293
rolldown command key 334 sequential-within-limits processing
rollup command key 334 examples 301
root source view, creating 167 general discussion 300
RPG IV service program
See also ILE RPG adding to a debug session 172
behavioral differences between RPG III 373 binder language 97
converting to 23, 25, 379 binding with CRTBNDRPG 60
overview 3 changing 93
unsupported RPG III features 398 creating 91
RT (return) indicator example 94
See return (RT) indicator in advanced application 30
run-time array reasons for using 91
allocating storage during run-time 120 reclaiming resources 112
run-time errors, correcting with a compiler listing 68 related CL commands 93
run-time inquiry messages, replying to 108 sample binder listing 100
run-time job attributes strategies for creating 92
See *JOBRUN updating 100
run-time storage, managing 113 service program creation
running a program about 91
See also program/procedure call strategies 92
differences between ILE RPG and OPM SET debug command
RPG/400 373 definition 164
from a menu-driven application 106 setting breakpoints
in the OPM default activation group 111 about 178
overview 103 conditional job breakpoints 181
using a user-created command 108 conditional thread breakpoints 187
using the CL CALL command 103 example 179, 182
unconditional job breakpoints 179
unconditional thread breakpoints 180
S using statement numbers 185
sample programs setting debug options 171
See examples SEU
scope See source entry utility (SEU)
of files 80 sharing an open data path for a file 277
screen design aid (SDA) 106 sort sequence
search argument affect of SRTSEQ parameter 279
externally described file ALTSEQ table in compiler listing 431
description 285 debug considerations 184
referencing a partial key 286 source debugging
valid 286 adding an object to a session 172
program-described file 288 built-in functions
%ADDR 206
Index 459
stepping while debugging summary tables (continued)
into a program or procedure 196 file operation codes allowed with (continued)
over a program or procedure 195 sequential 326
through a program 194 SPECIAL 328
storage management WORKSTN 341
allocating during run-time 120 sequential file processing 326
dynamic storage 113 SPECIAL file processing 328
managing run-time 113 syntax diagrams
strategies for creating ILE programs 23 CRTBNDRPG command 406
STRDBG command CRTRPGMOD command 419
See Start Debug (STRDBG) command CVTRPGSRC command 383
STRSEU (edit source) command 52 interpreting 405
structured operations system functions
indenting 65 spooling 278
Structured Query Language (SQL) system reply list
See DB2 for AS/400 SQL adding to 108
subfields changing 109
for file information data structure 253, 255
for program status data structure 252
for PRTCTL 323 T
subfiles table
control-record format 335 See also array
descriptions 335 displaying while debugging 202
examples 337 table of parameters
file operation codes allowed with 336 CRTBNDRPG command 58
general description 335, 336 CRTRPGMOD command 74
record format 335 CVTRPGSRC command 383
uses of 337 tape file 290
subprocedures TBREAK debug command
coding considerations 46 definition 165
debugging 198 using 180, 187
example 9 templates, inserting specification 390
information in compiler listing 434 test library, using 171
local data in dump listing 258 testing breakpoints 178
logic flow 5 TEXT parameter
overview 33 CRTBNDRPG command 58, 409
returning from 156 CRTRPGMOD command 74
scope of files 80 TGTRLS parameter
stepping into 196 CRTBNDRPG command 58, 416
stepping over 195 CRTRPGMOD command 74
SUBR23R3 (message retrieval) 158 THREAD debug command
SUBR40R3 (manipulating Double Byte Characters vari- definition 165
ables) 158 using 180
SUBR41R3 (manipulating Double Byte Characters vari- threaded applications
ables) 158 debugging 178
subroutines overview 21
avoiding a loop 236 tips
calling SUBR routines 158 See programming tips
error 228 TOFILE parameter 385, 388
file error (INFSR) 229 TOMBR parameter 386, 388
program error (*PSSR) 233 TOTC 238
substring of character or graphic literal TOTL 238
ILE debug built-in %SUBSTR 207 trial conversion, performing 388
summary tables TRUNCNBR parameter
file operation codes allowed with CRTBNDRPG command 58, 416
DISK 304 CRTRPGMOD command 74
PRINTER 316
Index 461
ÉÂÔÙ
Printed in U.S.A.
99H3717
SC09-2507-00