The C-specs are where everything happens. It is therefore important that you understand the workings of the C-specs.
Each C-spec executes an operation (such as add, multiply, read a record, turn off an indicator, or compare two variables for equality). This operation (RPG programmers usually call it "op code") is coded in columns 26–35.
Calculation specs come in three different varieties. This fact may be confusing to the newcomer to RPG, but supporting three different types of calculation specifications is necessary so that the RPG compiler can continue to compile source code that was written before more modern features were introduced.
Traditional C-specs have a rather simple organization. They are divided into a few fields that never vary in meaning or purpose. Here is what the C-spec contains:
The specification ID (C) in column 6. There is no escaping this requirement. All C-specs must have a letter C in column 6.
A control level indicator in columns 7–8, which is used if you want to perform an operation during the total time that control-level indicator is on. C-specs that have a control-level indicator in columns 7–8 must be coded at the end of the C-specs. This entry is optional.
Conditioning indicators are specified in columns 9–11. This entry is optional. The presence of indicators in these columns conditions the C-spec so that it is executed only if the indicator conditions are met.
An entry labeled Factor 1 in columns 12–25. This entry may be mandatory or optional, depending on the op code entered in columns 26–35.
An op code in columns 26–35. This entry is mandatory unless the specification is a continuation line. These positions may also contain an operation extender, which further defines the operation specified. For example, an H extender in a numeric operation to multiply or divide a set of numbers tells the system to half-adjust (round off) the entry placed in the resultant field. Database file input operations allow the use of an N to avoid locking the record if the file is open for update.
An entry labeled Factor 2 in columns 36–49. Like Factor 1, it can be mandatory or optional, depending on the op code used.
A result field in columns 50–63 for fixed-format C-specs. Again, it can be either mandatory, optional, or even prohibited.
Result field definition (also only applicable to fixed-format C-specs). Columns 64–68 contain the length of the result field and, if numeric, columns 69–70 contain the number of decimal places. As a general rule, the use of these positions is frowned upon. It is preferable to use the D-spec for all internal definitions.
Comments in columns beyond 80. You can enter anything you want if you think it will help you understand what the C-spec is doing.
You can specify a comment by placing an asterisk (*) in position7 of any specification. The asterisk in column 7 changes the entire statement into a free-form comment. This method is generally considered the best way to record inline program documentation.
IBM began to relax RPG's fixed-format syntax by adding certain free-form areas within the H, F, D, and C specifications. In C specs, this was accomplished by merging columns 39 through 80 into an extended Factor 2. The op codes that support the extended Factor 2, such as EVAL, IF, DOW, DOU, and FOR, must be coded left-adjusted, beginning in Factor 1. The operands of these operations may be coded anywhere within the extended Factor 2 and may continue to subsequent lines.
RPG also permits certain operations to be coded in a completely free-format syntax. A free-format section is introduced by the /FREE compiler directive and is terminated with the /END-FREE directive.
Within a free-format section, the op code is coded first, followed by any of Factor 1, Factor 2, and Result Field. Comments begin with a double slash sequence (//) and continue through the end of the line. The code example in Figure 24.1 illustrates the use of free-format calculations:
Figure 24.1: Calculations may be entered in a free-format syntax.
RPG IV provides a rich set of file I/O operations, including:
READ. Reads the next record from the file specified in Factor 2. Factor 2 can also contain a record name if you are using externally described files.
READP. Reads the previous record. Similar to READ.
READE. Reads the next record that has the same key value.
READPE. Reads the previous record that has the same key value.
CHAIN. Reads a record randomly by record number or key value.
WRITE. Writes a new record to a file.
UPDATE. Updates the last record read from a file.
DELETE. Deletes the last record read from a file.
EXCEPT. Performs exception output on program-described files.
RPG IV provides several structures you can use for decision making within your program:
IF, ELSEIF, ELSE, ENDIF. The IF operation can be used in two ways. It can be used for simple compares, in which the operand indicates how a comparison will be performed. In these cases, the statement is coded as IFXX where xx represents the type of compare. Equal-to is coded as IFEQ, greater than is coded as GT, and so on. But the IF statement can also perform a free-form comparison of the variables as described in Factor 2. How they are compared depends on how the free-form expression is constructed. If you code the equation using an equal to (=) sign, they are compared for equality. Other values are not equal, less than (<), less than or equal to (<=), greater than (>), and greater than or equal to (>=). See the example in Figure 24.2.
Figure 24.2: RPG IV example of IFxx and ELSE specifications.
This code executes the WRITE operation if "CustNbr" is greater than 500. If not, the ELSE operation dictates that the UPDATE operation be executed. The ENDIF marks the end of the decision group.
AND and OR can be used to create more complex free-form equations. You can add these operations immediately after a free-form expression to combine more than one comparison. An example is shown in Figure 24.3.
Figure 24.3: RPG IV example of IFXX and ORXX specifications.
This example is a modification of one shown in Figure 24.2. The WRITE operation is executed if "CustNbr" is greater than 500 or if "CrdCde" is equal to ‘T.’ In any other case ("CustNbr" less than or equal to 500 and "CrdCde" not equal to ‘T’), the program executes the update operation.
DO/ENDDO. The DO operation causes the repetition of all the statements between it and the ENDDO that follows. That repetition is performed for increasing values of a control variable (the Result field), from the value indicated in Factor 1 to the value in Factor 2. Each repetition increases the control variable by 1, unless indicated in Factor 2 of the related ENDDO.
If Factor 1 or Factor 2 is omitted, a value of 1 is assumed. If the Result field is omitted, the compiler uses an internal control variable.
DOWXX/ENDDO and DOUXX/ENDDO. The DOWXX and DOUXX operations are similar to IFXX in that they too accept a two-letter modifier like EQ and NE. DOWXX (Do While) repeats the statements enclosed between it and the ENDDO that follows, for as long as the comparison between Factor 1 and Factor 2 is true. DOUXX (Do Until) repeats the statements until the comparison is true. Like IFXX, both DOWXX, and DOUXX accept ANDXX and ORXX modifiers. But, just as the IF statement, the DO operation may be used to create free-form expressions too. See the example in Figure 24.4.
Figure 24.4: RPG IV example of DOUXX specifications.
This piece of code executes the statements between the DOU (Do Until) and the ENDDO until Complete is equal to ‘Y.’ Because the DOU operations perform the test at the ENDDO, the statements included would be executed at least once, even if Complete were equal to ‘Y’ to begin with. On the other hand, the DOW (Do While) operations perform the comparison immediately before they start the sequence of statements included. If the comparison doesn't hold true the first time, the statements included would not be executed at all, not even once.
ITER and LEAVE. These two operations can be included in any DO, DOW (Do While), or DOU (Do Until) group. LEAVE (as the name suggests) leaves the group immediately, transferring control to the statement that follows ENDDO. You can use leave when you have accomplished what you wanted to do in the DO, DOW, or DOU group and need to get out of it. ITER (Iterate) transfers control to the statement that performs the comparison. If that test yields a positive result, execution continues. ITER can be used to skip the rest of the current execution of the loop, in order to go to the next one.
EXSR. Use EXSR (Execute Subroutine) to execute a subroutine coded within the program. The subroutine must begin with BEGSR (Begin Subroutine) and end with ENDSR (End Subroutine). The subroutine can contain EXSR statements to execute other subroutines. When the program executes the ENDSR operation, control returns to the statement immediately after the EXSR.
CALL and PARM. You can use the CALL operation (followed by optional PARM operations) to execute a different program from within your RPG module. It works like EXSR, except that the statements executed are not within your program, but in another. PARMS allow you to pass parameter data to the called program and/or obtain information back from it.
SELECT, WHENXX, OTHER, and ENDSL. The IFxx operation, when combined with ELSE, performs a two-pronged decision fork. Execution can follow one path or the other. If you need more than two paths, use the SELECT operation group, as shown in Figure 24.5. Note that any of the WHENXX operations could have been combined with ANDXX or ORXX.
Figure 24.5: RPG IV example of the SELECT and WHENXX specifications.
This piece of code executes segment 1 when CODE equals ‘A,’ or executes segment 2 when CODE equals ‘B,’ or segment 3 when CODE equals ‘C.’ Otherwise (if none of the WHEN tests holds true), it executes segment 4.