The RPG IV language accepts operation codes on its calculation specifications, but there are actually three distinct syntax structures for calculation specifications. The first structure is the traditional
Traditional fixed-format calculations are the most widely used form of statement. This is due primarily to the legacy of RPG and its original fixed-format only coding. Today, RPG IV programmers primarily use a combination of the traditional fixed-format specifications along with the enhanced specifications.
Figure 12.1 contains an example of using the traditional fixed-format calculation specifications.
|
|
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++Len++DcHiLoEq 0001 C CustNo Chain CustRec 71 0002 C *IN71 ifeq *OFF 0003 C Add 1 Visits 0004 C Update CustRec 0005 C endif
|
|
In Figure 12.1, line 1 illustrates the CHAIN operation code, which is the common file access method used in RPG programs. Line 2 uses the deprecated IFEQ operation code to check for a record found condition. If the CHAIN operation is successful, *IN71 will be equal to *OFF,
Enhanced-format calculation specifications have been available since RPG IV was introduced. This style specification is the most popular for new applications and for maintenance (i.e., program changes) to existing applications. This style can be easier to use and may provide a level of productivity far beyond that of the traditional
|
|
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++ 001 C CustNo Chain CustRec 0002 C if %Found 0003 C Eval Visits = Visits + 1 0004 C Update CustRec 0005 C endif
|
|
In Figure 12.2, line one
The free-format specifications are a contemporary feature to the RPG language. They provide a syntax that is
Free-format specifications allow RPG operations to be specified in
Free-format operations must be specified between a /FREE and /END-FREE compiler directive. These directives must appear on a line by
Figure 12.3 illustrates an example of the free-format specifications. Note that the code is the same as in the example listed in Figure 12.2, but has been reformatted to the free-format syntax.
|
|
.....C/FREE++++++++++++++++++++++++++++++++++++++++++++++++++++ C/Free 0001 Chain CustNo CustRec; 0002 If %Found(); 0003Visits += 1; 0004 Update CustRec %Fields(Visits); 0005 endif; C/End-Free
|
|
Line 1, in Figure 12.3
Operation code syntax on free-format specification is substantially different from traditional
|
Traditional Syntax |
Factor 1 |
OpCode |
Factor 2 |
Result |
|
Free format Syntax |
OpCode |
Factor 1 |
Factor 2 |
Result ; |
Free format syntax requires a terminating semicolon at the end of all free format RPG IV statements. If a semicolon is not specified, a compile error will occur. The semicolon is required at the end of all operation code statements.
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++ C CustNo Chain CustRec ....../FREE++++++++++++++++++++++++++++++++++++++++++++++++++++ Chain CustNo CustRec;
Not all operation codes may be used in free-format. Most notably are the MOVEL and MOVE, and there is no direct replacement for them in free-format. Although the EVAL and EVALR operations do most of the function of MOVEL and MOVE respectively, they are not equivalent functions. Therefore a direct translation is not always available. If factor 2 and the result field of the MOVEL operation are the same datatype and length, then EVAL and MOVEL are equivalent. Likewise, if factor 2 and the result of the MOVE operation are the same length, then EVALR and MOVE are equivalent.
The primary difference between MOVEL and EVAL is that MOVEL is effectively a substring-like function. That is, if factor 2 is shorter than the result filed, the number of bytes
Contemporary RPG IV contains a number of syntaxes to perform simple math. Originally, the ADD, SUB, MULT, DIV, and SQRT operation codes were used to do arithmetic. Today, the EVAL operation can be used along with expressions to perform any mathematical formula. In addition, free-format syntax allows assignment statements (i.e., the EVAL operation) to be used with or without the EVAL operation code named. That is, the EVAL operation code name is optional on the free format specification. The following two statements are equivalent free-format syntax mathematical operations:
.....C/FREE++++++++++++++++++++++++++++++++++++++++++++++++++++ /Free 0001 Eval C = A + B; 0002 C = A + B; /End-free
There are several syntaxes that may be used to perform math. In fact, there are no less than eight
|
|
.....C/FREE++++++++++++++++++++++++++++++++++++++++++++++++++++ /Free 0005 Eval X = X + Y; 0006 Eval X += Y; 0007 X = X + Y; 0008 X += Y; /End-free
|
|
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++ 0001 C X Add Y X 0002 C Add Y X 0003 C Eval X = X + Y 0004 C Eval X + = Y
The /FREE and /END-FREE statements are required to start and end free-format syntax and are not
Traditional comments in RPG appeared on lines that contain an asterisk in position 7 of the source line. Figure 12.5 illustrates traditional comments.
|
|
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++ * Retrieve the customer record. If found, increment * the customer's visit counter and update the record. 0001 C CustNo Chain CustRec 0002 C if %Found 0003 C Eval Visits = Visits + 1 0004 C Update CustRec 0005 C endif
|
|
The first two lines of the source in Figure 12.5 are comments. The asterisk in position 7 causes the compiler to ignore the entire line.
With free-format RPG, an alternate comment syntax is provided that allows comments to be intermixed with the actual statements themselves.
In Figure 12.6 three comment statements are embedded within the source code. Note the double forward slash (//), that indicates the beginning of a comment. When // is
|
|
.....C/FREE++++++++++++++++++++++++++++++++++++++++++++++++++++ C/Free // Retrieve the customer record. 0001 Chain CustNo CustRec; 0002 If %Found(); 0003 Visits += 1; // Increment visits // Update the customer file 0004 Update CustRec %Fields(Visits); 0005 endif; C/End-Free
|
|
The alternate syntax for comments may be used within /FREE and /END-FREE statements and in place of traditional comments. Figure 12.7 illustrates using the alternate style comments with traditional RPG statements.
|
|
.....CSRn01Factor1+++++++OpCode(ex)Factor2+++++++Result++++++++ // Retrieve the customer recordd. 0001 C CustNo Chain CustRec 0002 C if %Found // If it is an existing customer // increment the Visits field 0003 C Eval Visits = Visits + 1 // then update the file 0004 C Update CustRec 0005 C endif
|
|
Note that the appearance of the // symbols may occur at any point on the line. Unlike free format syntax, however, when // comments are intermixed with traditional RPG calculation specifications, they must appear on a line by themselves.
Data structures and arrays have different syntax grammars when they are addressed by traditional RPG calculation specifications. The enhanced and free-format RPG syntax however supports a unified data structure and array syntax. This syntax is referred to as "data structures as arrays" or the simpler "array data structures." Figure 12.8 illustrates using data structures as arrays with the enhanced syntax.
|
|
.....DName+++++++++++EUDSFrom+++To+++++TDc.Functions+++++++++++++++++++ 00 01 D myStruct DS Dim(30) QUALIFIED 0002 D ItemNo 5I 0 0003 D ItemPrice 7P 2 0004 D Desc 20A 0005 D Prices S Dim(30) Like(myStruct.Price) 0006 D i S 10I 0 0007 C for i = 1 to %elem(myStruct) 0008 C eval Prices(i) += myStruct(i).ItemPrice 0009 C endfor
|
|
Figure 12.9 illustrates the same source code rewritten using free-format syntax.
|
|
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}
.....DName+++++++++++EUDSFrom+++To+++++TDc.Functions++++++++++++++ 0001 D myStruct DS Dim(30) QUALIFIED 0002 D ItemNo 5I 0 0003 D ItemPrice 7P 2 0004 D Desc 20A 0005 D Prices S Dim(30) Like(myStruct.Price) 0006 D i S 10I 0 /FREE 0007 For i = 1 to %elem(myStruct); 0008 Prices(i) += myStruct(i).ItemPrice; 0009 endfor; /END-FREE
|
|
In the examples in Figures 12.8 and 12.9 the data structure myStruct is a multiple occurrence data structure. In this syntax, however, these types of data structures are referred to as data structure arrays and may contain an array index in places the complex OCCURS operation. The DIM keyword (line 1) declares the number of elements for the data structure array named myStruct. When the DIM keyword is used, the data structure may be used within the RPG source member like an array. The SORTA and MOVEA operations may not be used with data structure arrays. In addition, only qualified data structures may be declared as an array. To declare a qualified data structure the QUALIFIED keyword is use. In addition, the LIKEDS or LIKEREC keywords may be used; with these keywords, the QUALIFIED keyword is
To access individual elements of a data structure array or regular array, parentheses are used (see line 8 in Figure 12.8 or 12.9). Within the parentheses a literal, named constant, field name, or procedure that returns a numeric value or a mathematical expression may be specified.
Manipulating date, time, or timestamp
Table 12.1 summarizes the differences between traditional fixed-format calculation specification date manipulation and free-format syntax.
|
Fixed-format Operation |
Free-format Syntax |
|---|---|
|
ADDDUR and SUBDUR – Add or subtract a duration. (Add a period of time to a date.) |
+ or – symbols along with the %YEARS, %MONTHS, %DAYS, %HOURS, %MINUTES, %SECONDS, and %MSECONDS built-in functions. e.g., StartTime = StartTime + %Hours(HRSWRK) |
|
SUBDUR – Subtract two date values. (Find the difference between two dates.) |
%DIFF built-in function. e.g., nHoursWorked = %DIFF(nClockIn : nClockOut : *HOURS) |
|
EXTRCT – Extract a component of a date. |
%SUBDT built-in function. e.g., nDayofMonth = %SUBDT(InvDate : *DAYS) |
|
TEST – Checking a variable for a valid date value. |
TEST opcode e.g., TEST(DE) *YMD ORDDTE // check non-date for date TEST(E) INVDATE // check date variable for valid date |
|
Duration codes |
Whenever a duration is needed, one of the duration code built-in functions may be used, including: %YEARS, %MONTHS, %DAYS, %HOURS, %MINUTES, %SECONDS, and %MSECONDS built-in functions. |
|
MOVE – Move a date value to a non-date value, or move a non-date value to a date value. |
The built-in functions %DATE, %TIME, and %TIMESTAMP may be used to copy a non-date value to a date field. The %CHAR built-in function may be used to copy a date, time or timestamp value to a non-date field. |
The bottom line is that date, time, and timestamp variables are manipulated with built-in functions when used in free-format syntax, and with operation codes when used with traditional syntax. Figure 12.10 illustrates the use of many of the date built-in functions.
|
|
.....DName+++++++++++EUDS.......Length+TDc.Functions++++++++++++++++++ D DueDate S D D DueDte S 6S 0 D InvDate S D INZ(D'2003-03-15') D Today S D Inz(*SYS) D nDayOfMonth S 5I 0 D nDays S 5I 0 /FREE 0001 Test(DE) *YMD DueDte; 0002 if NOT %Error; 0003 DueDate = %Date(DueDte : *YMD); 0004 nDayofMonth = %SUBDT(DueDate : *DAYS); 0005 endif; 0006 nDays = %DIFF(Today : DueDate : *DAYS); 0007 if (nDays > 30); 0008 DueDate = InvDate + %Month(1); 0009 DueDte = %Char(DueDate : *YMD); 0010 endif; /END-FREE
|
|
In Figure 12.10, free-format line 1 uses the TEST operation to check the non-date field named DUEDTE field for a valid date value. If the date is valid, the %DATE built-in function is used to convert the non-date value to the real date field named DUEDATE. Then the day of the month is extracted from the DUEDATE field (line 4) and assigned to the nDayofMonth field.
On line 6 the number of days between the TODAY and DUEDATE fields is calculated using the %DIFF built-in function. On line 7 the number of days is compared to 30, and if greater than 30, one month is added to the value in the INVDATE field and the result is assigned to the DUEDATE field..
On line 9, the 6-digit zoned numeric field named DUEDTE is assigned the date value currently stored in the DUEDATE field. The format of the date value in
The TIME operation code is traditionally used to retrieve the current system date, time, or timestamp value at runtime. TIME is not supported in free-format syntax. In place of the time operation, the %DATE, %TIME, and %TIMESTAMP built-in functions may be used.
Normally these built-in functions are used to convert a non-date, time or timestamp values into real date, time, or timestamp values. When used without a parameter, they return the current system date, time, or timestamp value.
On line 1 in Figure 12.11, the current system date and timestamp is assigned to the DTS field. On line 2 the current system time is assigned to the RIGHTNOW field. Then on lines 3, 4, and 5, the fields
|
|
.....DName+++++++++++EUDS.......Length+TDc.Functions+++++++++ D Yesterday S D D Today S D D Tomorrow S D D RightNow S T D DTS S Z /FREE 0001 dts = %Timestamp(); 0002 rightNow = %Time(); 0003 yesterday = %Date() - %days(1); 0004 today = %Date(); 0005 Tomorrow = %Date() + %days(1); /End-Free
|
|
Figure 12.12 illustrates a traditional RPG IV routine to fill up a subfile with records from a database file.
|
|
.....FFileName++IFEASFRlen+LKeylnKFDevice+.Functions++++++++++++++ FDSPCUST CF E WORKSTN SFILE(CUSTLIST : RRN) FCUSTMAST IF E K DISK /COPY FKEYS .....C*Rn01..............OpCode(ex)Extended-factor2++++++++++ C EVAL *INLR = *ON C EXFMT PROMPT C if FKEY = F3 C RETURN C endif C CUSTNO SetLL CustMast C if %FOUND C Read CustRec C DOW NOT %EOF C Add 1 RRN C Write CUSTLIST C CUSTNO ReadE CustRec C enddo C endif
|
|
Listed in Figure 12.13 is the identical routine rewritten in RPG IV free-format syntax.
|
|
.....FFileName++IFEASFRlen+LKeylnKFDevice+.Functions++++++++++++++ FDSPCUST CF E WORKSTN SFILE(CUSTLIST : RRN) FCUSTMAST IF E K DISK /COPY FKEYS /FREE *INLR = *ON; Exfmt Prompt; If FKey = F3; return; endif; Setll CustNo CustMast; if %Found(); Read CustRec dow NOT %eof(); rrn += 1; Write CustList; ReadE CustNo CustRec; enddo; endif; /End-Free
|
|
The free-format syntax of RPG IV provides more room on each line for expressions. Programmer habits may or may not lead to more readable code when using either syntax. One
There are several basic issues that may arise as a result of using free-format syntax for the first time. The following list may be helpful to those who have never used a noncolumnar language.
Always include a semicolon at the end of every RPG IV free-format statements. This includes conditional statements as well as all other statements, such as assignments and looping. Never include a semicolon at the end of traditional syntax RPG IV statements.
Start all RPG IV free-format statement groups with the /FREE compiler directive and end them with an /END-FREE compiler directive.
Embedded SQL statements may not be embedded between /FREE and /END-FREE statements.
The CALLP and EVAL operation codes are optional when used with free-format syntax. If unspecified, they are implied.
Parentheses are optional when used on parameterless built-in functions and procedure calls. However, it is highly recommended to use empty parentheses in order to visually distinguish between variables and procedures.