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.

Restriction: IMS application programs cannot use PL/I multitasking. This is because all tasks operate as subtasks of a PL/I control task when you use multitasking.

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;       
Note:
  1. 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.

  2. 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.
  3. 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.
  4. The I/O areas that are used to pass segments to and from the database are defined as structures.
  5. 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.
  6. 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);
  7. 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.

  8. This is another call that has a qualified SSA.
  9. This is an unqualified call that retrieves data from the database. Because it is a Get Hold call, it can be followed by REPL or DLET.
  10. 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.
  11. The RETURN statement returns control to IMS.