There are a many differences between fixed-format and DCL-*. Some subtle, some not so subtle, and a few that are downright painful.
Whether you're free-handing (pun intended) new free-format DCL-* specs or converting existing fixed-format H-, F-, or D-specs to free, this article shares what I learned while writing a free automated conversion tool to generate free-format DCL-* statements from fixed-format.
If you plan to write in /free, you may wish to keep this article handy as a quick reference of what you need to do to compile.
Check OS Version and PTF
DSPDTAARA DTAARA(QUSRSYS/QSS1MRI)—The first two positions of the value must be V7.
DSPPTF LICPGM(5770WDS) SELECT(SI51094)—Any CUM upgrades after January 2015 will have this PTF (or the superseding PTF) included.
If you do not have both the OS and PTF, please enjoy the rest of the article for future reference.
Turn SEU Syntax-Checking Off
Please note the new H, F, and D DCL-*free source code lines will reverse image as invalid in SEU. (I am still mad about %SCANRPL not being supported in V6R1 SEU). I turn the SEU syntax-checker off (F13 and N for syntax checking) and keep going.
CLASS, DATFMT, TIMFMT, and PROCPTR Convert to Data Type Extensions
Notice the fixed-format D-spec keyword DATFMT is not used in the dcl-s statement. The extension (*ISO) is now part of the date data type.
Datfmt Date Format
D wedate s d datfmt(*iso-)
dcl-s wedate date(*iso-);
D wkmdy s d datfmt(*mdy/)
dcl-s wkmdy date(*mdy/);
Timfmt Time Format
D TIMER s T TIMfmt(*iso)
dcl-s TIMER time(*iso);
Procptr Procedure Pointer
The asterisk (*) signifying a pointer data type is replaced with word POINTER data type. The PROCPTR keyword is an extension (*PROC) of the data type.
D CANCLHDLRPTR S * PROCPTR
D INZ(%PADDR('CANCLHDLR'))
dcl-s CANCLHDLRPTR pointer(*proc) inz(%paddr('CANCLHDLR'));
CLASS Java Object
The class word is dropped entirely and is now part of the OBJECT datatype extension. Notice the keyword data has been reformatted to fit in 74 characters. More on continuation rules later.
D nformulaevaluator...
D s o class(*java: 'org.apache.poi.ss.us+
D ermodel.FormulaEvaluator' )
dcl-s nformulaevaluator object
(*java: 'org.apache.poi.ss.usermodel.FormulaEvaluator' );
VARYING Keyword Removed and the VARCHAR Data Type Is Used
D BuildContin s 200a varying
dcl-s BuildContin varchar(200);
*NEXT Is Removed if the Overlay Keyword Is the Data Structure Name
I had concerns about this one at first and took a little while to test and verify. The *NEXT extension is truly redundant if overlaying the data structure name.
The *NEXT keyword is still valid if you are overlaying a data structure subfield. Notice line 27 overlays the data structure name and line 29 overlays a subfield.
0024.00 D nestds ds 100
0025.00 D aa1 1 4a dim(dimsize)
0026.00 D aa2 4a overlay(nestds:1)
0027.00 D aa3 4a overlay(nestds:*next)
0028.00 D bb1 1a overlay(aa1:1)
0029.00 d cc2 2a overlay(aa1:*next)
After conversion, the *NEXT at line 27 is removed. The *NEXT at line 29 remains in place.
0024.00 dcl-ds nestds len(100);
0025.00 aa1 char(4) dim(dimsize) pos(1);
0026.00 aa2 char(4) pos(1);
0027.00 aa3 char(4);
0028.00 bb1 char(1) overlay(aa1:1);
0029.00 cc2 char(2) overlay(aa1:*next);
0030.00 end-ds;
Also note line 26 changed from OVERLAY(nestds:1) to POS(1) notation as the field was overlaying the Data Structure name.
DS LEN Is Not Allowed with Extname
This one to me is like the enforced correction of an old wrong. I work on a lot of code with ambiguous code, like the DSNAME has a length and an EXTNAME.
D DSNAME E DS 1000 EXTNAME(FILENAME) .
The record length of FILENAME is not 1000. After conversion, the statement will look like this:
dcl-ds DSNAME len(1000) extname('FILENAME') end-ds;
And your compile listing will look like this:
*RNF3529 20 a 000010
Extname Keyword is not allowed for a program-described data structure; keyword is ignored.
Your solution is to remove the len(1000) and either change the program to work with the correct length or change the format of FILENAME to equal the data structure length required.
+ or - Lengths Are Now Part of the Data Type Extension, Packed(1: +2)
This change is a much better read than overloading the To/Length field in fixed-format.
D NextStepFlg s - 9 like(srUserStat)
dcl-s NextStepFlg like(sruserstat:-9);
Data Areas
I can only imagine an IBM memo came down from on high to the compiler writers that said, "Remove the *VAR keyword and make them remember all these syntactical nitpicking rules." (More about this memo when we get to the DCL-F specs usage keyword.) And to be clear, this is not the same memo that said "Cripple the loyal vast majority using SEU."
Data Area Names Will Be Quoted and Uppercased
Now, with data areas, you have to remember where to put a quote or uppercase. If your data area name is a not a variable or constant, you now must quote and uppercase the dtaara keyword name.
dcl-ds ScreenFieldDS extname(JCRFFDF:AA) end-ds; is not valid unless JCRFFDF and AA are a constant or a defined field name.
dcl-ds ScreenFieldDS extname('JCRFFDF':'AA') end-ds; // with quotes around each piece is how you have to do it now.
Data Area *VAR Modifier Is Removed
If your data area name is a variable name, do not put quotes around it.
UDS Requires DTAARA{name) {*AUTO}
Fixed-format allowed IN and OUT opcodes with UDS. If you are using these opcodes, change the *auto keyword to *userctl so these codes will still work
Quick Reference
Table 1 shows fixed-format keywords on the left and /free equivalents on the right.
Fixed-Format and Free-Format Data Area Keywords |
|
Fixed-Format Keywords |
/free Equivalents |
Dtaara(*VAR : runtimeDA) |
dtaara(runtimeDA) ; |
Dtaara(runtimeDA) |
dtaara('RUNTIMEDA'); |
uds dtaara(TESTX73) |
dtaara(*auto: 'TESTX73'); |
uds dtaara(*lda) |
dtaara(*auto: *LDA); |
Uds |
dtaara(*auto); |
uds dtaara |
dtaara(*auto); |
Dtaara |
Dtaara; |
Continuation Lines (+ and -) Must Be Reformatted as Keywords Are Expanded or Removed
I must confess to never having used the minus sign (–) continuation character, which was interesting as the continuation character can make a big difference when the definition space expanded from 37 to 74 characters.
In case I'm not the only person on the planet who didn't know the difference, the plus sign (+) keeps spaces only before it.
aa char(10) inz('A+
B');
Results in aa='AB'
The minus sign (-) preserves all the spaces before and after it.
aa char(10) inz('A -
B');
Results in aa='A B'
Please be aware I had to reformat your inz and constant values to allow for the number of spaces available in free-format. If you are manually converting, your plus sign continuations will be OK. You will have to move the characters after the minus sign to keep spacing correct.
D c@hars c const('abcdefghijklmnopqrstuvwxyzABC-
D DEFGHIJKLMNOPQRSTUVWXYZ<>?:;!@#$%¢&;*-
D ()-_=+¬¦{}\|<>,./?`~')
dcl-c c@hars const('abcdefghzjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY-
Z<>?:;!@#$%¢&;*()-_=+¬¦{}\|<>,./?`~');
Remove All /free and /end-free Statements
Yeah! Love it. We do not need these statements any more. Aesthetics aside, mix and match fixed and free as you wish.
Remove All PR Prototypes for Procedures Defined Internally
Here is even more to love. If the procedure interface is defined internally, meaning the procedure is inside this program source, you do not need to include the redundant PR definition. This includes the *entry parameters prototype.
This is the suggested *Entry procedure interface (with no PR):
//---*ENTRY--------
dcl-pi *n;
parm fields
end-pi;
You will need to have a dftactgrp keyword in your H-spec—sorry, I meant CTL-OPT statement—if you remove the *entry PR. Here is a standard CTL-OPT statement I use for general programming.
ctl-opt dftactgrp(*no) actgrp(*caller) expropts(*resdecpos)
datfmt(*iso) timfmt(*iso) option(*nodebugio: *NOUNREF);
Notice the new *NOUNREF keyword in the options string. To quote the manual, "*NOUNREF indicates that unreferenced variables should not be generated into the RPG module. This can reduce program size, and if imported variables are not referenced, it can reduce the time taken to bind a module to a program or service program." I have put this keyword in all my copy books and RPGLEHSPEC dtaaras.
*DELETE Will Be Added to the Usage Keyword If Record Is Deleted in Main or Procedure
Frankly, I could have gone the rest of the day without the dcl-f USAGE keyword and certainly the rest of my career without the *DELETE keyword in the usage statement. Not sure how we go from a simple, single, one-keystroke U for update in the F-specs to typing out USAGE(*UPDATE:*DELETE*OUTPUT) and call that progress.
IBM requires a usage (*delete) keyword if the file or any record format in that file has a delete opcode in the main or F-specs inside any dcl-proc. This massively complicates the F-specs source conversion as now I have to read the entire source, looking for DELETE opcodes by file or included record formats, and figure out if the DELETE opcode is in the main or in a procedure (and keep track of the procedure names containing the delete opcodes) and where the file was declared. Ugh.
An inclusive cross-reference of old F-specs versus new would be as long as the article to this point.
I have never told anyone to read the manual. Honestly though, your best bet is to review IBM i Version 7.1 Programming - IBM Rational Development Studio for I ILE RPG Reference section 5-39.
Below is an excerpt from the /free conversion utility JCRHFD that can be used for quick reference. Look for the usage string.
From the fixed-format F-specs: File Type is Input, Update or Output single character. Designation is Primary, Secondary, and Full etc. FileAddition is the A for add. IsDelete means I found a DELETE opcode in the main or in the procedure being processed.
//-------------------------------
if FileType = 'I'
and Designation = 'F'
and FileAddition = ' ';
if not (Device = 'DISK '
or Device = 'SEQ '
or Device = 'SPECIAL');
string = 'usage(*input)';
endif;
//-------------------------------
elseif FileType = 'I'
and Designation = 'F'
and FileAddition = 'A';
string = 'usage(*input: *output)';
//-------------------------------
elseif FileType = 'U'
and Designation = 'F'
and FileAddition = ' ';
if IsDelete;
string = 'usage(*update: *delete)';
else;
string = 'usage(*update)';
endif;
//-------------------------------
elseif FileType = 'U'
and Designation = 'F'
and FileAddition = 'A';
if IsDelete;
string = 'usage(*update: *delete: *output)';
else;
string = 'usage(*update: *output)';
endif;
//-------------------------------
elseif FileType = 'O'
and Designation = ' ';
if not (Device = 'PRINTER');
string = 'usage(*output)';
endif;
Please note primary and secondary files will not convert to free-format.
Positive Note
In my opinion, if we could ditch the usage keyword and the quote/uppercase requirements and fix the STRSEU syntax-checker, there are a couple of things I really like in the new /free. It is fun to be able to define a procedure with just DCL-PROC NAME; END-PROC.
Surprise Ending
The real reason I like the new /free has nothing to with the syntax but rather the IBM Rational Developer for i (RDi) Show Indentation window and the JCRCMDS JCRSDENT Show Source Indentation screen. Both tools show the new D-specs indented as structures.
It is easy to see the start and stop of data structures, prototypes, and procedure interfaces if they are outlined and indented.
An indented data structure (dcl-ds) listed in the RDI Show Indentation window is shown below in Figure 1.
Figure 1: The indented data structure looks like this.
The DCL-PR and DCL-PI indents so nicely it is just great, as shown in Figure 2.
Figure 2: And here's the indented dcl-proc and dcl-pi.
Free (no cost) RPG free-format source using the Free Software Foundation license for the free conversion tool is JCRHFD at www.jcrcmds.com. (That is a lot of free!)
LATEST COMMENTS
MC Press Online