My kids and I enjoy reading fairy tales. Together, weve seen an ugly duckling become a swan, a beast become a handsome prince, and a wooden puppet become a boy.
These stories are not unlike the transformation Ive seen in RPG since I wrote my first program on a System/3 Model 12 so many years ago. The RPG we use today is much more powerful and elegant than what I used back then.
With V4R2, IBM continues this transformation, with more enhancements to the RPG IV compiler. I think were going to like some of these a lot!
Figure 1 contains a short example program I threw together to illustrate some of these changes. Ill be referring to it throughout this article.
File Operations
Let me start by introducing the new built-in functions that help with file I/O. They are %EOF, %FOUND, %EQUAL, and %OPEN. These new built-in functions will reduce the number of indicators we have to use in our programs by providing an alternative to specifying the traditional resulting indicators for input/output operations. The %EOF function returns *ON if the specified file is at end of file for the READ, READC, or READE operations (beginning of file for READP or READPE operations), or *OFF otherwise. You can also use %EOF to test for failed write (WRITE) operations to a subfile.
Look at Label A in Figure 1. Notice the READ has no resulting indicator. It doesnt need one because of the %EOF function in the next line.
For CHAIN, SETLL, SETGT, and DELETE operations, the %FOUND function accomplishes the same sort of thing. It returns *ON if the desired record was found (e.g., the CHAIN succeeded), or *OFF if not. You can see an example of this at Label B.
If you prefer, you can use the %EQUAL function instead of %FOUND on SETLL operations. (%EQUAL also works for the LOOKUP table or array operation.)
To test whether or not a file is open, use the %OPEN function. Like the other functions weve already seen, this returns a value of *ON (open) or *OFF (closed). At Label C, the program in Figure 1 uses this function to decide whether or not it needs to open the error report file. If no errors are found while the program runs, the file never gets opened. The program also uses %OPEN at Label E to ensure it doesnt try to print an error message if the error report file open fails.
Error Handling
There are also two new functions to help with error handling%ERROR and %STATUS. To use them, you must use the new E op code extender on the operation that might end in error. You omit the resulting indicator in the low position.
The %ERROR function accepts no parameters, and returns *ON if the last executed operation with an E extender ended in error. Look at Label D. The E operation extender keeps the program from canceling if the open fails. The %ERROR function on the following line will prove true (*ON) if the open fails, and the abend routine will execute.
The %STATUS function may take a parameter, but it doesnt have to. Without a parameter, %STATUS returns a program or file status code, whichever changed most recently. You can get the most recent status code for a certain file by specifying the file name in the parameter.
Better Access to Logical Data
V4R2 adds support for logical (a.k.a. Boolean) variables to RPG, but theyre not
called logical variables. Instead, theyre called indicator variables. You define indicator variables on the D-specs, specifying no length, and a data type of N in position 40. Indicator variables can have values of *ON and *OFF.
In Figure 1, variables GoodCustomer and PostToGL are indicator variables. If youll look through the calculations, youll see two places where GoodCustomer is set on or off and one place where it is tested with an IF. I could have compared GoodCustomer to *ON, but thats not necessary.
IBM also added RPG support for logical data areas. The PostToGL indicator variable gets its value from the logical data area GLACTIVE, found somewhere in the library list.
Named Indicators for Device Files
You can now use your own data structure to define the indicators used by workstation and printer files that specify the INDARA keyword. Such a data structure must be 99 bytes long, and all subfields must be of the indicator data type.
This means your RPG programs do not have to refer to the indicators in device files by number. Instead, you can assign names to the indicators and refer to them by name.
The few display file specs shown in Figure 2 define indicators 03, 12, and 20 through 23. In Figure 3, data structure Conditions maps these indicators to indicator variables so that you can refer to SflClr instead of *IN22.
New Character Manipulation Abilities
The character variables weve been using all these years are fixed-length. V4R2 adds support for variable-length character and graphic variables.
Variable-length character variables are declared with a length from 1 to 32,767 and a data type of A, just like fixed-length character variables. To make the variable variable- length, add the keyword VARYING. RPG makes the variable two bytes larger than its declared length. The first two bytes contain the significant length (the position of the last nonblank character in the field) of the data in binary format.
You can use the %LEN (length) function to set or retrieve the current length of a variable-length character variable.
Dont confuse these variable-length character variables with null-terminated strings like those used in the C language. They are not the same things.
The %REPLACE function is new. It allows you to replace a substring of a character or graphic variable with another substring. The two substrings dont have to be the same length, nor do they have to be the same format (one can be fixed-length, the other variable-length), but they do have to be the same data type.
%REPLACE has four parameters. The first two are required; the last two are not. The first parameter is the string to be inserted into the character variable. The second parameter is the character variable containing the data to be replaced. The third parameter is the starting position of modification. The default value is 1, which means the replacement data will be placed at position 1 of the character variable. The fourth parameter is the number of characters being replaced. It defaults to the length of the first parameter.
Assume the program in Figure 1 retrieves a customer master record in which the customer name is Jack Sprat & Sons, Inc. The %SCAN function finds a blank, an ampersand, and another blank beginning at position 12 of the customer name. The %REPLACE operation replaces & with and and stores Jack Sprat and Sons, Inc. in CustName.
%CHAR converts graphic, time stamp, date, or time data to character format. Time stamp, date, and time values will be in edited format.
Changes to the H-Spec
You may find yourself using control (H) specs more once you move to V4R2 because IBM has added the ability to specify compiler options there. The CRTBNDRPG and CRTRPGMOD commands will read these compiler options.
In Figure 1, Ive included three compiler options: DftActGrp(*no), ActGrp(*new), and Indent(..) in the control spec. Figure 4 contains a list of the compiler options allowed in H-specs.
This is exciting to me. It means I no longer have to put compiler options in comments and hope that whoever compiles my code follows my instructions. What a load off a programmers mind! Maybe IBM should add control specs to DDS and CL.
Theres another enhancement that people who run their applications internationally will like. The control specs now allow you to dynamically set the DECEDIT value at runtime. If you specify DECEDIT(*JOBRUN) in the H-spec, the program will use the decimal editing character of the job.
Miscellaneous Changes and Enhancements
Here are other ways V4R2 RPG IV differs from previous compilers:
The %EQUAL and %FOUND functions can be used with table and array LOOKUPs to indicate that an exact match was found.
The %FOUND function can indicate a match from a CHECK, CHECKR, or SCAN operation.
RPG programs can now import and export procedures and variables with mixed- case names. To do so, add a parameter to the IMPORT or EXPORT keywords in the D- specs (not the EXPORT keyword in the P-specs). The parameter must be a literal or a constant.
Date formats *CMDY (cmmddyy), *CDMY (cddmmyy), and *LONGJUL (yyyyddd) are now supported.
Values 0 (19xx) through 9 (28xx) are now supported for century digits in dates.
The first parameter of the OVERLAY keyword in D-specs may now be the name of the data structure itself.
CRTRPGMOD now has a BNDDIR parameter, allowing you to specify a binding directory.
CRTBNDRPG and CRTRPGMOD have a new PRFDTA (profile data) parameter to support application profiling.
The FIXNBR parameter of the CRTBNDRPG and CRTRPGMOD commands now accepts the value *INPUTPACKED, meaning that the program should handle invalid packed data from input files.
You can place an N in position 36 of an input spec or position 52 of an output spec to define an indicator variable.
You can also specify a variable-length field by placing the value *VAR in positions 31 through 34 of an input spec or 53 through 80 of an output spec.
RPG now defines a new status code value, 115, for errors with variable-length
The Tale Continues
So thats whats new with RPG. Stay tuned to these pages. I have a feeling Ill be writing a sequel to this tale in the not-too-distant future.
In case it hasnt hit you, it is now possible to write an RPG program with no indicators. RPG has come a long way. Whether or not you think its become a swan, maybe you can at least agree that RPG is not the ugly duckling it once was.
fields.
Reference
ILE RPG/400 Reference (SC09-2508, CD-ROM QB3AGZ00)
H DftActGrp (*no) ActGrp(*new) Indent(..)
FXacts if e k disk
FCustMas if e k disk
FsomeRpt o e printer
FErrorRpt o e printer usropn
D GoodCustomer s N
D PostToGL s N dtaara(GLACTIVE)
D ScanX s 5I 0
D CustName s 35 varying
C in PostToGL
C unlock PostToGL
C
BEGIN LABEL A
C read XactsR
C dow not %eof( Xacts)
END LABEL A
C
C eval % len( CustName) 0
BEGIN LABEL B
C CusNo chain CustMasR
C if %found( CustMas)
END LABEL B
C eval GoodCustomer = *on
C eval ScanX = %scan( & : CusNm)
C if ScanX > *zero
C eval CustName =
C %replace( and : CusNm: ScanX: 3)
C endif
C if PostToGL
... do whatever you do if GL is interfacing to this application
C endif
... do some more stuff
C else
C eval GoodCustomer = *off
C exsr ErrorRoutine
C endif
C
C if GoodCustomer
... do whatever you do for valid customer numbers
C else
... do whatever you do for invalid customer numbers
C endif
C
C write RptLine
C
C read XactsR
C enddo
C
C eval * inLR = *on
C*****
C ErrorRoutine begsr
C
BEGIN LABEL C
C if not %open(ErrorRpt)
END LABEL C
BEGIN LABEL D
C open (e) ErrorRpt
END LABEL D
C if %error
... do an abend routine
C endif
C endif
C
BEGIN LABEL E
C if %open( ErrorRpt)
END LABEL E
C write ErrorLine
C endif
C
C endsr A INDARA
... more specs
A R SFLCTL SFLCTL(SFL)
A CF03(03 Exit)
A CF12(12 Previous screen)
A 21 SFLDSP
A 20 SFLDSPCTL
A 22 SFLCLR
A 23 SFLEND(*MORE)
A SFLSIZ(0011)
A SFLPAG(0010)
Figure 2: A fragment of a display file containing conditioning indicators
FCustListDFcf e workstn sfile(sfl: rrn)
F indds(Conditions)
... more F specs
D Conditions ds 99
D EndProgramWasRequested...
D 3 3n
D CancelScreen 12 12n
D SflDspCtl 20 20n
D SflDsp 21 21n
D SflClr 22 22n
D SflEnd 23 23n
... some C specs go here
C
C eval SflClr = *off
C eval SflDspCtl = *on
C eval SflDsp = *on
C eval SflEnd = *on
C exfmt sflctl
C
C if EndProgramWasRequested
Figure 1: This program illustrates some of the new features of RPG IV
Figure 3: This RPG program does not have to refer to device file indicators by number
ACTGRP
ALWNULL
AUT
BNDDIR
CVTOPT
DFTACTGRP
ENBPFRCOL
FIXNBR
GENLVL
INDENT
LANGID
OPTIMIZE
OPTION
PRFDTA
SRTSEQ
TEXT
TRUNCNBR
USRPRF
LATEST COMMENTS
MC Press Online