This week I am beginning a 3-part series on Free-Format RPG IV. Originally introduced in IBM i 5.1, free format has only recently been implemented on a widespread basis. Until now, most people have stuck with the traditional or hybrid RPG IV syntax.
RPG IV has been an interesting language. It's one of the only languages that has multiple syntax implementations in the same iteration of the compile.
When RPG IV was first introduced, it had an expanded but compatible syntax to support code written for its earlier implementations such as RPG III and RPG II. This syntax allows you to migrate RPG III code (and RPG II with a few more steps) to RPG IV, recompile and go.
The downside here is that it also allowed you to continue to write in RPG III-style; while not required, it did provide an outlet for a lazy-shop standard to "force" programmers to write in RPG III style while in RPG IV. Did you really believe you would somehow port the RPG IV code back to RPG III? And if so, why?
Also introduced with RPG IV was the so called hybrid syntax. This allowed RPG IV developers to write code that utilized expressions. For example, instead of coding something like "X ADD Y Z," the RPG IV programmer could write "Z = Z + Y". While standard in virtually all other high-level languages, this was a huge advantage over RPG III, particularly for conditional statements.
The EVAL opcode was also introduced to allow expressions for both string and numeric statements. So now instead of coding this:
.....CL0n01Factor1+++++++OpCode++++Factor2+++++++Result++++++++Len++DcR1R2R3
C CustNo Chain CustMast 71
C *IN71 IFEQ *ON
C CUSTNO OREQ 9999
C MOVE *BLANKS ERRMSG
C MOVEL 'Not Found' ERRMSG
C ENDIF
we could code like this:
.....CL0n01Factor1+++++++OpCode++++Factor2+++++++Result++++++++Len++DcR1R2R3
C CustNo Chain CustMast 71
C If *IN71 = *ON or CustNo = 9999
C eval errMsg = 'Not Found.'
C endif
Then in 5.1 IBM added Free-Format syntax. Originally, IBM really wanted to do free format but thought it would cost a lot more, so it anticipated a much later arrival period for it. The author of the original RPG IV compile (ported from the mainframe, by the way) came up with an innovative idea and effectively implemented it in a week.
One of the problems you have whenever a new syntax or feature is introduced is providing a high level of backwards compatibility with existing code. If I move to free format, can I code the way I used to code, with subtle changes of course, and not lose anything?
Sadly, the answer was a resounding NO! The free-format syntax did not (and still doesn't) support several key RPG IV interfaces. Probably the biggest issue was IBM's decision to not include a MOVE and MOVEL operation in free format. They felt that the EVAL opcode would handle most of what MOVE/MOVEL handled. Problem was, MOVE is "move right-justified" and EVAL is "move left-justified". And this is only the second biggest issue with not having MOVE/MOVEL support in free format. The other I'll address later in this article.
So how would our example code be specified in free format?
C/free
Chain (custno) custmast;
If NOT %Found() or custno = 9999;
errMsg = 'Not Found.';
endif;
/end-free
As mentioned, in version 5.1 of the operating system, IBM introduced a new syntax into RPG IV. This syntax is called free format. To code an RPG IV statement in free format, the programmer must insert a directive into the Calculation specifications that tells the syntax checker that free-format syntax has begun.
The /FREE directive starts free-format syntax. It must be specified beginning in column 7 of the Calculation specifications. As with all RPG compiler directives, a "C" in column 6 is not necessary. Nothing else may appear on the line following the /FREE statement.
To end free-format syntax, the /END-FREE directive is used. Unlike the /FREE statement, the /END-FREE may start in any position on the line between columns 7 to 72; it does not need to start in position 7, although it typically does. Nothing may appear in column 6 of the /END-FREE statement.
Once you've entered into free format, operation codes must be entered in free-format syntax. Many opcodes appear in free format in the same syntax as they do in regular fixed-format RPG IV; however, some of the legacy opcodes, such as CHAIN, READ, and SETLL, have a subtle but necessary syntax change as follows:
| Factor 1 | OpCode | Factor 2 | Result | R1 | R2 | R3 |
|---|---|---|---|---|---|---|
| key | CHAIN(n) | file | N/F | Err | ||
| key | SETLL | file | GT | Err | EQ | |
| [*NOKEY] | CLEAR | [*ALL] | variable |
| OpCode | Factor 1 | Factor 2 | Result |
|---|---|---|---|
| CHAIN(n) | Key | file; | |
| SETLL | key | file; | |
| CLEAR | [*NOKEY] | [*ALL] | variable; |
Note that in free-format syntax, a semi-colon terminates the statement. This is a common omission, and a cause of most compile-time errors. The best thing to do is force yourself to enter the semi-colon so often that it becomes second nature.
Below is an example of the traditional fixed-format syntax and equivalent free-format syntax:
.....CL0n01Factor1+++++++OpCode++++Factor2+++++++Result++++++++Len++DcR1R2R3
C CustNo Chain CustMast 71
C If *IN71
C eval errMsg = 'Customer Not Found.'
C endif
C/free
Chain (custno) custmast;
If NOT %Found();
errMsg = 'Customer Not Found.';
endif;
/end-free
The area between /FREE and /END-FREE is, as the name implies, free format, but with a few caveats:
A free format statement may begin in position 8 and continue through position 80. Most programmers, however, prefer to end the statement before column 80 for readability.
If an RPG statement will not fit on a single line, or you prefer to use fewer positions to enter your RPG statement, you may continue the statement onto subsequent lines. RPG has no statement continuation symbol. You simply continue the statement onto the next line as if it were all one line. The RPG IV parser looks for a semi-colon ';'. Until it detects it, it considers everything to be part of the single operation/statement. Once found, it ends the statement. For example, the following two examples are equivalent:
C/free
eval msgText = 'Customer ' + %char(custno) + ' not found. ';
eval msgText = 'Customer '
+ %char(custno) + ' not found. ';
/end-free
One frequent error that occurs regardless of your experience with free format is to forget to enter the semi-colon after the statement. If you do this, the compile will often identify the next statement as being in error, rather than the statement with the missing semi-colon. If the error you receive indicates a syntax error or "unexpected token" on a line that isn't (in your view) in error, it must be that a missing semi-colon for the previous operation/statement is causing the problem.
When concatenating multiple literals, one common mistake people make is confusing the concatenation symbol that RPG IV uses (the plus sign (+)) with the function it performs in DDS and CL's (continuation).
In RPG, the plus sign is used as the concatenate symbol and as a literal continuation symbol. It is not used to continue a statement in RPG IV.
In most situations, there never needs to be a plus sign specified at the end of a line when continuing that line. For example, the following two valid statements are identical in RPG IV:
C/free
(1a) eval msgText = 'Customer ' +
(1b) %char(custno) +
(1c) ' not found.';
(2a) eval msgText = 'Customer '
(2b) + %char(custno)
(2c) + ' not found.';
/end-free
Note the plus sign at the end of lines 1a and 1b is not used on lines 2a and 2b because it is a concatenation symbol, not a continuation symbol and therefore may appear anywhere on the line--having no impact on statement continuation.
When literals or field names are continued onto a second line, you may break the literal or field name into parts and must use a special continuation symbol.
To continue a literal, insert a plus sign and continue the literal on the next line. For example:
C/free
eval msgText = 'The total due by +
Customer ' + %char(custno) +
' is ' %char(amtdue);
/end-free
To continue a field name, an ellipse must be specified. The ellipse is specified in RPG IV as 3 consecutive periods. For example, the following statements use the long field name PRODUCTDESCRIPTION to build a message:
C/free
eval msgText = 'Item ' + %char(itemno) + ' ' + product...
description;
/end-free
In this example, the PRODUCTDESCRIPTION field name is continued on a second line. The first part of the variable name "PRODUCT" is specified on the first line, followed by three periods (an ellipse). The remainder of the field name "DESCRIPTION" is specified on the second line. There is no restriction on where you break a field or data structure or subprocedure name across multiple lines.
Switching to free format requires that you apply contemporary coding techniques rather than rely on many old RPG III and RPG II-style habits. This new style isn't optional, it is required. Many legacy operation codes no longer work when using free format. So in order to move to a style that's compatible with free format, you have to let go of old habits.
The best way to learn free-format RPG IV is to write it. Another way is by seeing side-by-side comparisons of code in fixed and free format that performs the same task.
The integrated Fixed-To-Free-Format conversion tool, built into WDSC (now called "RDi"), is by far the easiest way to convert fixed-format code that has a high level of free-format compatibility to free format. Simply highlight any fixed-format statements in a source member you've opened for edit in RDi, and right click. Then select "Convert to free-format". RDi will attempt to convert as much of the code to free format as possible. It will insert a beginning /FREE directive and an ending /END-FREE directive where necessary. Often multiple /FREE... /END-FREE pairs are inserted as some code simply does not convert to free format. That code is left untouched by RDi.
Certainly the fixed-format operation codes that have been used for years, in billions of lines of RPG code can be converted, right? Not likely. Ironically, many of the opcodes used in day-to-day RPG II and RPG III programming cannot be converted (at least by the conversion tool) to free format.
The widespread use of some opcodes that IBM has decided not to implement in free format, has been one of the top causes for people procrastinating the move to free format. Specifically, the following operation codes are NOT supported in free format:
This is only a partial list. However, with the exception of the MOVE and MOVEL opcodes, all these deprecated opcodes have free-format equivalents that are, in my opinion, easier to use. For example, the +, -, *, and / symbols are used for math instead of ADD, SUB, MULT, and DIV opcodes. The DOWxx and other conditional/looping opcodes have been replaced with true express-based conditional statements such as DOW, DOU, and IF. Some third-party software such as the CodeStudio RPG editor for Microsoft Windows I wrote in the early to mid-1990s do convert DOWxx, DOUxx, and IFxx to free format.
If any fixed-format code contains these opcodes, it may or may not convert to free format using the RDi conversion tool.
The MOVE and MOVEL opcodes do not work in free format because, well, I'm not sure why they are not implemented, but they aren't. In many conventional situations, the MOVE opcode can be converted into a free-format EVALR (eval with right-adjust) opcode, and MOVEL may be converted into an EVAL opcode. However it is not always so straightforward.
MOVEL is really a polymorphic operation and was one long before IT Grad Students were using that word in a sentence. MOVE/MOVEL allows you to:
And this is just off the top of my head; but there are many more.
That's all for this week. Next time I'll illustrate how to implement the above limitation in free format using contemporary coding techniques. Some will be brief and wow you, while others will introduce complexity and be a bit too long in my opinion, but we'll cover this next time.
Follow Bob Cozzi on Twitter at: Twitter.com/bobcozzi
Bob Cozzi is the author of Subprocedures and Service Programson DVD. A 3-disc training series that gives RPG IV programmers an easy way to learn how to get started with RPG IV Subprocedures and of course Service Programs. It is available today at www.RPGWorld.com/DVD. Bob's website www.RPGWorld.com is also the place to download the source code he features here in RPG Coder and additional examples he has created over the decades. The RPGWorld.com website welcomes thousands of System i RPG IV developers from all over the world, who share ideas and help each other with technical issues.