We in the RPG compiler development team at IBM think that V5R1 is the most significant release of RPG IV since V3R6/V3R2, when prototyped calls and subprocedures were introduced. The RPG IV enhancements in V5R1 fall into two main categories: functionality that makes it easier to write, read, and maintain your RPG code; and new functionality.
Totally Free-form Calculations
Perhaps the most noticeable enhancement to RPG is the addition of free-form calculations. Figure 1 shows a small example of the new free-form calculations in RPG IV. They start with /free and end with /end-free.
Free-form statements begin with the op code, are followed by one or more of factor 1, factor 2, and the result field, and end with a semicolon (;). You can code a statement on more than one line if you like, but you can only code one statement per line. You can leave out the EVAL and CALLP op codes if you want, unless you have operational extenders such as EVAL(H).
If a procedure call has no parameters, you must code empty parentheses as a parameter list. In traditional calculations, you may code the empty parentheses or not, however you choose.
In a free-form calculation, you begin comments with //. The remainder of the line is a comment. Line 11 of Figure 1 is a full-line comment, while line 18 has an end-of-line comment. You can also use // for full-line comments in traditional specifications, but endof-line comments are not allowed.
Not all the traditional fixed-form op codes are allowed in free-form calculations. However, several new built-in functions allow you to do most of your coding in free-form calculations. Figure 2 (page 78) shows a table of op codes that are not supported in free- form calculations, with the suggested replacement coding for free-form calculations. You can use SEU to code your free-form calculations, but no syntax checking will be done.
Data Structure Enhancements
The new QUALIFIED keyword for data structures allows you to name your subfields without worrying whether the name has already been used in the program. When you specify a subfield of a qualified data structure in calculations, you qualify the subfield name with the owning data structure name. For example, the data structure attrs has a subfield age. To use this subfield in calculations, you code attrs.age.
D attrs DS QUALIFIED
D age 10I 0
D height 4F
D weight 4F
EVAL attrs.age = 10
Since the subfields cannot be used alone, you are free to use the same names again within the same source member. You could reuse the name as a subfield in another data structure or as an ordinary item such as a file, standalone field, or subroutine. If two data structures have subfields with the same name, the subfields are completely independent; so the definitions of the subfields do not have to match at all. When qualified subfield names are continued across two lines, you can break the name after the dot, and avoid using the usual three dots:
D price DS QUALIFIED
D today 11P 3
D min 11P 3
D part DS QUALIFIED
D name 100A VARYING
D price 15P 3
D today S D DATFMT(*ISO)
Another new D-spec keyword, LIKEDS, says to define one data structure with the same subfields as another data structure. The new data structure is automatically a qualified data structure:
D myAttrs PR LIKEDS(attrs)
EVAL myAttrs.height = 168.9
Using LIKEDS, you can easily define several data structures alike:
D norm DS LIKEDS(attrs)
D cand DS LIKEDS(attrs)
if %abs(cand.age - norm.age) > 25;
sendMsg ('Abnormal age'
: candidate.age);
endif;
What makes LIKEDS very powerful is that you can use it for prototyped procedures on both the return value and the parameters. This gives you the ability to receive a data structure as a parameter:
P chkAttrs B
D chkAttrs PI
D at LIKEDS(attrs)
D CONST
C RETURN at.age > MIN_AGE
C AND
C at.height > MIN_HEIGHT
C AND
C at.weight < MAX_WEIGHT
P chkAttrs E
You cant initialize individual subfields of a data structure defined with LIKEDS, but you can initialize the new data structure the same as the parent data structure using INZ(*LIKEDS).
More Granular Exception Handling
The MONITOR group has been added to RPG to allow for more localized and more general exception handling. The MONITOR group is very similar in concept to the CL MONMSG, except that, with the MONITOR group, you can monitor as many statements as you want.
The MONITOR group starts with the MONITOR op code and ends with the ENDMON op code. The first part of the MONITOR group is the MONITOR block, which contains the statements being monitored for errors. One or more ON-ERROR blocks follow the MONITOR block. These start with an ON-ERROR op code listing the status codes for the errors you want that ON-ERROR block to handle. The rest of the ON- ERROR block contains the code to handle those errors. You can code as many lines in each ON-ERROR block as you like.
You can code three special values in the ON-ERROR list:
*FILEErrors dealing with files
*PGMProgram errors
*ALLAll errors
You can nest MONITOR groups with other structured groups, including other MONITOR groups. If an error occurs in an inner MONITOR group that is not handled by that monitor, the error can be handled by the outer group.
If you call a subroutine from a MONITOR block, or if you do an input or output operation that uses I- or O-specs, any errors in the subroutine or I/O specs will be handled by the monitor. Of course, the subroutine could have its own MONITOR group to handle its own errors; in that case, the MONITOR group containing the EXSR would only handle the errors not handled by the subroutines monitor.
Figure 3 (page 79) shows an example of a MONITOR group. The blue section is the code that is being monitored. The first ON-ERROR block handles open errors; the second ON-ERROR block handles several errors that might occur handling the data; the last one handles all other errors.
More Control over File Opens
The new F-spec keywords EXTFILE and EXTMBR allow you to specify the file to be opened. You can use either literals or variables as the parameters to these keywords. Using a variable for either of the keywords allows you to wait until runtime to decide on the actual file without using an override command.
The EXTFILE parameter must be in the form LIBRARY/FILE; the library can be *LIBL. For EXTMBR, the name can be *FIRST or *ALL.
Figure 4 has an example of a program using EXTFILE and EXTMBR. This program is the command processing program for a command that has three parameters: a file name, a member name, and an attribute character. The program sets all comment lines to the specified attribute. You can download full source code for the command and the RPG program at www.midrangecomputing.com/mc
.
Easy Interaction with Java
A new form of the EXTPROC keyword makes it very easy for RPG programmers to call Java methods and write Java native methodsJava methods that are actually procedures written in another language. In the EXTPROC keyword, you say that you are prototyping a Java method, and you give its class. You can specify that the method is static by using the STATIC keyword.
When you call an instance method (a nonstatic method), you specify the object instance by coding an additional first parameter. In Java, you might code string. getBytes(); in RPG, you would code this getBytes(string): If you want Java to call your RPG procedure, you tell Java that your procedure is a native method, and you tell RPG that your procedure is a Java method.
class MyClass
{native int trimLen (byte[] string);}
DtrimLen PR 10I 0 extproc(*JAVA
D :'MyClass'
D :'trimLen')
D string 100A varying const
Then you code your subprocedure normally.
P trimLen B export
D trimLen PI 10I 0
D string 100A varying const
C RETURN %len(%trim(string))
P E
These are the big changes to RPG. There are several more small enhancements that you can find out about by reading the Whats New in This Release section of the V5R1
DgetBytes PR 65535A extproc(*JAVA
D :'java.lang.String'
D :'getBytes')
D varying
You can declare Java objects to be used with Java methods. You use the new CLASS keyword.
Dstring S O class(*JAVA
D :'java.lang.String')
eval data = getBytes(string)
RPG manuals. You can find the manuals at http://publib.boulder.ibm.com/pubs/ html/as400/infocenter.htm.
REFERENCES AND RELATED MATERIALS
iSeries 400 Information Center: http://publib.boulder. ibm.com/pubs/html/ as400/infocenter.htm
/free
callp(e) filePrep(filename);
if %error;
cleanup('Error handling file' + filename);
return;
endif;
open custFile;
setll klist custRec;
reade klist custRec;
dow not %eof(custFile);
// correct the area code
if areaCode = OLD_AREA_CODE
and custCity <> *blanks;
custAreaCode = getNewAreaCode(custCity);
endif;
reade klist custRec;
enddo;
cleanup(); // normal cleanup
/end-free
Figure 1: Free-form RPG IV calculations are a departure from traditional RPG coding.
Opcode Suggested free-form replacement (if any)
ADD + operator
ADDDUR "+ operator with new duration BIFs %YEARS, %DAYS, %MINUTES, etc."
ALLOC New BIF %ALLOC
ANDxx AND operator
BITOFF, BITON No replacement
CABxx No replacement
CALL, CALLB CALLP opcode
CASxx SELECT group with EXSR
CAT + operator
CHECK New BIF %CHECK
CHECKR New BIF %CHECKR
COMP IF opcode
DEFINE Definition specifications
DIV / operator or %DIV
DO FOR opcode
DOUxx, DOWxx DOU and DOW opcodes
END ENDIF, ENDDO etc.
EXTRCT New BIF %SUBDT
GOTO No replacement
IFxx IF opcode
LOOKUP New BIFs %LOOKUP, %LOOKUPxx (arrays) and %TLOOKUP, %TLOOKUPxx (tables)
MOVE EVAL or EVALR with BIFs %CHAR, %UCS2 and %GRAPH, and new BIFs %DATE, %TIME and %TIMESTAMP
MOVEA EVAL
MOVEL EVAL with BIFs %CHAR, %UCS2 and %GRAPH, and new BIFs %DATE, %TIME and %TIMESTAMP
MULT * operator
Opcode Suggested free-form replacement (if any)
MVR %REM
MxxZO No replacement
OCCUR New BIF %OCCUR
ORxx OR operator
PARM Definition specifications
PLIST Definition specifications
REALLOC New BIF %REALLOC
SCAN %SCAN
SETOFF, SETON EVAL
SHTDN New BIF %SHTDN
SQRT New BIF %SQRT
SUB + operator
SUBDUR - operator with new duration BIFs %YEARS, %DAYS, %MINUTES
SUBST %SUBST
TAG No replacement
TESTB No replacement
TESTN No replacement
TESTZ No replacement
TIME New BIFs %DATE, %TIME and %TIMESTAMP
WHENxx WHEN opcode
XFOOT New BIF %XFOOT
XLATE New BIF %XLATE
Z-ADD, Z-SUB EVAL
Note: Some of the opcodes that have no free-form replacement, such as GOTO and TAG, will not likely ever
have free-form replacements. Others, such as BITON and BITOFF will likely have free-form replacements in the
future.
Figure 2: Many op codes are not supported in free-form calculations.
/free
MONITOR;
open file;
read file;
dow not %eof;
. . . handle the record
enddo;
ON-ERROR 1216;
error = 'File not found';
ON-ERROR 113 : 102: 103;
error = 'Error with input data';
addBadRrn (rrn);
ON-ERROR *ALL;
error = 'Unexpected error ' +
%char(%status);
return;
ENDMON;
/end-free
Figure 3: MONITOR groups provide a better way to trap errors.
Fqrpglesrc UF E DISK USROPN RENAME(QRPGLESRC:REC)
F EXTFILE(fileName)
F EXTMBR(memberName)
D fileName S 21A
// a type-definition for a library-qualified name
D qualName DS QUALIFIED
D name 10A
D lib 10A // the prototype for this program
D pgm PR
D filelib LIKEDS(qualName) CONST
D mbr 10A CONST
D attribute 1A CONST // the procedure interface for this program (entry parameter list)
D pgm PI
D filelib LIKEDS(qualName) CONST
D memberName 10A CONST
D attribute 1A CONST
/free
fileName = %trim(filelib.lib) + / + filelib.name;
open qrpglesrc;
Figure 4: The EXTFILE and EXTMBR keywords let you specify a files name at runtime.
LATEST COMMENTS
MC Press Online