RPG Programmers Guide
RPG Programmers Guide
ERserver
iSeries
WebSphere®® Development Studio:
ILE RPG Programmer’s Guide
Version 5
SC09-2507-05
ERserver
iSeries
WebSphere®® Development Studio:
ILE RPG Programmer’s Guide
Version 5
SC09-2507-05
Note!
Before using this information and the product it supports, be sure to read the general information
under “Notices” on page 481.
Contents v
Methods for Processing Disk Files . . . . . . 326 File Maintenance . . . . . . . . . . . . 379
Consecutive Processing . . . . . . . . . 326 CUSMSTL1: DDS for a Logical File . . . . . 380
Sequential-by-Key Processing . . . . . . . 327 MNTMENU: DDS for a Display Device File . . 381
Random-by-Key Processing . . . . . . . . 332 CUSMNT: RPG Source . . . . . . . . . 383
Sequential-within-Limits Processing . . . . . 334 Search by Zip Code . . . . . . . . . . . 390
Relative-Record-Number Processing . . . . . 336 CUSMSTL2: DDS for a Logical File . . . . . 391
Valid File Operations . . . . . . . . . . . 337 SZIPMENU: DDS for a Display Device File . . 392
Using Commitment Control . . . . . . . . 339 SCHZIP: RPG Source . . . . . . . . . . 394
Starting and Ending Commitment Control . . . 340 Search and Inquiry by Name . . . . . . . . 398
Specifying Files for Commitment Control . . . 342 CUSMSTL3: DDS for a Logical File . . . . . 399
Using the COMMIT Operation . . . . . . 342 SNAMMENU: DDS for a Display Device File 400
Specifying Conditional Commitment Control 344 SCHNAM: RPG Source . . . . . . . . . 403
Commitment Control in the Program Cycle . . 344
DDM Files . . . . . . . . . . . . . . 345
Part 5. Appendixes . . . . . . . . 409
Using Pre-V3R1 DDM Files . . . . . . . . 345
Contents vii
viii ILE RPG Programmer’s Guide
About This Guide
This guide provides information that shows how to use the ILE RPG compiler (ILE
RPG) in the Integrated Language Environment. ILE RPG is an implementation of
the RPG IV language on the iSeries server with the Operating System/400
(OS/400) operating system. Use this guide to create and run ILE applications from
RPG IV source.
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 WebSphere Development Studio: ILE
RPG Reference, SC09-2508-04.
The iSeries Information Center contains advisors and important topics such as CL
commands, system application programming interfaces (APIs), logical partitions,
clustering, Java , TCP/IP, Web serving, and secured networks. It also includes links
to related IBM Redbooks and Internet links to other IBM Web sites such as the
Technical Studio and the IBM home page.
The manuals that are most relevant to the ILE RPG compiler are listed in the
“Bibliography” on page 485.
# If you are mailing a readers’ comment form from a country other than the
United States, you can give the form to the local IBM branch office or IBM
representative for postage-paid mailing.
v If you prefer to send comments by FAX, use the following number:
1–845–491–7727
v If you prefer to send comments electronically, use one of these e-mail addresses:
– Comments on books:
[email protected]
– Comments on the Information Center:
[email protected]
Be sure to include the following:
v The name of the book.
v The publication number of the book.
v The page number or topic to which your comment applies.
What's New
There have been several releases of RPG IV since the first V3R1 release. The
following is a list of enhancements made for each release since V3R1 up to the
current release:
v “What's New This Release?” on page xi
v “What's New in V5R2?” on page xv
v “What's New in V5R1?” on page xviii
v “What's New in V4R4?” on page xxiii
v “What's New in V4R2?” on page xxvii
v “What's New in V3R7?” on page xxxi
v “What's New in V3R6/V3R2?” on page xxxv
| Note: The information for this product is up-to-date with the V5R3 release of RPG
| IV. If you are using a previous release of the compiler, you will need to
| determine what functions are supported on your system. For example, if
| you are using a V5R1 system, the functions new to the V5R3 release will not
| be supported.
Note: Many of the examples included in this guide have been modified to
″free-form″, rather than ″traditional″ coding style. These changed examples
have not been marked. See WebSphere Development Studio: ILE RPG Reference
for detailed explanation of the differences between the two coding styles.
| Example:
| D numDdMmYy s 6p 0
| D date s d datfmt(*jul)
| date = D’2003-08-21’;
| numDdMmYy = %dec(date : *dmy);
| // now numDdMmYy = 210803
| v Control specification CCSID(*CHAR : *JOBRUN) for correct conversion of
| character data at runtime:
| The Control specification CCSID keyword is enhanced to allow a first parameter
| of *CHAR. When the first parameter is *CHAR, the second parameter must be
| *JOBRUN. CCSID(*CHAR : *JOBRUN) controls the way character data is
| converted to UCS-2 at runtime. When CCSID(*CHAR:*JOBRUN) is specified,
| character data will be assumed to be in the job CCSID; when CCSID(*CHAR :
| *JOBRUN) is not specified, character data will be assumed to be in the
| mixed-byte CCSID related to the job CCSID.
| v Second parameter for %TRIM, %TRIMR and %TRIML indicating what
| characters to trim:
| %TRIM is enhanced to allow an optional second parameter giving the list of
| characters to be trimmed.
| Example:
| trimchars = ’*-.’;
| data = ’***a-b-c-.’
| result = %trim(data : trimchars);
| // now result = ’a-b-c’. All * - and . were trimmed from the ends of the data
| v New prototype option OPTIONS(*TRIM) to pass a trimmed parameter:
| When OPTIONS(*TRIM) is specified on a prototyped parameter, the data that is
| passed be trimmed of leading and trailing blanks. OPTIONS(*TRIM) is valid for
| character, UCS-2 and graphic parameters defined with CONST or VALUE. It is
| also valid for pointer parameters defined with OPTIONS(*STRING). With
| OPTIONS(*STRING : *TRIM), the passed data will be trimmed even if a pointer
| is passed on the call.
| Example:
| D proc pr
| D parm1 5a const options(*trim)
| D parm2 5a const options(*trim : *rightadj)
| D parm3 5a const varying options(*trim)
| D parm4 * value options(*string : *trim)
| D parm5 * value options(*string : *trim)
| D ptr s *
| D data s 10a
| D fld1 s 5a
|
| /free
| data = ’ rst ’ + x’00’;
| ptr = %addr(data);
|
| proc (’ xyz ’ : ’ @#$ ’ : ’ 123 ’ : ’ abc ’ : ptr);
| // the called procedure receives the following parameters
| // parm1 = ’xyz ’
| // parm2 = ’ @#$’
| // parm3 = ’123’
| // parm4 = a pointer to ’abc.’ (where . is x’00’)
| // parm5 = a pointer to ’rst.’ (where . is x’00’)
| v Support for 63 digit packed and zoned decimal values
| Packed and zoned data can be defined with up to 63 digits and 63 decimal
| positions. The previous limit was 31 digits.
| v Relaxation of the rules for using a result data structure for I/O to
| externally-described files and record formats
| – The result data structure for I/O to a record format may be an
| externally-described data structure.
| – A data structure may be specified in the result field for I/O to an
| externally-described file name for operation codes CHAIN, READ, READE,
| READP and READPE.
| Examples:
| 1. The following program writes to a record format using from an
| externally-described data structure.
| Foutfile o e k disk
| D outrecDs e ds extname(outfile) prefix(O_)
| /free
| O_FLD1 = ’ABCDE’;
| O_FLD2 = 7;
| write outrec outrecDs;
| *inlr = *on;
| /end-free
| 2. The following program reads from a multi-format logical file into data
| structure INPUT which contains two overlapping subfields holding the fields
| of the respective record formats.
| Flog if e k disk infds(infds)
| D infds ds
| D recname 261 270
| D input ds qualified
| D rec1 likerec(rec1) overlay(input)
| D rec2 likerec(rec2) overlay(input)
| /free
| read log input;
| dow not %eof(log);
| dsply recname;
| if recname = ’REC1’;
| // handle rec1
| elseif recname = ’REC2’;
| // handle rec2
| endif;
| read log input;
| enddo;
| *inlr = *on;
| /end-free
| v Support for new environment variables for use with RPG programs calling
| Java methods
| – QIBM_RPG_JAVA_PROPERTIES allows RPG users to explicitly set the java
| properties used to start the JVM
| This environment variable must be set before any RPG program calls a Java
| method in a job.
| This environment variable has contains Java options, separated and
| terminated by some character that does not appear in any of the option
| strings. Semicolon is usually a good choice.
| Examples:
| 1. Specifying only one option: If the system’s default JDK is 1.3, and you
| want your RPG programs to use JDK 1.4, set environment variable
| QIBM_RPG_JAVA_PROPERTIES to
| ’-Djava.version=1.4;’
| Note that even with just one option, a terminating character is required. This
| example uses the semicolon.
| 2. Specifying more than one option: If you also want to set the os400.stdout
| option to a different value than the default, you could set the environment
| variable to the following value:
| ’-Djava.version=1.4!-Dos400.stdout=file:mystdout.txt!’
# In addition, data structures can be defined the same as a record format, using
# the new LIKEREC keyword.
# v Enhanced externally-described data structures
# Externally-described data structures can hold the programmer’s choice of input,
# output, both, key or all fields. Currently, externally-described data structures can
# only hold input fields.
# v Enhancments to keyed I/O
# Programmers can specify search arguments in keyed Input/Output operations in
# /FREE calculations in two new ways:
# 1. By specifying the search arguments (which can be expressions) in a list.
# 2. By specifying a data structure which contains the search arguments.
# Examples: D custkeyDS e ds extname(custfile:*key)
# /free
# CHAIN (keyA : keyB : key3) custrec;
# CHAIN %KDS(custkeyDS) custrec;
# v Data-structure result for externally-described files
# A data structure can be specified in the result field when using I/O operations
# for externally-described files. This was available only for program-described files
# prior to V5R2. Using a data structure can improve performance if there are
# many fields in the file.
# v UPDATE operation to update only selected fields
# A list of fields to be updated can be specified with an UPDATE operation. Tthis
# could only be done by using exception output prior to V5R2.
# Example: update record %fields(salary:status).
# v 31 digit support
# Supports packed and zoned numeric data with up to 31 digits and decimal
# places. This is the maximum length supported by DDS. Only 30 digits and
# decimal places were supported prior to V5R2.
# v Performance option for FEOD
# The FEOD operation is enhanced by supporting an extender N which indicates
# that the operation should simply write out the blocked buffers locally, without
# forcing a costly write to disk.
# v Enhanced data area access
# The DTAARA keyword is enhanced to allow the name and library of the data
# area to be determined at runtime
# v New assignment operators
# The new assignment operators +=, -=, *=, /=, **= allow a variable to be modified
# based on its old value in a more concise manner.
# Example: totals(current_customer) += count;
The major enhancements to RPG IV since V4R4 are easier interfacing with Java,
new built-in functions, free form calculation specifications, control of which file is
opened, qualified subfield names, and enhanced error handling.
Other enhancements have been made to this release as well. These include:
v You can specify parentheses on a procedure call that has no parameters.
v You can specify that a procedure uses ILE C or ILE CL calling conventions, on
the EXTPROC definition specification keyword.
v The following /DEFINE names are predefined: *VnRnMn, *ILERPG,
*CRTBNDRPG, and *CRTRPGMOD.
v The search string in a %SCAN operation can now be longer than string being
searched. (The string will not be found, but this will no longer generate an error
condition.)
v The parameter to the DIM, OCCURS, and PERRCD keywords no longer needs
to be previously defined.
v The %PADDR built-in function can now take either a prototype name or an
entry point name as its argument.
v A new operation code, ELSEIF, combines the ELSE and IF operation codes
without requiring an additional ENDIF.
v The DUMP operation code now supports the A extender, which means that a
dump is always produced - even if DEBUG(*NO) was specified.
The following tables summarize the changed and new language elements, based
on the part of the language affected.
Table 5. Changed Language Elements Since V4R4
Language Unit Element Description
Built-in functions %CHAR(expression{:format}) The optional second parameter specifies the
desired format for a date, time, or timestamp. The
result uses the format and separators of the
specified format, not the format and separators of
the input.
%PADDR(prototype-name) This function can now take either a prototype
name or an entry point name as its argument.
Definition specification EXTPROC(*JAVA:class-name:proc- Specifies that a Java method is called.
keywords name)
EXTPROC(*CL:proc-name) Specifies a procedure that uses ILE CL
conventions for return values.
EXTPROC(*CWIDEN:proc-name) Specifies a procedure that uses ILE C conventions
with parameter widening.
EXTPROC(*CNOWIDEN:proc-name) Specifies a procedure that uses ILE C conventions
without parameter widening.
INZ(*LIKEDS) Specifies that a data structure defined with the
LIKEDS keyword inherits the initialization from
its parent data structure.
LIKE(object-name) Specifies that an object has the same class as
another object.
PREFIX(character-literal{:number}) Prefixes the subfields with the specified character
literal, optionally replacing the specified number
of characters.
File specification OFLIND(name) This keyword can now take any named indicator
keywords as a parameter.
PREFIX(character-literal{:number}) Prefixes the subfields with the specified character
literal, optionally replacing the specified number
of characters.
Operation codes DUMP (A) This operation code can now take the A extender,
which causes a dump to be produced even if
DEBUG(*NO) was specified.
– Support for conversions between UCS-2 fields or graphic fields with different
Coded Character Set Identifiers (CCSIDs) using the EVAL, MOVE, and
MOVEL operations, and the new %UCS2 built-in function.
Other enhancements have been made to this release as well. These include:
v New parameters for the OPTION control specification keyword and on the
create commands:
– *SRCSTMT allows you to assign statement numbers for debugging from the
source IDs and SEU sequence numbers in the compiler listing. (The statement
number is used to identify errors in the compiler listing by the debugger, and
to identify the statement where a run-time error occurs.) *NOSRCSTMT
specifies that statement numbers are associated with the Line Numbers of the
listing and the numbers are assigned sequentially.
– Now you can choose not to generate breakpoints for input and output
specifications in the debug view with *NODEBUGIO. If this option is
selected, a STEP on a READ statement in the debugger will step to the next
calculation, rather than stepping through the input specifications.
v New special words for the INZ definition specification keyword:
– INZ(*EXTDFT) allows you to use the default values in the DDS for
initializing externally described data structure subfields.
– Character variables initialized by INZ(*USER) are initialized to the name of
the current user profile.
v The new %XFOOT built-in function sums all elements of a specified array
expression.
v The new EVALR operation code evaluates expressions and assigns the result to a
fixed-length character or graphic result. The assignment right-adjusts the data
within the result.
v The new FOR operation code performs an iterative loop and allows free-form
expressions for the initial, increment, and limit values.
v The new LEAVESR operation code can be used to exit from any point within a
subroutine.
v The new *NEXT parameter on the OVERLAY(name:*NEXT) keyword indicates
that a subfield overlays another subfield at the next available position.
v The new *START and *END values for the SETLL operation code position to the
beginning or end of the file.
v The ability to use hexadecimal literals with integer and unsigned integer fields
in initialization and free-form operations, such as EVAL, IF, etc.
v New control specification keyword OPENOPT{(*NOINZOFL | *INZOFL)} to
indicate whether the overflow indicators should be reset to *OFF when a file is
opened.
v Ability to tolerate pointers in teraspace — a memory model that allows more
than 16 megabytes of contiguous storage in one allocation.
The following tables summarize the changed and new language elements, based
on the part of the language affected.
The following tables summarize the changed and new language elements, based
on the part of the language affected.
Table 9. Changed Language Elements Since V3R7
Language Unit Element Description
Control DECEDIT(*JOBRUN | The decimal edit value can now be
specification ’value’) determined dynamically at runtime
keywords from the job or system value.
Definition DTAARA {(data_area_name)} Users can now access logical data
specification areas.
keywords
EXPORT {(external_name)} The external name of the variable
being exported can now be specified as
a parameter for this keyword.
IMPORT {(external_name)} The external name of the variable
being imported can now be specified
as a parameter for this keyword.
OVERLAY(name{:pos}) The name parameter can now be the
name of the current data structure.
Extended century *CYMD (cyy/mm/dd) The valid values for the century
format character ’c’ are now:
’c’ Years
-----------------------
0 1900-1999
1 2000-2099
. .
. .
. .
9 2800-2899
Internal data type N (Indicator format) Added to the list of allowed internal
data types on the definition
specifications. Defines character data in
the indicator format.
Data format N (Indicator format) Indicator format added to the list of
allowed data formats on the input and
output specifications for program
described files.
Data Attribute *VAR Added to the list of allowed data
attributes on the input and output
specifications for program described
files. It is used to specify
variable-length fields.
The following tables summarize the changed and new language elements, based
on the part of the language affected.
Table 11. Changed Language Elements Since V3R6
Language Unit Element Description
Definition ALIGN ALIGN can now be used to align float
specification subfields along with the previously
keywords supported integer and unsigned
alignment.
OPTIONS(*NOPASS *OMIT The *STRING option allows you to
*VARSIZE *STRING) pass a character value as a
null-terminated string.
Record address F (Float format) Added to the list of allowed record
type address types on the file description
specifications. Signals float processing
for a program described file.
Internal data type F (Float format) Added to the list of allowed internal
data types on the definition
specifications. Defines a floating point
standalone field, parameter, or data
structure subfield.
Data format F (Float format) Added to the list of allowed data
formats on the input and output
specifications for program described
files.
Writing a module with multiple procedures enhances the kind of applications you
can create. Any application consists of a series of logical units that are conceived to
accomplish a particular task. In order to develop applications with the greatest
flexibility, it is important that each logical unit be as independent as possible.
Independent units are:
v Easier to write from the point of view of doing a specific task.
v Less likely to change any data objects other than the ones it is designed to
change.
v Easier to debug because the logic and data items are more localized.
v Maintained more readily since it is easier to isolate the part of the application
that needs changing.
The main benefit of coding a module with multiple procedures is greater control
and better efficiency in coding a modular application. This benefit is realized in
several ways. You can now:
v Call procedures and programs by using the same call operation and syntax.
v Define a prototype to provide a check at compile time of the call interface.
v Pass parameters by value or by reference.
v Define a procedure that will return a value and call the procedure within an
expression.
v Limit access to data items by defining local definitions of variables.
v Code a module that does not make use of the cycle.
The run-time behavior of the main procedure in a module is the same as that of a
V3R1 procedure. The run-time behavior of any subsequent procedures differs
somewhat from a V3R1 program, most notably in the areas of procedure end and
exception handling. These differences arise because there is no cycle code that is
generated for these procedures.
Other enhancements have been made to for this release as well. These include:
v Support for two new integer data types: signed integer (I), and unsigned integer
(U)
The use of the integer data types provides you with a greater range of values
than the binary data type. Integer data types can also improve performance of
integer computations.
v *CYMD support for the MOVE, MOVEL, and TEST operations
You can now use the *CYMD date format in certain operations to work with
system values that are already in this data format.
v Ability to copyright your programs and modules by using the COPYRIGHT
keyword on the control specification
The copyright information that is specified using this keyword becomes part of
the DSPMOD, DSPPGM, or DSPSRVPGM information.
v User control of record blocking using keyword BLOCK
You can request record blocking of DISK or SEQ files to be done even when
SETLL, SETGT, or CHAIN operations are used on the file. You can also request
that blocking not be done. Use of blocking in these cases may significantly
improve runtime performance.
v Improved PREFIX capability
Changes to the PREFIX keyword for either file-description and definition
specifications allow you to replace characters in the existing field name with the
prefix string.
v Status codes for trigger program errors
Two status codes 1223 and 1224 have been added to indicate trigger program
errors.
The following tables summarize the changed and new language elements, based
on the part of the language affected.
Table 13. Changed Language Elements Since V3R1
Language Unit Element Description
File description PREFIX(prefix_string Allows prefixing of string to a field
specification {:nbr_of_char_ replaced}) name or a partial rename of the field
keywords name
Definition CONST{(constant)} Specifies the value of a named
specification constant, or indicates that a prototyped
keywords parameter that is passed by reference
has a constant value
PREFIX(prefix_string Allows prefixing of string to a field
{:nbr_of_char_ replaced}) name or a partial rename of the field
name
Operation codes RETURN Returns control to the caller, and
returns a value, if specified
For more information on RPG IV, see the WebSphere Development Studio: ILE RPG
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.
Cycle Programming
When a system processes data, it must do the processing in a particular order. This
logical order is provided by:
v The ILE RPG compiler
v The program code
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.
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).
2 RPG reads the next record and sets on the record identifying and control
level indicators.
3 RPG processes total calculations (conditioned by control level indicators L1
through L9, an LR indicator, or an L0 entry).
4 RPG processes all total output lines (identified by a T in position 17 of the
output specifications).
5 RPG determines if the LR indicator is on. If it is on, the program ends.
6 The fields of the selected input records move from the record to a
processing area. RPG sets on field indicators.
7 RPG processes all detail calculations (not conditioned by control level
indicators in positions 7 and 8 of the calculation specifications). It uses the
data from the record at the beginning of the cycle.
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:
v handles input parameters, opens files, initializes program data
v writes the records conditioned by the 1P (first page) indicator
v 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
available, 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
subprocedure 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.
Indicators can be defined as variables on the definition specifications. You can also
use RPG IV indicators, which are defined either by an entry on a specification or
by the RPG IV program itself.
Each RPG IV indicator has a two-character name (for example, LR, 01, H3), and is
referred to in some entries of some specifications just by the two-character name,
and in others by the special name *INxx where xx is the two-character name. You
can use several types of these indicators; each type signals something different. The
positions on the specification in which you define an indicator determine the use
of the indicator. Once you define an indicator in your program, it can limit or
control calculation and output operations.
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
calculation operations.
Operation Codes
The RPG IV programming language allows you to do many different types of
operations 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.
v Arithmetic operations
v Array operations
v Bit operations
v Branching operations
v Call operations
v Compare operations
v Conversion operations
v Data-area operations
v Date operations
v Declarative operations
v Error-handling operations
v File operations
v Indicator-setting operations
v Information operations
v Initialization operations
v Memory management operations
v Move operations
v Move zone operations
v Result operations
v Size operations
v String operations
v Structured programming operations
v Subroutine operations
v 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
Control Specifications
Today's date will be printed in day, month, year format with ″/″ as the separator.
Definition Specifications
Calculation Specifications
Output Specifications
The output specifications describe what fields are to be written on the QSYSPRT
output:
v 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.
v 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
constant string ’** NOT ON EMPLOYEE FILE **’ will be printed instead.
v 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 statement.
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.
P CalcPay B
D CalcPay PI 8P 2
D Rate 5P 2 VALUE
D Hours 10U 0 VALUE
D Bonus 5P 2 VALUE
D Overtime S 5P 2 INZ(0)
/free
// Determine any overtime hours to be paid.
if Hours > 40;
Overtime = (Hours - 40) * Rate * 1.5;
Hours = 40;
endif;
// Calculate the total pay and return it to the caller.
return Rate * Hours + Bonus + Overtime;
/end-free
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
*------------------------------------------------------------------------*
* Constant Declarations *
*------------------------------------------------------------------------*
D Heading1 C ’NUMBER NAME RATE H-
D OURS BONUS PAY ’
D Heading2 C ’______ ________________ ______ _-
D ____ _______ __________’
*------------------------------------------------------------------------*
* 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. *
*------------------------------------------------------------------------*
/free
chain trn_number emp_rec;
if %found(emp_rec);
pay = CalcPay (emp_rate: trn_hours: trn_bonus);
endif;
/end-free
*------------------------------------------------------------------------*
* 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’
*------------------------------------------------------------------------*
* Subprocedure -- calculates overtime pay. *
*------------------------------------------------------------------------*
P CalcPay B
D CalcPay PI 8P 2
D Rate 5P 2 VALUE
D Hours 10U 0 VALUE
D Bonus 5P 2 VALUE
D Overtime S 5P 2 INZ(0)
/free
// Determine any overtime hours to be paid.
if Hours > 40;
Overtime = (Hours - 40) * Rate * 1.5;
Hours = 40;
endif;
// Calculate the total pay and return it to the caller.
return Rate * Hours + Bonus + Overtime;
/end-free
P CalcPay E
If you have internet access, you can obtain a complete list of publications that
discuss the OS/400 system at the following URL:
http://publib.boulder.ibm.com/
You can also order the AS/400 V4 System Library Poster, G325-6334-02.
The following table lists some of the most commonly used CL commands, their
function, and the reasons you might want to use them.
The host development tools have undergone major improvements. We are shipping
new C and C++ compilers, completely refreshed from the latest AIX compilers, to
replace the existing versions of these compilers. This will help customers and
solution providers port e-business solutions from other platforms. ILE RPG has
also made major enhancements. Improved Java interoperability and free-form
C-Specs top the list of enhancements. COBOL has added z/OS migration
capabilities as well as introducing some COBOL/Java interoperability capabilities.
Host components:
v ILE RPG
v ILE COBOL
v ILE C/C++
v Application Development ToolSet (ADTS)
Chapter 1. Overview of the RPG IV Programming Language 13
WebSphere Development Studio for iSeries
Workstation components:
v IBM WebFacing Tool
v iSeries development tools: Remote System Explorer and iSeries projects
v Java development tools (with iSeries enhancements)
v Web development tools (with iSeries enhancements)
v Struts environment support
v Database development tools
v Web services development tools
v Server development tools
v XML development tools
v CODE
v VisualAge RPG
v Integrated iSeries debugger
If you want to learn more about WebSphere Development Studio Client for iSeries,
see the most current information available on the World Wide Web at
ibm.com/software/awdtools/iseries/.
Each of the above areas is explained briefly in the following paragraphs and
discussed 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.
Alternatively, you may create a program using separate commands for compilation
and binding. This two-step process allows you to reuse a module or update one
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
directories 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
available to update the program.
For more information on the one-step process, see Chapter 6, “Creating a Program
with the CRTBNDRPG Command,” on page 59. For more information on the
two-step process, see Chapter 7, “Creating a Program with the CRTRPGMOD and
CRTPGM Commands,” on page 75. For more information on service programs, see
Chapter 8, “Creating a Service Program,” on page 91.
Program Management
ILE provides a common basis for:
v Managing program flow
v Sharing resources
v Using application program interfaces (APIs)
v Handling exceptions during a program’s run time
It gives RPG users much better control over resources than was previously
possible.
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 procedure names are resolved at bind time (that is, when you create
the program), static calls are faster than dynamic calls.
v Operational descriptors
v Omitted parameters
v The passing of parameters by value
v The use of return values
v A greater number of parameters to be passed
Source Debugging
Use WebSphere Development Studio Client for iSeries. This is the recommended
method and documentation about debugging programs and appears in that
product’s online help. With the integrated iSeries debugger you can debug your
program running on the iSeries server from a graphical user interface on your
workstation. You can also set breakpoints directly in your source before running
the debugger. The integrated iSeries debugger client user interface also enables you
to control program execution. For example, you can run your program, set line,
watch, and service entry point breakpoints, step through program instructions,
examine variables, and examine the call stack. You can also debug multiple
applications, even if they are written in different languages, from a single debugger
window. Each session you debug is listed separately in the Debug view.
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
activation 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:
v CEETREC – Signal the Termination-Imminent Condition
v CEE4ABN – Abnormal End
v CEECRHP – Create your own heap
v CEEDSHP – Discard your own heap
v CEEFRST – Free Storage in your own heap
20 ILE RPG Programmer’s Guide
RPG Programming in ILE
Note: You cannot use these or any other ILE bindable APIs from within a program
created with DFTACTGRP(*YES). This is because bound calls are not
allowed in this type of program.
For more information on these ILE bindable APIs, see Chapter 9, “Running a
Program,” on page 103.
Multithreaded Applications
The iSeries system now supports multithreading. ILE RPG does not directly
support initiating or managing program threads. However, ILE RPG procedures
can run as threads in multithreaded environments. If you want to call an ILE RPG
procedure in a multithreaded application, you must ensure that the ILE RPG
procedure is threadsafe. You must also ensure that any system functions that your
procedure accesses are also threadsafe.
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
flexibility.
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
creation 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.
program and two RPG programs. In this example, one of the RPG programs has
been moved to ILE; the remaining programs are unchanged.
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 messages
may have new message IDs, so if your CL program monitors for a
specific message ID, you may have to change that ID.
Related Information
Converting to RPG IV “Converting Your Source” on page 420
One-step creation process Chapter 6, “Creating a Program with the
CRTBNDRPG Command,” on page 59
ILE static binding Chapter 10, “Calling Programs and Procedures,” on
page 129; also ILE Concepts
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
programs 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
procedure 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
previous call to the procedure ended with LR on, or ended
abnormally.
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
with programs in different activation groups. If you want to share
a file across activation groups, you must open it at the job level by
specifying SHARE(*YES) on an override command or create the file
with SHARE(*YES).
Errors When you call an ILE RPG program or procedure in the same
Related Information
Converting to RPG IV “Converting Your Source” on page 420
One-step creation process Chapter 6, “Creating a Program with the
CRTBNDRPG Command,” on page 59
Activation groups “Managing Activation Groups” on page 110
RCLRSC “Reclaim Resources Command” on page 112
ILE static binding Chapter 10, “Calling Programs and Procedures,” on
page 129; also ILE Concepts
Exception handling differences
“Differences between OPM and ILE RPG Exception
Handling” on page 256
Override and open scope “Overriding and Redirecting File Input and
Output” on page 307 and “Sharing an Open Data
Path” on page 311; 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:
v 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.
v 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.)
v 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.
Job
XY Activation Group
*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.
Job
Y Activation Group
*PGM(Y)
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.
Job
XYZ Activation Group
*PGM(X)
CL *MODULE(X1)
*SRVPGM(Y)
*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
75
Activation groups “Managing Activation Groups” on page 110
ILE static binding Chapter 10, “Calling Programs and Procedures,” on
page 129; also ILE Concepts
Exception Handling Chapter 13, “Handling Exceptions,” on page 251;
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 88
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
application 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.
#
Job
Default Activation Group
*PGM(X)
CL
RPG
*SRVPGM(Z)
RPG
#
# Figure 11. Scenario to Avoid. An application has a CL program in the OPM default activation
# group and ILE programs in a named activation group.
# When an application is 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.
# Note: Calling an ILE program from the command line, or from an OPM program
# that simply makes a call, is not a problem. The problems, which can all be
# solved, stem from OPM programs and ILE programs using shared resources
# such as overrides and commitment control, and from OPM programs trying
# to using OPM commands such as RCLRSC which have no effect on
# programs running in a named activation group.
Refer to the end of this section to see where to look for more detailed information
on coding modules with multiple procedures.
Note: In the RPG documentation, the term ’procedure’ refers to both main and
subprocedures.
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
procedure.
Figure 12 shows what a module might look like with multiple procedures.
*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
subprocedures 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:
v Whether the call is bound (procedure) or dynamic (program)
v How to find the program or procedure (the external name)
v The number and nature of the parameters
v Which parameters must be passed, and which are optionally passed
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.
# //---------------------------------------------------------
# // FmtAddr - procedure to produce an address in the form
# //---------------------------------------------------------
# D FmtAddr PR 100A VARYING
# D streetNum 10I 0 CONST
# D streetName 50A CONST
# D city 20A CONST
# D state 15A CONST
# D zip 5P 0 CONST
#
#
# Figure 14. Prototype for FmtAddr Procedure
#
If the program or procedure is prototyped, you call it with CALLP or within an
expression if you want to use the return value. You pass parameters in a list that
follows the name of the prototype, for example, name (parm1 : parm2 : ...).
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 parameter
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):
v Programs that are on the system at run time
v Exported procedures in other modules or service programs that are bound in the
same program or service program
v Subprocedures in the same module
# FmtCust calls FmtAddr to format the address. Because FmtCust wants to use the
# return value, the call to FmtAddr is made in an expression. Figure 16 shows the
# call.
# //--------------------------------------------------------------
# // Call the FmtAddr procedure to handle the address
# //--------------------------------------------------------------
# Address = FmtAddress (STREETNUM : STREETNAME :
# CITY : STATE : ZIP);
##
# Figure 16. Calling the FmtAddr Procedure
#
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
# interface enables a number of options for parameter passing.
v 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.
v 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)
ARRSRPT MODULE
Main Procedure
Open file, read record, write
output records, close files
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
uppercase 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.
//--------------------------------------------------------------
// InArrears
//
// Parameters: (none)
// Globals: DUEDATE, AMOUNT, CurDate
//
// Returns: ’1’ if the customer is in arrears
//--------------------------------------------------------------
P InArrears B 1
D InArrears PI 1A 2
// Local declarations
D DaysLate S 10I 0 3
D DateDue S D 3
// Body of procedure
/free
DateDue = %date (DUEDATE: *ISO);
DaysLate = %diff (CurDate: DateDue: *d);
// The data in the input file comes from another type
// of computer, and the AMOUNTC field is a character
// string containing the numeric value. This string
// must be converted to the numeric AMOUNT field
// for printing.
# AMOUNT = %dec(AMOUNTC : 31 : 9);
if DaysLate > 60 AND AMOUNT > 100.00;
return ’1’; 4
endif;
return ’0’; 4 5
/end-free
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 procedure
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
parameters, 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 consistent with the external definition (the prototype). In the case
of InArrears, there are no entry parameters.
Consider next the subprocedure FmtCust, which is shown in Figure 19 on page 39.
FmtCust is called by ARRSRPT to format the relevant fields of a record into an
output record for the final report. (The record represents an account that is in
arrears.) FmtCust uses global data, and so does not have any input parameters. It
formats the data into two output fields: one for the name, and one for the address.
//--------------------------------------------------------------
// FmtCust formats CUSTNAME, CUSTNUM, STREETNAME etc into
// readable forms
//
// Parameters: Name (output)
// Address (output)
// Globals: CUSTNAME, CUSTNUM, STREETNUM, STREETNAME, CITY
// STATE, ZIP
//--------------------------------------------------------------
P FmtCust B
D FmtCust PI
D Name 100A
D Address 100A
/free
//--------------------------------------------------------------
// CUSTNAME and CUSTNUM are formatted to look like this:
// A&P Electronics (Customer number 157)
//--------------------------------------------------------------
Name = CUSTNAME + ’ ’ + ’(Customer number ’
+ %char(CUSTNUM) + ’)’;
# //--------------------------------------------------------------
# // Call the FmtAddr procedure to handle the address
# //--------------------------------------------------------------
#
# Address = FmtAddress (STREETNUM : STREETNAME :
# CITY : STATE : ZIP);
# /end-free
# P FmtCust E
# Finally, consider the last subprocedure of this application, FmtAddr. Notice that
# FmtAddr does not appear in the ARRSRPT module, that is shown in Figure 17 on
# page 37. We decided to place FmtAddr inside another module called FMTPROCS.
# FMTPROCS is a utility module that will contain any conversion procedures that
# other modules might need to use.
# Figure 20 on page 40 shows the source of the module FMTPROCS. 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 FMTPROCS. 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 FmtAddr.
# //-----------------------------------------------------------------
# D/COPY QRPGLESRC,FMTPROC_P
# P FmtAddr B EXPORT
# D FmtAddr PI 100A VARYING
# D streetNum 10I 0 CONST
# D streetName 50A CONST
# D city 20A CONST
# D state 15A CONST
# D zip 5P 0 CONST
# /free
# //--------------------------------------------------------------
# // STREETNUM, STREETNAME, CITY, STATE, and ZIP are formatted to
# // look like:
# // 27 Garbanzo Avenue, Smallville IN 51423
# //--------------------------------------------------------------
# return %char(streetNum) + ’ ’ + %trimr(streetName)
# + ’, ’ + %trim(city) + ’ ’ + %trim(state)
# + ’ ’ + %editc(zip : ’X’);
# P FmtAddr E
##
# Figure 20. Source for module FMTPROCS, containing subprocedure FmtAddr.
#
# FMTPROCS is a NOMAIN module, meaning that it consists only of
subprocedures; there is no main procedure. A NOMAIN module compiles faster
and requires less storage because there is no cycle code that is created for the
module. You specify a NOMAIN module, by coding the NOMAIN keyword on the
control specification. For more information on NOMAIN modules, see “Program
Creation” on page 45.
//=================================================================
// Source for module ARRSRPT. Contains a main procedure and
// two subprocedures: InArrears and FmtCust.
//
// Related Module: CVTPROCS (CharToNum called by InArrears)
//=================================================================
//--------------------------------------------------------------
// F I L E S
//
// CUSTFILE - contains customer information
// CUSTRPT - printer file (using format ARREARS)
//--------------------------------------------------------------
FCUSTFILE IP E DISK
FCUSTRPT O E PRINTER
*--------------------------------------------------------------*
* P R O T O T Y P E S
*--------------------------------------------------------------*
# /COPY QRPGLE,FMTPROC_P
*--------------------------------------------------------------*
* 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
Figure 22. ILE RPG Complete Source for ARRSRPT Module (Part 1 of 3)
*--------------------------------------------------------------*
* 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 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
# // Body of procedure
# /free
# DateDue = %date (DUEDATE: *ISO);
# DaysLate = %diff (CurDate: DateDue: *d);
# // The data in the input file comes from another type
# // of computer, and the AMOUNTC field is a character
# // string containing the numeric value. This string
# // must be converted to the numeric AMOUNT field
# // for printing.
# AMOUNT = %dec(AMOUNTC : 31 : 9);
# if DaysLate > 60 AND AMOUNT > 100.00;
# return ’1’;
# endif;
# return ’0’;
# /end-free
# P InArrears E
Figure 22. ILE RPG Complete Source for ARRSRPT Module (Part 2 of 3)
# //--------------------------------------------------------------
# // FmtCust formats CUSTNAME, CUSTNUM, STREETNAME etc into
# // readable forms
# //
# // Parameters: Name (output)
# // Address (output)
# // Globals: CUSTNAME, CUSTNUM, STREETNUM, STREETNAME, CITY
# // STATE, ZIP
# //--------------------------------------------------------------
#
# P FmtCust B
# D FmtCust PI
# D Name 100A
# D Address 100A
#
# /free
# //--------------------------------------------------------------
# // CUSTNAME and CUSTNUM are formatted to look like this:
# // A&P Electronics (Customer number 157)
# //--------------------------------------------------------------
# Name = CUSTNAME + ’ ’ + ’(Customer number ’
# + %char(CUSTNUM) + ’)’;
# //--------------------------------------------------------------
# // Call the FmtAddr procedure to handle the address
# //--------------------------------------------------------------
#
# Address = FmtAddress (STREETNUM : STREETNAME :
# CITY : STATE : ZIP);
# /end-free
# P FmtCust E
Figure 22. ILE RPG Complete Source for ARRSRPT Module (Part 3 of 3)
Figure 24 and Figure 25 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 AMOUNTC 15 TEXT(’AMOUNT OUTSTANDING’)
A DUEDATE 10 TEXT(’DATE DUE’)
A*================================================================*
A* FILE NAME : CUSTRPT
A* RELATED PGMS : ARRSRPT
A* DESCRIPTIONS : THIS IS THE PRINTER FILE CUSTRPT. IT HAS
A* ONE RECORD FORMAT CALLED ARREARS.
A*================================================================*
A R ARREARS
A 2 6
A ’Customer number:’
A RPTNUM 5 0 2 23
A TEXT(’CUSTOMER NUMBER’)
A RPTNAME 100A 3 10
A TEXT(’CUSTOMER NAME’)
A RPTADDR 100A 4 10
A TEXT(’CUSTOMER ADDRESS’)
A 5 10’Amount outstanding:’
A AMOUNT 10 2 5 35EDTWRD(’ $0. ’)
A TEXT(’AMOUNT OUTSTANDING’)
A 5 50’Due date:’
A DUEDATE 10 5 60
A 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:
v General
v Program Creation
v Main Procedures
v Subprocedures
General Considerations
v 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.
v 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
application, any module or program that makes use of the /COPY file will be
recompiled 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
compilation errors, you can then decide whether to accept the change to
prototypes to avoid these errors, or whether to change the call interface.
Program Creation
v If you specify that a module does not have a main procedure then you cannot
use the CRTBNDRPG command to create the program. (A module does not have
a main procedure if the NOMAIN keyword is specified on a control
specification.) This is because the CRTBNDRPG command requires that the
module contain a program entry procedure and only a main procedure can be a
program entry procedure.
v Similarly, when using CRTPGM to create the program, keep in mind that a
NOMAIN module cannot be an entry module since it does not have a program
entry procedure.
v A program that is created to run in the default OPM activation group (by
specifying DFTACTGRP(*YES) on the CRTBNDRPG command) cannot contain
bound procedure calls.
Subprocedure Considerations
v 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.
v The control specification can only be coded in the main source section since it
controls the entire module.
v 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
specified for the definition.)
The automatic storage that is associated with earlier invocations is unaffected by
later invocations. All invocations share the same static storage, so later
invocations can affect the value held by a variable in static storage.
Recursion can be a powerful programming technique when properly
understood.
v The run-time behavior of a subprocedure differs somewhat from that of a main
procedure, because there is no cycle code for the subprocedure.
– When a subprocedure ends, it simply returns to the caller. None of the usual
termination activities, such as closing of files, occurs until the main procedure
that is associated with the subprocedure itself ends. You should code a
″cleanup″ subprocedure that is called both by the program entry procedure at
application-end, and by a cancel handler enabled for the program entry
procedure.
An alternative is to code the NOMAIN module so that there is no implicit file
opening or data area locking, and that within any subprocedure, an open is
matched by a close, an IN by an OUT, a CRT<temp obj> by a DLT<temp
obj>, and so on. This alternative applies to modules that may have a
subprocedure active when the main procedure is not active.
– Exception handling within a subprocedure differs from a main procedure
primarily because there is no default exception handler for subprocedures. As
a result, situations where the default handler would be called for a main
procedure correspond to abnormal end of the subprocedure.
Main Procedures
Topic See
Exception handling “Exception Handling within a Main Procedure” on
page 254
Main Procedure End “Returning from a Main Procedure” on page 153
Subprocedures
Topic See
Defining Chapter on subprocedures, in the WebSphere
Development Studio: ILE RPG Reference
Prototyped Call
Topic See
Free-form call “Using a Prototyped Call” on page 134
General Information WebSphere Development Studio: ILE RPG Reference,
Chapter 24
Passing parameters “Passing Prototyped Parameters” on page 136
Prototypes Chapter on defining data and prototypes in the
WebSphere Development Studio: ILE RPG Reference
Use WebSphere Development Studio Client for iSeries. This is the recommended
method and documentation about creating and running an ILE RPG application
appears in that product’s online help.
Many Integrated Language Environment 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:
v Interactively using SEU
v Interactively using Remote Systems LPEX Editor.
Use WebSphere Development Studio Client for iSeries. This is the recommended
method and documentation about editing source appears in that product’s online
help. Your program editing tasks are simplified with the Remote Systems LPEX
editor. The editor can access source files on your workstation or your iSeries server.
When a compilation results in errors, you can jump directly from the compiler
messages to an editor containing the source. The editor opens with the cursor
positioned at the offending source statements so that you can correct them.
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
commands 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 on page 52.
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 for AS/400: Source Entry Utility manual and the ADTS/400: Programming
Development 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
parameter 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:
v Create a library
v Create a source physical file
v Start an SEU editing session
v Enter source statements.
1. To create a library called MYLIB, type:
CRTLIB LIB(MYLIB)
STRSEU SRCFILE(MYLIB/QRPGLESRC)
SRCMBR(EMPRPT)
TYPE(RPGLE) OPTION(2)
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. 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:
v IPF — for file description specifications
v IPD — for definition specifications
v IPI — for input specifications
v IPC — for calculation specifications
v IPCX — for calculation specifications with extended Factor 2
v IPO — for output specifications
v IPP — for output specifications continuation
v IPPR — for procedure specifications
*===============================================================*
* MODULE NAME: EMPRPT
* RELATED FILES: EMPMST (PHYSICAL FILE)
* QSYSPRT (PRINTER FILE)
* DESCRIPTION: This program prints employee information
* from the file EMPMST.
*===============================================================*
FQSYSPRT O F 80 PRINTER
FEMPMST IP E K DISK
D TYPE S 8A
D EMPTYPE PR 8A
D CODE 1A
IEMPREC 01
C EVAL TYPE = EMPTYPE(ETYPE)
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 01
O ENAME 20
O ENUM 32
O EDEPT 45
O TYPE 60
* Procedure EMPTYPE returns a string representing the employee
* type indicated by the parameter CODE.
P EMPTYPE B
D EMPTYPE PI 8A
D CODE 1A
C SELECT
C WHEN CODE = ’M’
C RETURN ’Manager’
C WHEN CODE = ’R’
C RETURN ’Regular’
C OTHER
C RETURN ’Unknown’
C ENDSL
P EMPTYPE E
Figure 29 on page 55 shows the DDS which is referenced by the EMPRPT source.
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
To create a program from this source use the CRTBNDRPG command, specifying
DFTACTGRP(*NO).
...+....1....+....2....+....3....+....4....+....5....+....6....+....7..
C
C (ILE RPG calculation operations)
C
C/EXEC SQL (the starting delimiter)
C+
C+ (continuation lines containing SQL statements)
C+
.
.
.
C/END-EXEC (the ending delimiter)
C
C (ILE RPG calculation operations)
C
You must enter a separate command to process the SQL statements. For more
information, refer to the DB2 Universal Database for AS/400 section of the Database
and File Systems category in the iSeries 400 Information Center at this Web site -
http://www.ibm.com/eserver/iseries/infocenter.
Refer to the ADTS for AS/400: Source Entry Utility manual for information about
how SEU handles SQL statement syntax checking.
# The stream file specified for the SRCSTMF can be an absolute path to the file
# (beginning with a slash), or it can be a path relative to the current directory.
# Include files
# The /COPY and /INCLUDE directives allow the specification of files in either the
# QSYS file system or the IFS file system. In cases where the compiler cannot tell
# which file system the directive refers to, the search will begin in the file system of
# the file containing the /COPY directive.
# When the compiler encounters a /COPY statement, the statement could refer to a
# file in the IFS or in the QSYS file system. If the name begins with a slash or is
# specified in single quotes, the name can only refer to a file in the IFS. A name in
# the IFS can be specified in double quotes as well. Where only part of the name is
# in double quotes, for example:
# /copy "SOME-LIB"/QRPGLESRC,MBR
# If the name could be either in the QSYS file system or the IFS, the file system of
# the file containing the /COPY statement will be searched first. Note that
# upper-casing occurs for the QSYS file system (except with extended names
# specified with double quotes, such as ″A/B″) but not for the IFS. (The IFS is not
# case sensitive.)
# Table 17. /Copy File Name Intepretation for QSYS and IFS
# /Copy statement QSYS interpretation IFS interpretation (see
# below for the meaning of
# ″.suffix″)
# /COPY MYMBR FILE(*LIBL/QRPGLESRC) MYMBR or MYMBR.suffix in
# MBR(MYMBR) one of the directories in the
# include path
# /COPY mymbr FILE(*LIBL/QRPGLESRC) mymbr or mymbr.suffix in
# MBR(MYMBR) one of the directories in the
# include path
# Table 17. /Copy File Name Intepretation for QSYS and IFS (continued)
# /Copy statement QSYS interpretation IFS interpretation (see
# below for the meaning of
# ″.suffix″)
# /COPY myfile,mymbr FILE(*LIBL/MYFILE) myfile,mymbr or
# MBR(MYMBR) myfile,mymbr.suffix (note
# that MYFILE,MYMBR is a
# valid name in the IFS file
# system)
# /COPY mylib/myfile,mymbr FILE(MYLIB/MYFILE) mylib/myfile,mymbr
# MBR(MYMBR) (directory mylib and file
# myfile,mymbr)
# /COPY ″A/b″,mymbr FILE(*LIBL/″A/b″) n/a (only part of name is in
# MBR(MYMBR) double quotes
# /COPY ″A/B″ FILE(*LIBL/QRPGLESRC) A/B
# MBR(″A/B″)
# /COPY a b FILE(*LIBL/QRPGLESRC) a or a.suffix (everything
# MBR(A) (everything after a after a blank is assumed
# blank is assumed to be a to be a comment)
# comment)
# /COPY ’a b’ N/A (name in single quotes) a b or a b.suffix
# /COPY N/A (name begins with /home/mydir/myfile.rpg
# /home/mydir/myfile.rpg slash)
# /COPY /QSYS.LIB/ N/A (name begins with /QSYS.LIB/L.LIB/F.FILE/
# L.LIB/F.FILE/M.MBR slash) M.MBR (which is actually a
# file in the QSYS file system,
# but is considered to be an
# IFS file by RPG)
#
# Note: When searching for files in the IFS, if the file name does not contain a dot,
# the RPG compiler will look for files with the following suffixes (in this
# order):
# 1. no suffix (abc)
# 2. .rpgleinc (abc.rpgleinc)
# 3. .rpgle (abc.rpgle)
# When searching for a relative file in the IFS (one whose path does not begin with
# /), the file will be searched for in the following places, in this order
# 1. The current directory.
# 2. The path specified by the INCDIR comand parameter.
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:
v Use the CALLB operation in your source
v Call a prototyped procedure
v 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.
Use WebSphere Development Studio Client for iSeries. This is the recommended
method and documentation about creating an ILE RPG program appears in that
product’s online help.
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 command. For more information see Chapter 7, “Creating a
Program with the CRTRPGMOD and CRTPGM Commands,” on page 75.
Table 19. CRTBNDRPG Parameters and Their Default Values Grouped by Function (continued)
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
FIXNBR(*NONE) Determines which decimal data that is not valid is to be fixed by the
compiler
Run-Time Considerations
DFTACTGRP(*YES) Identifies whether this program always runs in the OPM default
activation group
OPTION(*DEBUGIO) *DEBUGIO/*NODEBUGIO, determines if breakpoints are generated
for input and output specifications
ACTGRP(QILE) Identifies the activation group in which the program should run
SRTSEQ(*HEX) Specifies the sort sequence table to be used
LANGID(*JOBRUN) Used with SRTSEQ to specify the language identifier for sort
sequence
TRUNCNBR(*YES) Specifies the action to take when numeric overflow occurs for
packed-decimal, zoned-decimal, and binary fields in fixed-format
operations.
# INFOSTMF(path) Used with PGMINFO, specifies the stream file in the IFS to receive
# the PCML
# PGMINFO(*NONE) *PCML indicates that PCML (Program Call Markup Language)
# should be generated for the program
LICOPT(options) Specifies Licensed Internal Code options.
See Appendix C, “The Create Commands,” on page 443 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 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
recommended that you run your application as a unique group to ensure that the
associated 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.
*------------------------------------------------------------------------*
* 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
*------------------------------------------------------------------------*
* 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
*------------------------------------------------------------------------*
* 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’
See Appendix D, “Compiler Listings,” on page 465 for more information on the
different parts of the listing and for a complete sample listing.
*SECLVL
Second-level message text (appear in message summary section)
Note: Except for *SECLVL and *SHOWSKP, all of the above values reflect the
default settings on the OPTION parameter for both create commands. You
do not need to change the OPTION parameter unless you do not want
certain listing sections or unless you want second level text to be included.
If any compile option keywords are specified on the control specification, the
compiler 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:
v Select one of the following date separators: *SYSVAL, *BLANK, slash (/),
hyphen (-) period (.) or comma (,)
v Select one of the following date formats: *SYSVAL, *YMD, *MDY, *DMY, or *JUL
v 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
information on these directives refer to the WebSphere Development Studio: ILE RPG
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:
v Do Num
v Last Update
v PAGE/LINE
If you specify indentation and you also specify a listing debug view, the
indentation will not appear in the debug view.
Figure 33 on page 68 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
check that the source is coded the way you intended it to be. Parts of the listing,
besides the source statements, which you may want to check include:
v Match field table
If you are using the RPG cycle with match fields, then you can use this to check
that all your match fields are the correct lengths, and in the correct positions.
v Output-buffer positions
Lists the start and end positions along with the literal text or field names. Use
this to check for errors in your output specifications.
v Compile-time data
ALTSEQ and FTRANS records and tables are listed. NLSS information and
tables are listed. Tables and arrays are explicitly identified. Use this to confirm
that you have specified the compile-time data in the correct order, and that you
have specified the correct values for the SRTSEQ and LANGID parameters to the
compiler.
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
63 C SETOFF _12___ 003100
======> aabb
======> cccccc
*RNF5051 20 a 003100 Resulting-Indicator entry is not valid; defaults to blanks.
*RNF5051 20 b 003100 Resulting-Indicator entry is not valid; defaults to blanks.
*RNF5053 30 c 003100 Resulting-Indicators entry is blank for specified
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 shows an example of the
non-finger in-line diagnostic messages.
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
1 D FLD1 S +5 LIKE(FLD2) 000100
2 D FLD2 S D 000200
*RNF3479 20 1 000100 A length adjustment is not allowed for a field of the
specified data type.
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).
possible, the message line includes either the listing Line Number and SEU
sequence number, or the Statement Number of a source line which is related to the
message.
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
highlighted, 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.
For complete information on browsing a compiler listing, see ADTS for AS/400:
Source Entry Utility.
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 474.
In either case it is advisable to have a full listing, namely, one produced with
OUTPUT(*PRINT) and with OPTION(*XREF *SHOWCPY *EXPDDS *EXT
*SHOWSKP).
Note: Except for *SHOWSKP, this is the default setting for each of these
parameters on both create commands.
Of particular value for program maintenance is the Prologue section of the listing.
This section tells you:
v Who compiled the module/program
v What source was used to produce the module/program
v 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.
Use WebSphere Development Studio Client for iSeries. This is the recommended
method and documentation about creating an ILE RPG program appears in that
product’s online help.
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:
v 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.
v 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 20. CRTRPGMOD Parameters and Their Default Values Grouped by Function (continued)
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 identify
character for marking it
OPTION(*XREF *NOSECLVL *SHOWCPY Specifies the contents of compiler listing
*EXPDDS *EXT *NOSHOWSKP
*NOSRCSTMT)
Data Conversion Options
CVTOPT(*NONE) Specifies how various data types from externally described files are
handled
ALWNULL(*NO) Determines if the module will accept values from null-capable fields
FIXNBR(*NONE) Determines which decimal data that is not valid is to be fixed by the
compiler
Run-Time Considerations
SRTSEQ(*HEX) Specifies the sort sequence table to be used
OPTION(*DEBUGIO) *DEBUGIO/*NODEBUGIO, determines if breakpoints are generated
for input and output specifications
LANGID(*JOBRUN) Used with SRTSEQ to specify the language identifier for sort
sequence
# INFOSTMF(path) Used with PGMINFO, specifies the stream file in the IFS to receive
# the PCML
# PGMINFO(*NONE) *PCML indicates that PCML (Program Call Markup Language)
# should be generated for the module
TRUNCNBR(*YES) Specifies action to take when numeric overflow occurs for
packed-decimal, zoned-decimal, and binary fields in fixed format
operations.
LICOPT(options) Specifies Licensed Internal Code options.
For information on using the compiler listing, see “Using a Compiler Listing” on
page 65. A sample compiler listing is provided in Appendix D, “Compiler
Listings,” on page 465.
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
b. CRTSRVPGM command
c. CRTBNDRPG command where the NOMAIN module is included in a
binding directory.
2. Once it is bound, this module object can be debugged using a statement view.
A compiler listing for the module is also produced.
3. Type one of the following CL commands to see the compiler listing.
v DSPJOB and then select option 4 (Display spooled files)
v WRKJOB
v WRKOUTQ queue-name
v WRKSPLF
*=================================================================*
* 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
*------------------------------------------------------------------
* Subprocedure Trans_Inc
*------------------------------------------------------------------
P Trans_Inc B EXPORT
D Trans_Inc PI 11P 2
D ProdNum 10P 0 VALUE
D Quantity 5P 0 VALUE
D Discount 2P 2 VALUE
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
C RETURN Factor * Quantity * (1 - Discount)
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