Standardize Your Header Specification

Article ID: 56340

The RPG IV Header specification (called the "Control spec" only by those still working on the RPG compiler) is used in most applications being created today – it is difficult not to help elevate the boredom of prompting the CRTBNDRPG command from within PDM or forgetting to prompt it from within WDSc.

Note: The best RPG IV training you can find is going on this May in Las Vegas. Join Bob Cozzi, George Farr, Aaron Bartell, and others for RPG World. And use promotion code RPGCODER to save $100 off registration.

What good does it do? The Header specification can handle nearly all RPG compiler parameters so you don't have to remember which ones are needed to compile your source member. Or better yet, the programmer that follows you doesn't have to read your mind.

This feature allows you to embed the compiler parameters into your source code on the Header specification. This is such a cool feature that IBM Rochester added it to the CL compiler in i5/OS V6R1. Now if we can just get the Display File DDS folks to do the same . . .

Creating a standardized Header specification is only marginally challenging. The challenge is to create one that contains a set of standard settings that will unlikely change across all or nearly all applications in your shop. Many programmers are creating a set of generalized Header specification statements that work in the application they are currently maintaining rather than with most applications in their shop, and thus the reason for today's topic.

Most programming today includes some level of advanced RPG IV, and this means using subprocedures, C runtime functions, MI instructions, or an API or two. Calling a subprocedure or one of these other functions disqualifies the program from the default activation group. Therefore, DFTACTGRP(*NO) is a good choice for a standardized Header specification.

     H   DFTACTGRP(*NO)

If the default activation group is not being used, then in what activation group should the program be run? You could specify a standardized named activation group, for example:

     H   ACTGRP('MYACTGRP')

Some prefer ACTGRP(*CALLER) or ACTGRP(*NEW), but I usually like to name the activation group for most programs. The decision process behind the activation group choice is really not what this article is about and should be decided in your shop.

One problem with using DFTACTGRP an ACTGRP on the Header specification is that it isn't always allowed when compiling. For example, when the CRTRPGMOD command (PDM option 15) is used to compile the source member, you'll get a compile-time error if you use DFTACTGRP(*NO). Why do you get this error? IBM likes to generate errors, but they also are great at providing a workaround.

In addition to the DFTACTGRP and ACTGRP keywords, I recommend adding compile directives that will include these keywords only when the CRTBNDRPG command is used to compile the source member. Specify these directives and control the source code, as follows:

     H/IF DEFINED(*CRTBNDRPG)
     H   DFTACTGRP(*NO)
     H   ACTGRP('MYACTGRP')
     H/ENDIF

Adding these two directive statements above and below the keywords ensures that they will be included when the CRTBNDRPG command is used to compile the source. They will not be included when the CRTRPGMOD command is used. This is a great solution for standardized Header specifications.

Binding Directories

There have been myriad articles written that illustrate how to use C runtime functions, MI instruction, and various APIs from within RPG IV. In all cases, these functions and instructions require that the QC2LE binding directory be used at compile time. I'm surprised IBM hasn't included QC2LE in the default system binding directory. Perhaps someday they will, but until then BNDDIR('QC2LE') is a great candidate for your standardized Header specification.

     H BNDDIR('QC2LE')

Binary Fields Be Gone!

Most of you know my distain for "B" data-type usage in RPG IV. If you see it, it means (A) its legacy code that's never been updated, (B) IBM provided the code, or (C) somebody has some old habits they can't seem to break.

The "B" data type should never be used in RPG IV for any reason. To further that along, IBM has added a feature to the RPG IV compiler that will make sure that fields in database files that have the "B" data type are treated as "I" data types in RPG IV.

RPG III was the only language to use that curious "B" data type as a "B" data type. DDS actually stores these fields as integers, not RPG-style "B" fields. Most people don't realize this fact, but it's true.

IBM added the non-intuitive EXTBININT ("External Binary to Integer") keyword that ensures that the legacy-compatibility feature that RPG IV has that treats database "B" fields as RPGIII-style "B" fields is not used. Instead, it treats database "B" fields as integers. To turn this feature on, specify EXTBININT or EXTBININT(*YES) on your standardized Header specification.

     H EXTBININT(*YES)

Fixing an Ancient Hole in the RPG Cycle

Like a hidden leak in the ceiling that isn't noticed until you're ready to sell your house, the RPG Cycle had a subtle issue that IBM patched. But of course, IBM never wants to break existing code that may depend on certain features, so you have to insert the Header specification keyword in order to plug this hole.

The feature is the Overflow Indicator for printer files. Originally, RPG Didn't have the ability to close and reopen print files. But think about this; today, opening and closing print files is very common. When the program closes and then opens a print file, what is the status of the printer file's overflow indicator? The answer: Whatever it was when the printer file was closed.

This is one of those "facing into the wind, with your left hand on your hip, and the moon is blue" kind of things -- it is rare. But when it happens, you now have a tool to correct it:

     H OPENOPT(*INZOFL)

This oddly named option simply says: "Whenever a printer file is open, set off that printer file's corresponding overflow indicator." Why *INZOFL wasn't just another parameter of the OPTION keyword is beyond me, but it is what it is.

If you're a software developer and getting paid for your programs or a software house that distributes System i programs and service programs, a great standardized Header keyword is COPYRIGHT. This nearly always overlooked keyword inserts a copyright string into the compiled *MODULE object, which is subsequently embedded in the final *PGM or *SRVPGM object. Often I see a compile-time array with copyright info in it; this keyword is light years ahead of that technique.

     H COPYRIGHT('2008 - Robert Cozzi, Jr. All rights reserved')

That's all the keywords that I believe are generic/general purpose enough to warrant being included in a standardized Header specification. The next step is to place your standardized Header into its own /COPY source member and /COPY it into all your code.

     H/COPY SYSDEV/QCPYSRC,STDHDR

Where SYSDEV is a shared development library for your company, QCPYSRC is the /COPY source member (where a /COPY's are stored), and of course STDHDR is the standardized Header source member that contains the following, or a variation of it.

     H/IF DEFINED(*CRTBNDRPG)
     H   DFTACTGRP(*NO)
     H   ACTGRP('MYACTGRP')
     H/ENDIF
     H OPTION(*SRCSTMT:*NODEBUGIO)
     H BNDDIR('QC2LE')
     H EXTBININT(*YES)
     H OPENOPT(*INZOFL)
     H COPYRIGHT('2008 - xxx Company. All rights reserved.')

ProVIP Sponsors

ProVIP Sponsors