Coding a batch program in PL/I
The following code example is a skeleton batch program in PL/I. It shows you how the parts of an IMS program that is written in PL/I fit together.
The numbers to the right of the program refer to the notes that follow. This kind of program can run as a batch program or as a batch-oriented BMP.
Sample PL/I program
/* */ NOTES
/* ENTRY POINT */
/* */
DLITPLI: PROCEDURE (IO_PTR_PCB,DB_PTR_MAST,DB_PTR_DETAIL) 1
OPTIONS (MAIN);
/* */
/* DESCRIPTIVE STATEMENTS */
/* */
DCL IO_PTR_PCB POINTER;
DCL DB_PTR_MAST POINTER;
DCL DB_PTR_DETAIL POINTER;
DCL FUNC_GU CHAR(4) INIT('GU '); 2
DCL FUNC_GN CHAR(4) INIT('GN ');
DCL FUNC_GHU CHAR(4) INIT('GHU ');
DCL FUNC_GHN CHAR(4) INIT('GHN ');
DCL FUNC_GNP CHAR(4) INIT('GNP ');
DCL FUNC_GHNP CHAR(4) INIT('GHNP');
DCL FUNC_ISRT CHAR(4) INIT('ISRT');
DCL FUNC_REPL CHAR(4) INIT('REPL');
DCL FUNC_DLET CHAR(4) INIT('DLET');
DCL 1 QUAL_SSA STATIC UNALIGNED, 3
2 SEG_NAME CHAR(8) INIT('ROOT '),
2 SEG_QUAL CHAR(1) INIT('('),
2 SEG_KEY_NAME CHAR(8) INIT('KEY '),
2 SEG_OPR CHAR(2) INIT(' ='),
2 SEG_KEY_VALUE CHAR(6) INIT('vvvvv'),
2 SEG_END_CHAR CHAR(1) INIT(')');
DCL 1 UNQUAL SSA STATIC UNALIGNED,
2 SEG_NAME_U CHAR(8) INIT('NAME '),
2 BLANK CHAR(1) INIT(' ');
DCL 1 MAST_SEG_IO_AREA, 4
2 ———
2 ———
2 ———
DCL 1 DET_SEG_IO_AREA,
2 ———
2 ———
2 ———
DCL 1 IO_PCB BASED (IO_PTR_PCB), 5
2 FILLER CHAR(10),
2 STAT CHAR(2);
DCL 1 DB_PCB_MAST BASED (DB_PTR_MAST),
2 MAST_DB_NAME CHAR(8),
2 MAST_SEG_LEVEL CHAR(2),
2 MAST_STAT_CODE CHAR(2),
2 MAST_PROC_OPT CHAR(4),
2 FILLER FIXED BINARY (31,0),
2 MAST_SEG_NAME CHAR(8),
2 MAST_LEN_KFB FIXED BINARY (31,0),
2 MAST_NO_SENSEG FIXED BINARY (31,0),
2 MAST_KEY_FB CHAR(*);
DCL 1 DB_PCB_DETAIL BASE (DB_PTR_DETAIL),
2 DET_DB_NAME CHAR(8),
2 DET_SEG_LEVEL CHAR(2),
2 DET_STAT_CODE CHAR(2),
2 DET_PROC_OPT CHAR(4),
2 FILLER FIXED BINARY (31,0),
2 DET_SEG_NAME CHAR(8),
2 DET_LEN_KFB FIXED BINARY (31,0),
2 DET_NO_SENSEG FIXED BINARY (31,0),
2 DET_KEY_FB CHAR(*);
DCL THREE FIXED BINARY (31,0) INITIAL(3); 6
DCL FOUR FIXED BINARY (31,0) INITIAL(4);
DCL FIVE FIXED BINARY (31,0) INITIAL(5);
DCL SIX FIXED BINARY (31,0) INITIAL(6);
/* */
/* MAIN PART OF PL/I BATCH PROGRAM */
/* */
CALL PLITDLI (FOUR,FUNC_GU,DB_PCB_DETAIL,DET_SEG_IO_AREA, QUAL_SSA); 7
IF DET_STAT_CODE = GOOD_STATUS_CODE THEN DO;
CALL PLITDLI (FOUR,FUNC_GHU,DB_PCB_MAST,MAST_SEG_IO_AREA,QUAL_SSA); 8
IF MAST_STAT_CODE = GOOD_STATUS_CODE THEN DO;
CALL PLITDLI (THREE,FUNC_GHN,DB_PCB_MAST,MAST_SEG_IO_AREA); 9
IF MAST_STAT_CODE = GOOD_STATUS_CODE THEN DO;
CALL PLITDLI (THREE,FUNC_REPL,DB_PCB_MAST,MAST_SEG_IO_AREA); 10
IF MAST_STAT_CODE ^= GOOD_STATUS_CODE THEN DO;
/* INSERT REPLACE DIAGNOSTIC MESSAGE */
END;
END;
ELSE DO;
/* INSERT GHN DIAGNOSTIC MESSAGE */
END;
END;
ELSE DO;
/* INSERT GHU DIAGNOSTIC MESSAGE */
END;
END;
ELSE DO;
/* INSERT GU DIAGNOSTIC MESSAGE */
END;
RETURN; 11
END DLITPLI;
- After IMS has loaded the
PSB of the application program, IMS gives
control to the application program through this entry point. PL/I
programs must pass the pointers to the PCBs, not the names, in the
entry statement. The entry statement lists the PCBs that the program
uses by the names that it has assigned to the definitions for the
PCB masks. The order in which you refer to the PCBs in the entry statement
must be the same order in which they have been defined in the PSB.
The code example assumes that an I/O PCB was passed to the application program. When the program is a batch program, CMPAT=YES must be specified on the PSBGEN statement of PSBGEN so that the I/O PCB is included. Because the I/O PCB is required for a batch program to make system service calls, CMPAT=YES should always be specified for batch programs.
- Each of these areas defines one of the call functions used by the batch program. Each character string is defined as four alphanumeric characters, with a value assigned for each function. You can define other constants in the same way. Also, you can store standard definitions in a source library and include them by using a %INCLUDE statement.
- A structure definition defines each SSA the program uses. The unaligned attribute is required for SSAs. The SSA character string must reside contiguously in storage. You should define a separate structure for each qualified SSA, because the value of the data field for each SSA is different.
- The I/O areas that are used to pass segments to and from the database are defined as structures.
- Level-01 declaratives define masks for the PCBs that the program uses as structures. These definitions make it possible for the program to check fields in the PCBs.
- This statement defines the parmcount that
is required in DL/I calls that are issued from PL/I programs (except
for the call to the sample status-code error routine, where it is
not allowed). The parmcount is the address
of a 4-byte field that contains the number of subsequent parameters
in the call. The parmcount is required only
in PL/I programs. It is optional in the other languages. The value
in parmcount is binary. This example shows
how you can code the parmcount parameter
when three parameters follow in the call:
DCL THREE FIXED BINARY (31,0) INITIAL(3);
- This call retrieves data from the database. It contains a qualified
SSA. Before you can issue a call that uses a qualified SSA, initialize
the data field of the SSA. Before you can issue a call that uses an
unqualified SSA, initialize the segment name field. Check the status
code after each DL/I call that you issue.
Although you must declare the PCB parameters that are listed in the entry statement to a PL/I program as POINTER data types, you can pass either the PCB name or the PCB pointer in DL/I calls in a PL/I program.
- This is another call that has a qualified SSA.
- This is an unqualified call that retrieves data from the database.
Because it is a Get Hold call, it can be followed by
REPL
orDLET
. - The
REPL
call replaces the data in the segment that was retrieved by the most recent Get Hold call; the data is replaced by the contents of the I/O area referenced in the call. - The RETURN statement returns control to IMS.