Coding a batch program in C language

The following code example shows how to write an IMS™ program to access the IMS database in C language.

The numbers to the right of the program refer to the notes that follow the program.

Sample C language program

#pragma runopts(env(IMS),plist(IMS))                                       	NOTES    
#include <ims.h>
#include <stdio.h>                                                        	 1 
main() {                                                                  	 2 
/*                                                     */
/*             descriptive statements                  */
/*                                                     */
 IO_PCB_TYPE *IO_PCB = (IO_PCB_TYPE*)PCBLIST[0];
 struct {PCB_STRUCT(10)} *mast_PCB   = __pcblist[1];
struct {PCB_STRUCT(20)} *detail_PCB = __pcblist[2];                       	 3 
const static char func_GU[4]   = "GU  ";
const static char func_GN[4]   = "GN  ";
const static char func_GHU[4]  = "GHU ";
const static char func_GHN[4]    = "GHN ";                      
const static char func_GNP[4]    = "GNP ";                                	 4  
const static char func_GHNP[4] = "GHNP";
const static char func_ISRT[4] = "ISRT";
const static char func_REPL[4] = "REPL";
const static char func_DLET[4] = "DLET";
char qual_ssa[8+1+8+2+6+1+1]; /* initialized by sprintf                  	 5 
                               /*below.  See the  */
                               /*explanation for  */           
                               /*sprintf in note 7 for the */  
                               /*meanings of 8,1,8,2,6,1 ——*/  
                               /*the final 1 is for the    */
                               /*trailing '\0' of string */
static const char unqual_ssa[]= "NAME     ");
                               /* 12345678_ */
struct {
          ———                                                 
          ———                                                  
          ———                                                  
       } mast_seg_io_area;
 
struct {
          ———
          ———                                                             	 6 
          ———
       } det_seg_io_area;
/*                                                      */
/*        Initialize the qualifier                      */
/*                                                      */

    sprintf(qual_ssa,                                          
           "8.8s(8.8s6.6s)",                        
           "ROOT", "KEY", "=", "vvvvv");                                		 7 
/*                                                      */
/*            Main part of C batch program              */
/*                                                      */     
     ctdli(func_GU, detail_PCB,                                
          &det_seg_io_area,qual_ssa);                                    	 8 

     ctdli(func_GHU, mast_PCB,                                 
          &mast_seg_io_area,qual_ssa);                                   	 9 

     ctdli(func_GHN, mast_PCB,                                 
          &mast_seg_io_area);                                             	 10 

     ctdli(func_REPL, mast_PCB,                                
          &mast_seg_io_area;                                             	 11 
}                                                                         	 12 
Note:
  1. The env(IMS) establishes the correct operating environment and the plist(IMS) establishes the correct parameter list when invoked under IMS. The ims.h header file contains declarations for PCB layouts, __pcblist, and the ctdli routine. The PCB layouts 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.

    The stdio.h header file contains declarations for sprintf (used to build up the SSA).

  2. After IMS has loaded the application program's PSB, IMS gives control to the application program through this entry point.
  3. The C run-time sets up the __pcblist values. The order in which you refer to the PCBs must be the same order in which they have been defined in the PSB. (Values other than 10 and 20 can be used, according to the actual key lengths needed.) These declarations can be done using macros, such as:
    #define IO_PCB (IO_PCB_TYPE *) (__pcblist[0])
    #define mast_PCB   (__pcblist[1])
    #define detail_PCB (__pcblist[2])

    This 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.

  4. 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. (If the [4]s had been left out, 5 bytes would have been reserved for each constant.) 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 directive.

    Instead, you can define these by macros, although each string would have a trailing null ('\0').

  5. The SSA is put into a string (see note 7). You can define a structure, as in COBOL, PL/I, or Pascal, but using sprintf is more convenient. (Remember that C strings have trailing nulls that cannot be passed to IMS.) Note that the string is 1 byte longer than required by IMS to contain the trailing null, which is ignored by IMS. Note also that the numbers in brackets assume that six fields in the SSA are equal to these lengths.
  6. The I/O areas that will be used to pass segments to and from the database are defined as structures.
  7. The sprintf function is used to fill in the SSA. The %-8.8s format means a left-justified string of exactly eight positions. The %2.2s format means a right-justified string of exactly two positions.
    Because the ROOT and KEY parts do not change, this can also be coded:
    sprintf(qual_ssa,
            "ROOT    (KEY      =%-6.6s)", "vvvvv");
          /* 12345678 12345678 */
  8. 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. Unlike the COBOL, PL/I, and Pascal interface routines, ctdli also returns the status code as its result. (Blank is translated to 0.) So, you can code:
    switch (ctdli(....)) {
        case 0: ... /* everything ok */
     
                break;
        case 'AB': ....
     
                break;
        case 'IX': ...
     
                break;
        default:
    }

    You can pass only the PCB pointer for DL/I calls in a C program.

  9. This is another call with a qualified SSA.
  10. This call 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.
  11. 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 that is referenced in the call.
  12. The end of the main routine (which can be done by a return statement or exit call) returns control to IMS.
Restriction: IMS provides a language interface module (DFSLI000) that is an interface between IMS and the C language. This module must be made available to the application program at bind time.