5.8 普通COBOL程序编译流程图及样板作业流
图5.2是普通COBOL应用程序所需要做的准备工作,方框表示的是系统要做的处理,圆形表示的是输入或输出。从图5.2我们可以看到,COBOL源程序要变成可执行的运行模块,必须经过编译和链接两个处理。编译用来对COBOL源程序做语法检查并生成目标程序,编译的输入是COBOL源程序,而输出是中间产品,即目标程序。链接模块用来将目标程序加上一些必要的处理,比如将某些标准系统模块装配到目标程序中,并生成运行模块。链接处理的输入是编译作业步生成的目标模块,输出则是最终的可运行模块(装载模块)。
图5.2 COBOL应用程序编译流程
下面的样本作业流是一个将普通COBOL应用程序编译和连接成可执行模块的例子。我们可以看到在第9行和第26行有两个作业步,分别对应于我们前面提到的编译(COBOL)和链接(LKED)两个处理。
在编译(COBOL)作业步中,第17 行的SYSIN指定源程序的位置,这里是IBMUSER.TEST. COBOL(&SRC)而源程序的成员名是变量&SRC,它是在作业流开始的第4行通过SET语句指定的。第18行的SYSLIB指定程序需要的记录格式COPYBOOK所在的数据集,当你的程序中有COPY语句时,就必须提供它。第14 行的SYSLIN当然就是编译的输出要存放的数据集了。注意,这里我们使用的是临时文件(&&LOADSET),因为它只是一个过渡产品,在可执行模块生成后,它就没有存在的价值了,因而系统会在作业执行完后帮我们删除它,以免占用磁盘空间。
在链接(LKED)作业步中,第31行的SYSLIN是它的输入,注意,这里指向的正好是编译作业步的输出,即临时数据集(&&LOADSET),第28行和第29行的两个数据集使用同一个DD名(SYSLIB),我们称其为数据集的串联(Concatenate),该数据集提供程序装配时需要的系统模块。第32行的SYSLMOD就是链接的输出数据集即可执行模块存放的数据集,其成员名也是由第4行的SET语句提供的。
000001 //IBMUSERC JOB 'COMP BATCH',CLASS=A,MSGCLASS=H, 000002 // NOTIFY=&SYSUID,MSGLEVEL=(1,1) 000003 //* 000004 // SET SRC=IND1000 000005 //* 000006 //***************************************************************** 000007 //* JOB TO COMPILE AND LINK-EDIT COBOL PROGRAM 000008 //***************************************************************** 000009 //COBOL EXEC PGM=IGYCRCTL,REGION=2048K, 000010 // PARM='NODYNAM,LIB,OBJECT,RENT,RES,APOST,MAP,XREF,OFFSET' 000011 //STEPLIB DD DSNAME=COBOL.V3R1.SIGYCOMP, 000012 // DISP=SHR 000013 //SYSPRINT DD SYSOUT=* 000014 //SYSLIN DD DSNAME=&&LOADSET,UNIT=SYSDA, 000015 // DISP=(MOD,PASS),SPACE=(TRK,(3,3)), 000016 // DCB=(BLKSIZE=3200) 000017 //SYSIN DD DSN=IBMUSER.TEST.COBOL(&SRC),DISP=SHR 000018 //SYSLIB DD DSN=IBMUSER.TEST.COPY,DISP=SHR 000019 //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000020 //SYSUT2 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000021 //SYSUT3 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000022 //SYSUT4 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000023 //SYSUT5 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000024 //SYSUT6 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000025 //SYSUT7 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000026 //LKED EXEC PGM=HEWL,COND=(8,LT,COBOL),REGION=1024K, 000027 // PARM='LIST,XREF' 000028 //SYSLIB DD DSNAME=CEE.SCEELKED,DISP=SHR 000029 // DD DSN=IBMUSER.TEST.COPY,DISP=SHR 000030 //SYSPRINT DD SYSOUT=* 000031 //SYSLIN DD DSNAME=&&LOADSET,DISP=(OLD,DELETE) 000032 //SYSLMOD DD DSNAME=IBMUSER.TEST.LOAD(&SRC),DISP=SHR 000033 //SYSUT1 DD UNIT=SYSDA,SPACE=(TRK,(10,10))
下面提供的是一个带有调用过程的通用COBOL批处理编译作业流,当你有很多程序需要同时编译时,它就是非常方便的。因为,该作业流可以一次将你要编译的所有程序编译完成,不用挨个编译COBOL程序。当一个项目组共同完成一个较大的项目时,通常需要开发或修改的程序会很多,这时,下面的作业流就为你提供了很大的帮助。
作业流的第4行到第34行定义了一个过程,其名字为CBLBATCH,它的内容跟上面的COBOL编译作业流非常相似。要编译的程序名是由第8行的SET语句从外部传递进来的。作业流的第35行到第107行,逐个程序调用过程CBLBATCH编译COBOL程序,每行编译一个COBOL程序,如果你想编译那个程序,只要将该程序所在的行由注解(//*)变成可执行(//)即可。
如果你要成批编译程序,则只要将相关的程序编译行由注解(//*)变成可执行(//)即可。这样,你就可以一次将你的项目需要编译的程序全部编译完成了。
下面是完整的作业流,供你参考。
000001 //IBMUSERC JOB 'NEWMAN 168',CLASS=A,MSGCLASS=H, 000002 // NOTIFY=&SYSUID,MSGLEVEL=(1,1) 000003 //* 000004 //CBLBATCH PROC 000005 //***************************************************************** 000006 //* PROC TO COMPILE AND LINK-EDIT COBOL PROGRAM 000007 //***************************************************************** 000008 // SET SRC=&SRC 000009 //COBOL EXEC PGM=IGYCRCTL,REGION=2048K, 000010 // PARM='NODYNAM,LIB,OBJECT,RENT,RES,APOST,MAP,XREF,OFFSET' 000011 //STEPLIB DD DSNAME=COBOL.V3R1.SIGYCOMP, 000012 // DISP=SHR 000013 //SYSPRINT DD SYSOUT=* 000014 //SYSLIN DD DSNAME=&&LOADSET,UNIT=SYSDA, 000015 // DISP=(MOD,PASS),SPACE=(TRK,(3,3)), 000016 // DCB=(BLKSIZE=3200) 000017 //SYSIN DD DSN=IBMUSER.TEST.COBOL(&SRC),DISP=SHR 000018 //SYSLIB DD DSN=IBMUSER.TEST.COPY,DISP=SHR 000019 //SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000020 //SYSUT2 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000021 //SYSUT3 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000022 //SYSUT4 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000023 //SYSUT5 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000024 //SYSUT6 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000025 //SYSUT7 DD UNIT=SYSDA,SPACE=(CYL,(1,1)) 000026 //LKED EXEC PGM=HEWL,COND=(8,LT,COBOL),REGION=1024K, 000027 // PARM='LIST,XREF' 000028 //SYSLIB DD DSNAME=CEE.SCEELKED,DISP=SHR 000029 // DD DSN=IBMUSER.TEST.LOAD,DISP=SHR 000030 //SYSPRINT DD SYSOUT=* 000031 //SYSLIN DD DSNAME=&&LOADSET,DISP=(OLD,DELETE) 000032 //SYSLMOD DD DSNAME=IBMUSER.TEST.LOAD(&SRC),DISP=SHR 000033 //SYSUT1 DD UNIT=SYSDA,SPACE=(TRK,(10,10)) 000034 // PEND 000035 //*BKUPD1 EXEC CBLBATCH,SRC=BKUPD1 000036 //*ACCEPT1 EXEC CBLBATCH,SRC=ACCEPT1 000037 //*ACCEPT1X EXEC CBLBATCH,SRC=ACCEPT1X 000038 //*ACPDIS EXEC CBLBATCH,SRC=ACPDIS 000039 //*ARITHME EXEC CBLBATCH,SRC=ARITHME 000040 //*BKMENPW EXEC CBLBATCH,SRC=BKMENPW 000041 //*BKSENCD EXEC CBLBATCH,SRC=BKSENCD 000042 //*BKUPD1 EXEC CBLBATCH,SRC=BKUPD1 000043 //*BKUPD2 EXEC CBLBATCH,SRC=BKUPD2 000044 //*BKUPD3 EXEC CBLBATCH,SRC=BKUPD3 000045 //*CALL1 EXEC CBLBATCH,SRC=CALL1 000046 //*CONTINU1 EXEC CBLBATCH,SRC=CONTINU1 000047 //*COPY1 EXEC CBLBATCH,SRC=COPY1 000048 //*COPY2 EXEC CBLBATCH,SRC=COPY2 000049 //*CUSTINQ EXEC CBLBATCH,SRC=CUSTINQ 000050 //*CUSTINQ1 EXEC CBLBATCH,SRC=CUSTINQ1 000051 //*CUSTINQ3 EXEC CBLBATCH,SRC=CUSTINQ3 000052 //*CUSTMNT1 EXEC CBLBATCH,SRC=CUSTMNT1 000053 //*CUSTMNT2 EXEC CBLBATCH,SRC=CUSTMNT2 000054 //*DRIVER1 EXEC CBLBATCH,SRC=DRIVER1 000055 //*DRIVER2 EXEC CBLBATCH,SRC=DRIVER2 000056 //*DRIVER3 EXEC CBLBATCH,SRC=DRIVER3 000057 //*DYNAMIC1 EXEC CBLBATCH,SRC=DYNAMIC1 000058 //*EXAM01 EXEC CBLBATCH,SRC=EXAM01 000059 //*GETINV EXEC CBLBATCH,SRC=GETINV 000060 //*HELLO EXEC CBLBATCH,SRC=HELLO 000061 //*INDEX1 EXEC CBLBATCH,SRC=INDEX1 000062 //*IND100X EXEC CBLBATCH,SRC=IND100X 000063 //*IND1000 EXEC CBLBATCH,SRC=IND1000 000064 //*IND2000 EXEC CBLBATCH,SRC=IND2000 000065 //*IND4100 EXEC CBLBATCH,SRC=IND4100 000066 //*IND4100C EXEC CBLBATCH,SRC=IND4100C 000067 //*IND4150 EXEC CBLBATCH,SRC=IND4150 000068 //*INSPECT1 EXEC CBLBATCH,SRC=INSPECT1 000069 //*INTEDIT EXEC CBLBATCH,SRC=INTEDIT 000070 //*INVMENU EXEC CBLBATCH,SRC=INVMENU 000071 //*INVSUM1 EXEC CBLBATCH,SRC=INVSUM1 000072 //*MAIN1 EXEC CBLBATCH,SRC=MAIN1 000073 //*MAIN2 EXEC CBLBATCH,SRC=MAIN2 000074 //*MOVE1 EXEC CBLBATCH,SRC=MOVE1 000075 //*MYDRIVE EXEC CBLBATCH,SRC=MYDRIVE 000076 //*MYSUB EXEC CBLBATCH,SRC=MYSUB 000077 //*MYSUBJ EXEC CBLBATCH,SRC=MYSUBJ 000078 //*MYSUB1 EXEC CBLBATCH,SRC=MYSUB1 000079 //*MYSUB2 EXEC CBLBATCH,SRC=MYSUB2 000080 //*NUMEDIT EXEC CBLBATCH,SRC=NUMEDIT 000081 //*ORDRENT EXEC CBLBATCH,SRC=ORDRENT 000082 //*PARM1 EXEC CBLBATCH,SRC=PARM1 000083 //*PERFORM1 EXEC CBLBATCH,SRC=PERFORM1 000084 //*READ1 EXEC CBLBATCH,SRC=READ1 000085 //*RPT1000 EXEC CBLBATCH,SRC=RPT1000 000086 //*RPT7000 EXEC CBLBATCH,SRC=RPT7000 000087 //*SALESINQ EXEC CBLBATCH,SRC=SALESINQ 000088 //*SEARCH1 EXEC CBLBATCH,SRC=SEARCH1 000089 //*SEQ100X EXEC CBLBATCH,SRC=SEQ100X 000090 //*SRT1000 EXEC CBLBATCH,SRC=SRT1000 000091 //*STRING1 EXEC CBLBATCH,SRC=STRING1 000092 //STRLEN EXEC CBLBATCH,SRC=STRLEN 000093 //*SYSERR EXEC CBLBATCH,SRC=SYSERR 000094 //*TABLE1 EXEC CBLBATCH,SRC=TABLE1 000095 //*TABLE11 EXEC CBLBATCH,SRC=TABLE11 000096 //*TABLE2 EXEC CBLBATCH,SRC=TABLE2 000097 //*TABLE3 EXEC CBLBATCH,SRC=TABLE3 000098 //*TABLE6 EXEC CBLBATCH,SRC=TABLE6 000099 //*TABLE8 EXEC CBLBATCH,SRC=TABLE8 000100 //*UNSTR1 EXEC CBLBATCH,SRC=UNSTR1 000101 //*UPDTCUST EXEC CBLBATCH,SRC=UPDTCUST 000102 //*VNCUPDT EXEC CBLBATCH,SRC=VNCUPDT 000103 //*WRITE0 EXEC CBLBATCH,SRC=WRITE0 000104 //*WRITE1 EXEC CBLBATCH,SRC=WRITE1 000105 //*WRITE3 EXEC CBLBATCH,SRC=WRITE3 000106 //*WRITE4 EXEC CBLBATCH,SRC=WRITE4 000107 //*WRITE5 EXEC CBLBATCH,SRC=WRITE5