The Geezer’s Guide To Free-Form RPG, Part 4: Prototypes and Procedure Interfaces
July 9, 2014 Jon Paris
As promised in Part 3 of this Geezer’s Guide, this time I am going to be looking at the new support for prototypes and procedure interfaces. There are not a large number of enhancements in this area. Mostly they consist of improvements in the compiler’s use of defaults. Of course they also inherit all of the data definition enhancements in areas such as data type and length.
Let’s start with prototypes and see how they have changed. The basic building blocks are dcl-pr and dcl-parm. As with dcl-subf in data structures, the dcl-parm is optional and only needed when someone has been foolish enough to give a variable the same name as an RPG op-code. I often use QCMDEXC as an example of a program prototype so I’ll start with that. Here’s a fixed form version:
d qcmdexc Pr ExtPgm('QCMDEXC') d cmd 500a Const Options(*VarSize) d cmdLength 15p 5 Const
And here is its free-form counterpart:
dcl-pr qcmdexc ExtPgm; cmd char(500) Const Options(*VarSize); cmdLength packed(l5: 5) Const; end-pr;
The only real difference between the two, apart from the free-form of course, is that if the name of the program to be called matches the prototype name then the program name parameter for the ExtPgm keyword is optional. The compiler will simply convert the prototype name to upper case and use that. So in the example coding ExtPgm was equivalent to coding ExtPgm(‘QCMDEXC’). This particular feature also seems to have been enabled in fixed form.
Prototypes can also use a short-form definition when no parameters are required. This is similar to the short-form support for Data Structures that I described in the previous tip. Here’s an example:
dcl-pr MyProgram EXTPGM end-pr;
One new feature that those of you who make frequent use of APIs may appreciate is the new *DCLCASE option for the ExtProc keyword. Previously if you were prototyping a procedure with a mixed-case name you had to specify the name to the ExtProc keyword. Now you can simply specify ExtProc(*DCLCASE) and the compiler will use the procedure name as you declared it on the dcl-pr. In the example below, the first prototype would call a procedure named ‘JONSTESTPROC’ whereas the second and third would call ‘JonsTestProc’.
dcl-pr JonsTestProc end-pr; dcl-pr JonsTestProc ExtProc('JonsTestProc') end-pr; dcl-pr JonsTestProc ExtProc(*DclCase) end-pr;
This is particularly useful for those who make extensive use of APIs that use mixed case names such as Qp0lRenameUnlink and Qp0lRenameKeep, where a simple mistyping of the name can be a cause of frustration and can be surprisingly difficult to spot.
Defining Subprocedures and Procedure Interfaces
Given all of the new declaration (dcl) types we have introduced so far, you can probably guess that the old beginning P-spec has been replaced by dcl-proc as you can see in the example below. Not surprisingly the ending P-spec is replaced by end-proc.
As in the case of fixed form procedure interfaces, the new free-form style matches that of the prototypes. It uses dcl-pi and end-pi to begin and end the declaration and the (mostly) optional dcl-parm for the individual parameters. As with data structures, the only real difference is that the placeholder *N must be used if the name of the subprocedure is to be omitted on the dcl-pi statement.
So that you have a direct comparison, the example shows both the fixed and free-form versions of the interface definitions for the subprocedure DateInfo. This subprocedure accepts a date in *MDY format and returns a data structure containing the day number, day name, and fully formatted date string.
Here is the fixed-form version:
d dateInfo_T1 DS Template d dayNumber 1s 0 d dayName 9a d dateString 40a Varying /end-free // DateInfo Subprocedure p DateInfo B Export d PI LikeDS(dateInfo_T) d inputDate D DatFmt(*MDY) Const /free ... /end-free p DateInfo E
And here is the free-form translation:
dcl-ds dateInfo_T Template; dayNumber zoned(1); dayName char(9); dateString varChar(40); end-ds; // DateInfo Subproceure dcl-proc DateInfo export; dcl-pi *N LikeDS(dateInfo_T); inputDate date(*MDY) Const; end-pi; ... end-proc DateInfo;
One final point related to the use of subprocedures and ILE in general. Another of IBM‘s sensible new defaults allows that if you have coded at least one free-form ILE related control statement such as ACTGRP, BNDDIR, or STGMDL, you no longer need to remember to specify DFTACTGRP(*NO). Not a big thing, but helpful nonetheless.
Next time I will take a look at the changes made to file specifications. Changes that will be warmly welcomed by every RPGer who, like myself, is convinced that fixed format F-specs, with all their arcane columns and codes, are truly the spawn of the devil.
Until then if you have any questions or comments, please let me know.
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.