The following is a sample set of basic REXX Coding guidelines. They are meant to provide consistent naming and component usage without being overly restrictive.
Naming Standards
Library Naming Standards
The following describes the acceptable dataset naming standards for ISPF and REXX objects:
Component |
Low-level dataset qualifier(s) |
Description |
ISPLLIB |
ISPLLIB, LLIB, LOAD |
Load/executable modules |
SYSPROC |
SYSPROC, PROC, CLIST, EXEC, SYSEXEC |
REXX or CLIST executable modules |
ISPSLIB |
ISPSLIB, SLIB, SKELETONS |
File-tailoring skeletons |
ISPMLIB |
ISPMLIB, MLIB, MESSAGES |
Application-defined error message libraries |
ISPPLIB |
ISPPLIB, PLIB, PANELS |
Application panels |
Object Naming Standards
REXX programs and ISPF components use the following naming convention:
aastnnnn
where the symbols are represented by the following:
aa |
System Acronym. |
s |
Subsystem. See table below for current list of assigned subsystems. |
t |
Object type. M=Messages P=Panel S=Skeleton R=REXX Program C=CLIST Program @=Menu H=Help Panel |
nnnn |
Sequence number to allow for up to 999 programs within a given function. |
APPLID
aas
General Coding Guidelines
ISPF Panels
· Use the default )ATTR attributes whenever possible (e.g. do not code your own )ATTR section)
· The following ATTR statement (in addition to the standard definitions is also acceptable):
@ TYPE(INPUT) CAPS(ON) INTENS(HIGH) PAD(_)
)BODY section
The “header section” on the panel should adhere to the following format:
)BODY EXPAND($$)
%$-$ Title Goes Here $-$
+COMMAND ===>_ZCMD
+ Userid -@ZUSER
+ Date -@ZDATE
+ Time -@ZTIME
· Use the EXPAND option to center the title on the screen (and in this case place hyphens around the title). This will allow a panel to be changed to a popup without changes and will prevent errors.
· Ensure you use ZCMD as the field name for the panel. The panel should pass the contents of ZCMD back to ISPF to ensure users may consistently use the “dot” notation (e.g. 1.2.3.fa).
· Input fields should be followed by “==>“ as in the example below:
Saveid ==>_Version
)INIT section
)INIT
IF (&FUNCTION = &Z)
&FUNCTION = ‘LIST’
HELP = NFCH001
Provide default values if the values do not currently existing in any of the variable pools.
Ensure the .HELP panel is set to the appropriate help panel.
)PROC section
VER(&NFDBNAME,NONBLANK,MSG=NFOZ011)
If you require application-specific error messages for validation, ensure a format using the MSG parameter on the VER statement is used. This will ensure a consistent messaging interface.
ISPF Skeletons
Every skeleton member should contain the skeleton name itself within the resulting code (e.g. JCL). This will aid in determining which skeleton is the source of the problem if problems arise.
· )DOT…)ENDDOT should be avoided in skeletons if possible. It is preferable to code a loop in your program and include the skeleton multiple times. This is typically faster than )DOT…)ENDDOT/
ISPF-specific items
· Always use the ISPF function variable pool unless there is an explicit need to use the PROFILE or SHARED variable pools.
ISPEXEC VGET (VAR1, VAR2)
· If you place variables in the PROFILE or SHARED pool, the variable names should begin with the application and subsystem name (e.g. aas) to ensure uniqueness between in-house and vendor products.
ISPEXEC VPUT (aaDVAR1,aaDVAR2) PROFILE
· Do not use the ALTLIB activate command unless absolutely required!
· If PFKEYs are modified by the application, the application should save the existing setting and restore them at program termination.
REXX Programs
· All programs should be written in REXX unless there is a specific reason for coding the program in CLIST (and you should be prepared to provide a reason for justifying your choice).
· ISPF functions should use an error handler to trap errors as opposed to coding for each individual error which could result from an ISPF call.
‘ispexec CONTROL ERRORS RETURN’ /* APPL HANDLES ERRORS */
call ON ERROR NAME ISPERROR
call ON FAILURE NAME ISPERROR
….
ISPERROR:
call OFF ERROR /* PREVENT INFINITE LOOPS */
call OFF FAILURE
if RC > 8 then
do
SMSG = ZERRSM
LMSG = ZERRLM
‘ispexec VPUT (SMSG,LMSG)’
‘ispexec SETMSG MSG(ISRZ000)’ /* DISPLAY SYSTEM MESSAGE */
if EXECENV = ‘BACK’ then
do
say ZERRSM’:’
say ZERRLM
end
end
else
RETURN
signal CleanUp
RETURN
· Generic functions such as RxDB2 should be left as independent internal subroutines (e.g. do not make RxDB2 calls inline) – this will minimize the impact of changes to the RxDB2 procedure.
· Minimize the use of the INTERPRET command. While there are situations where this instruction is warranted, overuse will result in unreadable and hard-to-maintain code. If you do use it, you should document why you are using it.
· Major comment blocks describing program operation should be documented at the end of the program. Minor comment blocks should be inserted where required. For minor comment blocks, you should use the CBOX edit macro to ensure consistency. For major comment blocks, the following sample should be suffice:
/*******************************************************************/
/* */
/* Description */
/* */
/* A program description goes here */
/* */
/* Algorithm */
/* */
/* Describe the basic algorithm used by your program */
/* */
/* Input */
/* */
/* Describe any inputs such as parameters, filenames, etc. */
/* */
/* File Tailoring Variables: */
/* */
/* If you perform alot of file-tailoring, use common names and */
/* describe them here. */
/* */
/* MAINTENANCE: */
/* DATE USER DESCRIPTION */
/* ——– —- ————————————————–*/
/* MM/DD/YY JJT Enter date, initials and changes that are made. */
/* */
/*******************************************************************/
· Every function should contain a CleanUp label. Within this section you should close any remaining opened tables, free files, etc.
· SIGNAL should only be used in the CALL ON ERROR instruction or to branch to CleanUp. The LEAVE instruction should be used to prematurely exit looping constructs.
· Any invocation of the ISPSTART command with the NEWAPPL parameter should specify an APPLID of aas (see Naming Standards).
· The function should always return to the caller with the RETURN instruction (e.g. do not use EXIT).
· All programs receiving input parameters should be coded as follows:
/* REXX */
arg InputParms
parse value InputParms with …. (it would be preferable to use the ParseParms, etc. for this – see below)
· Stems: The 0th element (e.g. MyStem.0) should contain the number of entries in the entire stem.
Common Internal Subroutine Names
The following is a list of standard internal subroutine names (or labels), and they should only be used to accomplish the task described in Description. Sample code may be found in TEMPLATE:
Name |
Description |
Init |
Performs application initialization. “Hard-coded” values or initialization functions should be placed here. |
ParseParms |
Parses CLIST-style input parameters. This internal function should be copied from an existing program. Any program using the Parse, Check, or CheckAppl Parms functions should include the arg InputParms statement as the first executable line of the program. |
CheckParms |
Defines the allowable input keywords which may be specified for this application, parses them from InputParms, and assigns either the user-provided value or a default value (if the user does not provide the keyword as input). |
CheckApplParms |
Based on application processing, checks for the existence of required parms, domain values of input parms, etc. Basically, this function validates all input parameters. |
ISPError |
Handles ISPF error handling in a generic routine. This function should be present for any application that invokes ISPF services. |
RXDB2 |
This function handles the call to the REXX-to-DB2 interface. Since this function returns a stem value, this function must be embedded within the application. In order to mass-apply any configuration changes, this function should NOT be modified (and any call to DB2 should go through this internal subroutine). |
FunctionAdjectiveOperand |
Generic subroutine naming standard. Function should be a verb and Operand should be a noun. Examples: GetDatabaseList ExecuteSQLStatement |
ElapsedTime |
Return the elapsed time in mm.ss (minutes and seconds) since the elapsed time clock has been reset. The caller is responsible for resetting the elapsed time clock. |
Miscellaneous Functions
LISTDSI Return Codes
The following may be used to dynamically interpret the return code from the LISTDSI function.
DSIERR.0 = ‘Normal completion’
DSIERR.1 = ‘Error parsing LISTDSI statement’
DSIERR.2 = ‘Dynamic allocation (SVC 99) error’
DSIERR.3 = ‘Data set type prohibits its being processed’
DSIERR.4 = ‘Error extracting UNIT name’
DSIERR.5 = ‘Data set is not cataloged’
DSIERR.6 = ‘Error obtaining data set name from VTOC’
DSIERR.7 = ‘Error finding device type’
DSIERR.8 = ‘Data set is not on DASD’
DSIERR.9 = ‘HSM migrated the data set & NORECALL was specified’
DSIERR.10 = ‘Undefined return code RC(10)’
DSIERR.11 = ‘Directory info was requested but ‘UserId’ has’,
‘insufficient access authority for this data set’
DSIERR.12 = ‘VSAM data set’
DSIERR.13 = ‘Data set open failed’
DSIERR.14 = ‘Device type not found in UCB tables’
DSIERR.15 = ‘Undefined return code RC(15)’
DSIERR.16 = ‘Data set not found. RC(16) ‘
DSIERR.17 = ‘An abend occurred.’
DSIERR.18 = ‘Partial data set information obtained’
DSIERR.19 = ‘Multi-volume data set’
DSIERR.20 = ‘Device type not found in EDT table’
DSIERR.21 = ‘Catalog error prevented locate completion’
DSIERR.22 = ‘Volume not mounted’
DSIERR.23 = ‘I/O error during OBTAIN macro’
DSIERR.24 = ‘Obtain could not find data set in VTOC’
DSIERR.25 = ‘Data set migrated off of DASD’
DSIERR.26 = ‘Data set is on a mass storage (MSS) device.’
DSIERR.27 = ‘No volume serial number is allocated for this data set’
DSIERR.28 = ‘DD name is invalid – must be 1 to 8 characters’
DSIERR.29 = ‘Both data set name and file name were omitted.’
File-tailoring – using a permanent dataset
If you need to perform file tailoring to a dataset other than the TEMP tailoring output dataset, the following sample code will allow you to allocate the dataset. You may need to use this option if you wish to permanently save the output of the tailoring process, or if the output is too large to be held by the default TEMP tailoring dataset.
/********************************************************************/
/* Delete the old version and re-allocate member for output JCL */
/********************************************************************/
FTInit:
x = outtrap(“garbage.”)
“free dd(ISPFILE)”
“DEL ‘”OutputJCL”‘”
“alloc ddname(ISPFILE) da(‘”OutputJCL”‘) new space(5,5) tracks “,
“reuse catalog lrecl(80) blksize(27920) recfm(F B) dsorg(PS) “,
“bufno(20)”
if rc > 4 then
do
do m = 1 to GARBAGE.0
say GARBAGE.m
end
signal CleanUp
end
“EXECIO 0 DISKW ISPFILE (FINIS” /* write empty member */
ispexec ftopen
return