The Geezer’s Guide to Free-Form RPG, Part 5: File Definitions
August 13, 2014 Jon Paris
While the changes in data definition introduced by the new free-form RPG support are great, I have to admit that it was probably the free-form file specifications that raised the biggest cheer from me. Let me tell you why.
I have always hated F-specs. Those nasty little single column codes drove me crazy. I could never remember what went where. I know I’m not the only one. All of the programmers we have taught RPG to over the last few years have also had similar problems coming to grips with with F-specs.
I am reminded of this almost every time I dive into coding, since F-specs remained as the only thing I ever needed the prompter for once I started to use RDi for all my development work. Now, for the first time ever, I am coding file definitions without prompting and without referencing the manual.
Happy, happy, happy!
So, let’s get into some details.
As with all the new declarations, file definitions begin with the characters “dcl-” for files, followed by “f”. It might have been nice to be able to spell out “file” as an alternative, but I’m happy enough with just the “f”.
The name of the file follows and here we encounter our first new feature. BIG file names! Or perhaps, to be more precise, the option to use meaningful file names. In the past we were stuck with using a traditional 10-character system name for our files, but no such limit applies in the new RPG. I really like this because it has always bothered me that determining the function of a file in a program invariably requires the use of some secret decoder ring. This is often worse in the case of print files where, for example, a monthly sales summary report might have a highly meaningful name such as SLSRPT0055. How much better it is to be able to use a meaningful file name. Of course it would be even nicer if we could also use meaningful record names, or indeed use the file name for all I/O operations on single format files, but I digress.
The downside is that you need to specify both the EXTFILE and EXTDESC keywords as you can see in the example below. I can’t help wishing that the compiler had not been as strict about this and had simply allowed EXTDESC and provided EXTFILE(*EXTDESC) as the default whenever it was used. Perhaps we’ll see this in the future.
Here’s the original fixed form version of a printer file definition:
FSLSRPT0055O E Printer OflInd(pageFull)
This is a straightforward translation:
dcl-f SLSRPT0055 Printer OflInd(pageFull);
And this uses the new long name support:
dcl-f MthSalesSummary Printer ExtDesc('SLSRPT0055') ExtFile(*ExtDesc) OflInd(pageFull);
The next entry following the name must be the device keyword, or alternatively LIKEFILE. If no device is specified then the compiler assumes a default of DISK.
Once the device has been specified then next come the device specific keywords. These are basically those that used to appear in the keyword area of the F-spec, and since these are basically unchanged I won’t deal with them here. There is, however, one new keyword, KEYED, which replaces the old “A” and “K” entries in the Record Address type field. The remaining single column entries, such as Limits Processing, are not supported in free-format. If you still need them then you must stick with a fixed format definition.
File Usage. . . At Long Last Sensible Defaults
As I noted in my first tip on this subject, one of the best parts of the new support is the use of sensible defaults.
No longer do we have to tell the compiler that files are externally described: it is the default! If you get nostalgic for the bad old days you can always add *EXT as a parameter to the device type keywordâ€”i.e., DISK(*EXT)–but why bother? Nor do we have to specify that a printer file is used for output. Output is the default usage for printer files! In a similar fashion, the file usage (input, output, both) also defaults based on the device type.
To give you the full picture, here are the defaults for the basic file types:
But the provision of sensible defaults doesn’t end there. It also comes into play even in cases where the default usage is not sufficient for the task at hand. The compiler takes an incremental approach. For example, in order to perform updates, the file must be defined as input capable. But you don’t have to specify that, the compiler provides *INPUT as by default when *UPDATE is specified. This table shows the defaults used:
Previously, if you specified a “U” to enable a file for update, it was also enabled for delete. As you can see from the table this is not the case in free-form. Specifying *DELETE implies *UPDATE, but the reverse is not true. To me this makes perfect sense.
In a similar vein, in order for records to be added to a file, *OUTPUT must now be specified. Previously file addition was specified by coding an “A” in a specific column. This resulted in the, to me, rather perverse situation of an apparent input file being capable of having new records written to it. Again, the new requirement makes a lot more sense.
Program Described Files
So far I have focused on externally described files because, while not the norm in the early days of RPG, they are in the vast majority these days. It makes sense then that the new free-form support makes external definitions the default.
Printer files are the major exception to the march away from program defined files. For some reason while many RPGers have accepted the benefits of externally described disk and display files, they have failed to embrace printer files with the same degree of enthusiasm. Go figure. Perhaps the fact that O-specs are not supported in free-form may be the final carrot that leads them to the right path. One can but hope.
To define a file as program described simply requires adding a length parameter to the device keyword. For instance, Printer(132). Similarly, in the unlikely event that you want to program describe a keyed disk file, you would need to add a key type and length parameter to the KEYED keyword. For example, KEYED( *Char: 5 ).
I hope you have found this “Geezer’s Guide” series useful. I’m sure there are things I have forgotten, or simply don’t know yet. As I discover them, I’ll be share them with you here.
For myself I have found writing this an interesting exercise and, as I have noted from time to time, found a few “tweaks” here and there that I’d like to see made in this support. Interestingly several of these concern default behaviors that I’d like to see extended. Interesting how picky one can get about such things once you see what can be done!
Jon Paris is one of the world’s most knowledgeable experts on programming on the System i platform. Paris cut his teeth on the System/38 way back when, and in 1987 he joined IBM’s Toronto software lab to work on the COBOL compilers for the System/38 and System/36. He also worked on the creation of the COBOL/400 compilers for the original AS/400s back in 1988, and was one of the key developers behind RPG IV and the CODE/400 development tool. In 1998, he left IBM to start his own education and training firm, a job he does to this day with his wife, Susan Gantner–also an expert in System i programming. Paris and Gantner, along with Paul Tuohy and Skip Marchesani, are co-founders of System i Developer, which hosts the new RPG & DB2 Summit conference. Send your questions or comments for Jon to Ted Holt via the IT Jungle Contact page.