示例程序
一个读写文件的示例
本节将通过一个例子程序来综合上述内容。这个例子程序使用C标准库函数读写文件。本节内容将包括:
- 编写C源代码
- 编写JCL脚本来编译C源代码
- 义Edit Macro在编写程序的过程中调用JCL来编译源代码
- 编写执行程序的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"); }
备注:上面的代码中ゥ可以认为是定界符。由于编码问题,需要在hex模式下将其改成5B5B。//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=* // ゥ
可以看出,上面的CLIST是将编译JCL脚本嵌入了CLIST中(或者在上传ftp不要转码)。 运行脚本 运行程序的JCL中重点是定义读写的文件
需要注意是REPORT的DD定义中各个参数的意义。尤其是DCB参数中个参数之间的关系。详细参见参考资料11 P113。 实际上可以丰富这个JCL脚本,使其可以在REPORT是否存在的情况均能正确执行。//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)
关于编译和绑定
在程序开发过程中,通常可以将函数定义在单独的源文件中,分别编译。这是就需要分别调用编译脚本和绑定脚本了。 注意这里说的绑定不是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