示例程序

一个读写文件的示例

本节将通过一个例子程序来综合上述内容。这个例子程序使用C标准库函数读写文件。本节内容将包括:

  1. 编写C源代码
  2. 编写JCL脚本来编译C源代码
  3. 义Edit Macro在编写程序的过程中调用JCL来编译源代码
  4. 编写执行程序的JCL脚本 C代码
    ??=pragma filetag("IBM-1388")
    #include <stdio.h>
    int main()
    {
    FILE * fp;
    fp = fopen("DD:report",”w”);
    if(fp==NULL) {
      printf("Open Error\n");
    }
    fprintf(fp,"TEST\n");
    }
    
    编译绑定脚本
    //CBCC  JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID
    //DOCLG EXEC PROC=EDCCB,INFILE='IBMUSER.DEVP.SRC(RWF)',         
    //       OUTFILE='IBMUSER.RUN.LOAD(RWFILE),DISP=SHR',    
    //       CPARM='LOCALE("ZH_CN.IBM-1388"),SOURCE',           
    //       REGION=75M                                         
    //SYSUT1  DD SYSOUT=*                                       
    //                                                          
    CLIST
    PROC 0                                                            
    ISREDIT MACRO (PARM)                                              
    ISREDIT (DSNAME) = DATASET                                        
    ISREDIT (MNAME) = MEMBER                                          
    WRITE &DSNAME                                                     
    WRITE &MNAME                                                      
    SET A=&SUBSTR(8:8,&SYSTIME)                                       
    WRITE &SYSDATE                                                    
    WRITE &SYSUID                                                     
    SUBMIT * END(ゥ)                                                 
    //&SYSUID.&A JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID 
    //DOCLG EXEC PROC=EDCCB,INFILE='&DSNAME(&MNAME)',                 
    //       OUTFILE='IBMUSER.RUN.LOAD(&MNAME),DISP=SHR',          
    //       CPARM='LOCALE("ZH_CN.IBM-1388"),SOURCE',                 
    //       REGION=75M                                               
    //SYSUT1  DD SYSOUT=*                                             
    //                                                                
    ゥ
    
    备注:上面的代码中ゥ可以认为是定界符。由于编码问题,需要在hex模式下将其改成5B5B。
    可以看出,上面的CLIST是将编译JCL脚本嵌入了CLIST中(或者在上传ftp不要转码)。 运行脚本 运行程序的JCL中重点是定义读写的文件
    //RWFL JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=&SYSUID 
    //STEP1 EXEC PGM=RWFILE,PARM='para1 param2 …'        
    //STEPLIB DD DSN=IBMUSER.RUN.LOAD,DISP=SHR               
    //        DD DSN=CEE.SCEERUN,DISP=SHR                       
    //REPORT  DD DSN=IBMUSER.TEST.REPORT,DISP=(NEW,CATLG,DELETE),    
    //        UNIT=3390,VOL=SER=Z9USR1,SPACE=(100,50),          
    //        DCB=(LRECL=20,RECFM=VB,BLKSIZE=100)
    
    需要注意是REPORT的DD定义中各个参数的意义。尤其是DCB参数中个参数之间的关系。详细参见参考资料11 P113。 实际上可以丰富这个JCL脚本,使其可以在REPORT是否存在的情况均能正确执行。

关于编译和绑定

在程序开发过程中,通常可以将函数定义在单独的源文件中,分别编译。这是就需要分别调用编译脚本和绑定脚本了。 注意这里说的绑定不是DB2程序BIND DBRM,这里是连接(LINK)的意思。 编译JCL脚本

//CCONLY JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=IBMUSER       
//*COMPILE STEP:                                                    
//COMPILE EXEC PGM=CCNDRVR,REGION=75M,                                
//    PARM=('/LOCALE("ZH_CN.IBM-1388"),SOURCE')                       
//STEPLIB  DD  DSNAME=CEE.SCEERUN,DISP=SHR                            
//         DD  DSNAME=CBC.SCCNCMP,DISP=SHR                            
//SYSIN    DD  DSNAME=IBMUSER.DEVP.SRC(TEST),DISP=SHR                  
//SYSLIB   DD  DSNAME=CEE.SCEEH.H,DISP=SHR                            
//         DD  DSNAME=CEE.SCEEH.SYS.H,DISP=SHR                        
//SYSLIN   DD  DSNAME=IBMUSER.DEVP.OBJ(TEST),DISP=SHR                      
//SYSPRINT DD  SYSOUT=*                                               
//SYSOUT   DD  SYSOUT=*                                               
//SYSCPRT  DD  SYSOUT=*                                               
//*

关于IBMUSER.OBJ的属性

绑定JCL脚本

//LINKOBJ JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=IBMUSER       
//BIND   EXEC PGM=IEWL,REGION=20M,                                    
//   PARM='AMODE=31,MAP,RENT,DYNAM=DLL,CASE=MIXED,COMPAT=CURR'        
//STEPLIB  DD  DSN=CEE.SCEERUN,DISP=SHR                               
//SYSLIB   DD  DSN=CEE.SCEELKEX,DISP=SHR                              
//         DD  DSN=CEE.SCEELKED,DISP=SHR                              
//         DD  DSN=IBMUSER.DEVP.OBJ,DISP=SHR                               
//OBJPATH  DD  DSN=IBMUSER.DEVP.OBJ,DISP=SHR                               
//SYSPRINT DD  SYSOUT=*                                               
//SYSLIN  DD  *                                                       
  INCLUDE OBJPATH(TEST) 
/*                                                                    
//SYSLMOD  DD  DSNAME=IBMUSER.RUN.LOAD(TEST),DISP=SHR

上面的脚本

  • INCLUDE OBJPATH指定要bind的module;
  • SYSLIB定义了要link的函数module所在的数据集,需要注意的是如果只指定module所在的数据集,连接程序在数据集中寻找member名为函数名的module以链接程序。此外,在BIND的时候也可以将函数module所在的数据集INCLUDE在SYSLIN。 另外,可以使用Object library utility[2]来创建一个lib,在编译的时候将编译产生的module维护到该lib中,这样可以直接在SYSLIB中指定相应的lib且不要求module的member名和函数名是一致的。

object library utility

object library utility功能上类似于USS环境的ar工具。在JCL中可以使用编目过程EDCLIB和EDCCLIB建立和维护目标码库(object library)。其中EDCLIB用来维护object library;EDCCLIB编译程序并维护object library。参考资料[2]中有关于这个两个过程需要的数据集的描述。 他们实际上调用的是EDCALIAS程序。 参考EDCCLIB可以写出下面的JCL脚本将包含编译后的module的PDS IBMUSER.LIB建立成一个object library

//MLIB JOB CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1),NOTIFY=IBMUSER
//OUTILITY  EXEC PGM=EDCALIAS,PARM='DIR',
//    REGION=75M                                                
//STEPLIB  DD  DSNAME=CEE.SCEERUN2,DISP=SHR                    
//         DD  DSNAME=CEE.SCEERUN,DISP=SHR                     
//SYSLIB   DD  DSNAME='IBMUSER.DEV.OBJ',DISP=SHR                              
//SYSMSGS  DD  DSNAME=CEE.SCEEMSGP(EDCPMSGE),DISP=SHR
//SYSOUT   DD  SYSOUT=*                                              
//SYSPRINT DD  SYSOUT=*                                              
//*

更多object library utility的用法和binder参数,以及与编译绑定运行相关的数据集定义,可以参考2

对于用户的库,可以在链接程序IEWL的SYSLIB定义。如

//SYSLIB   DD  DSN=CEE.SCEELKEX,DISP=SHR     
//         DD  DSN=CEE.SCEELKED,DISP=SHR     
//         DD  DSN=IBMUSER.DEVP.OBJ,DISP=SHR

results matching ""

    No results matching ""