6.13 COPY语句

下面显示的是COPY语句的通用语法。

COPY语句与其他的COBOL语句有很大的不同,因为其他的COBOL语句都是在程序运行时执行的,而COPY语句则是在程序编译的时候执行的。COPY语句是一个库文件服务语句,用来将预先写好的文本复制到程序的源代码中。每条COPY语句必须以句号结束。如果没有在COPY语句中指定库名(LibraryName),则系统假定要访问的库名指定在编译作业流中的SYSLIB所指定的文件名中。

如果指定短语SUPPRESS,表示在程序编译清单中不出现嵌套在复制成员中的内容,COPY语句要求COBOL编译选项LIB是生效的。

预先写好的源程序段可以在程序编译时复制到程序中来,这样很多公司就可以将标准的文件描述、记录描述和过程描述预先写好,存放到复制库中,其他程序员不用在程序中重复编写而是直接使用COPY语句复制到程序中来,既节省了程序员的工作量,也可以保证所有人使用的是同一套标准格式。

编译器在处理包含有COPY语句的源程序时,首先处理所用的COPY语句,然后对COPY以后的源程序做编译处理。处理COPY语句时,编译器将复制库中预先写好的文本代码复制到源程序中,置换原来程序中的从COPY开始到句号(.)结束的语句。如果在COPY语句中没有指定REPLACING短语,复制库中的文本会原封不动地抄到源程序中来。

每条COPY语句必须以句号(.)结束。注解行和空行可以出现在复制库文本中,出现在复制库文本中的注解行和空行都会复制到源程序中,但如果注解行或空行中有正好与REPLACING短语后面的变量(Identifier1)或常量(Literal1或word1)相同时,注解行或空行就不会复制到源程序中。

只有处理完所有的COPY和REPLACING语句后,才能确定COBOL源程序语法的正确性。单凭复制库文本的内容是不能独立确定程序的语法正确性的。

COPY可以出现在源程序的任何地方,作为IBM主机COBOL的扩充,COPY语句可以嵌套调用。但是,被嵌套调用的COPY语句不能包含REPLACING短语,同样,带有REPLACING短语的COPY语句也不可以包含嵌套的COPY语句。

COPY语句不能递归(Recursion),也就是说,在一组嵌套的COPY语句中,一个复制库成员名只能出现一次。比如,假定源程序有语句COPY X,而复制库文件X又含有语句COPY Y,这时,复制库文本文件Y就一定不能出现COPY X或COPY Y语句。

当你想把复制库文件中的部分或全部文本复制到源程序之后做某些修改,就要使用COPY REPLACING短语,所修改的内容只反映在源程序中,而原来的复制库文本文件则保持不变。

REPLACING短语匹配的过程是以文本单词(Text Word)为单位进行的,这里所谓的单词并不等同于英语中的单词,它指的是:

● 用引号(‘’)括起来的一串字符。

● 用下面的分隔符隔开的字符串。

✧ 空格。

✧ 伪文本分隔符(==)。

✧ 逗号(,)。

✧ 左括号或右括号。

当指定REPLACING短语时,复制库文本会复制进源程序,然后所有与Identifier1匹配的文本单词会置换为Identifier2。

为了修改复制库文本文件中的数据名的一部分,程序员可以使用带有标准伪文本(Pseudo Text)分隔符(==)的REPLACING选项。伪文本(Pseudo-Text)是一组用分隔符双等号(==)括起来的字符串,伪文本可以包含最多322个字符。请记住,伪文本字符串必须用分隔符括起来。伪文本使得我们可以一次置换多个单词或字符。伪文本1(PseudoText1)不能为空值(Null),也不能只由空格字符、逗号、分号或注解行组成。伪文本前后的空格不作为文本比较的字符,嵌套在中间的空格表明包含多个文本单词则要参与比较。伪文本不能包含单词COPY。

6.13.1 程序例子(COPY命令)

下面的程序是使用COPY命令的例子,这是完整的源程序,至于COPY库文本我们没有在这里单独列出来,因为在下面的编译清单中,你可以看到它们的全貌。

        000001  IDENTIFICATION DIVISION.
        000002 *
        000003  PROGRAM-ID. COPY2.
        000004  AUTHOR. NEWMAN LV.
        000005 *
        000006  ENVIRONMENT DIVISION.
        000007 *
        000008  INPUT-OUTPUT SECTION.
        000009 *
        000010  DATA DIVISION.
        000011 *
        000012
        000013  FILE SECTION.
        000014 *
        000015  WORKING-STORAGE SECTION.
        000016 * COPY DIRECTLY
        000017  COPY FILREC1.
        000018 * COPY REPLACING
        000019  COPY FILREC1 REPLACING
        000020             REC1 BY REC2
        000021             FILLER BY MAST-NOTES.
        000022 * COPY REPLACING TEXT WORDS
        000023  COPY FILREC4.
        000024  COPY FILREC4 REPLACING
        000025             PIC  BY MAST
        000026             X BY Y
        000027             9 BY 0.
        000028 * NESTED COPY.
        000029  COPY FILREC2.
        000030 * COPY REPLACING PSEUDO TEXT1
        000031  COPY FILREC3.
        000032  COPY FILREC3 REPLACING ==:MAST-:== BY ==MST-==.
        000033 * COPY REPLACING PSEUDO TEXT2
        000034  COPY FILREC3 REPLACING ==:MAST-:== BY ==WS-==.
        000035 * COPY REPLACING PSEUDO TEXT3
        000036  COPY FILREC3 REPLACING ==:MAST-:== BY ====.
        000037 * COPY SUPPRESS
        000038  COPY FILREC1 SUPPRESS.
        000039 *
        000040  PROCEDURE DIVISION.
        000041 *
        000042      DISPLAY 'FOR TEST COPY VERB... '
        000043      STOP RUN.

6.13.2 程序编译清单(COPY命令)

下面显示的是上面的程序COPY2的编译清单,由于我们可以看到复制库中的源代码,所以我们会在这里对每个COPY命令做讲解。

第17行的COPY命令,直接将复制库文件FILREC1的内容抄到源程序中,它的内容显示在第18行和第24行,请注意第7列的字符‘C’,表示该行的内容是从别的地方复制过来的,而不是源程序中原来就有的。

第26行到第28行的COPY REPLACING命令除了将FILREC1中的内容复制到程序之外,还要将REC1置换为REC2,FILLER置换为MAST-NOTES。COPY命令执行的结果显示在第29行到第35行,如果你够仔细,你就会发现MAST-REC1并没有按照要求改成MAST-REC2,问题出在哪里?原因其实很简单,是我们对文本单词(Text Word)的理解出了误差,所谓的文本单词要么是用引号括起来的字符串,要么是用几个规定的分隔符分隔开来的字符串,因此,REC1并不是一个完整的文本单词,而MAST-REC1才是一个完整的文本单词。所以,只有将REPLACING后面的REC1 BY REC2写成MAST-REC1 BY MAST-REC2才能达到置换的目的。与REC1相反,第35行的FILLER成功置换成了MAST-NOTES,因为FILLER是一个完整的文本单词。

第37行的COPY命令简单明了,直接将FILREC4的内容抄到程序中,其结果显示在第38行到第44行。接下来的第45行到第48行的COPY REPLACING命令,则是为了更深刻地说明什么叫做文本单词!第46行的PIC BY MAST短语,目的是将所有的文本单词PIC置换成字符串MAST,从第50行到第55行的结果你能看到,左边的PIC原封不动地保留下来,而右边的PIC则全部被置换成MAST了,因为左边的PIC不是文本单词!第47行的短语X BY Y是要将所有的文本单词X置换成Y,再看看第50行到第55行的结果,右边的4个X确实都换成了Y,因为它们都是由空格和左括号隔离开来的文本单词。第48行的短语9 BY 0是要把所有的文本单词9换成0,再看看结果,第50行的9换成了0,但第53行的S9和V99都没有发生变化,因为9自己不是一个文本单词,而S9和V99则是。看了这个例子,你应该对什么是文本单词有了很深刻的印象了吧。

第57行的COPY语句看起来没有什么特别之处,闪光点在库复制文件FILREC2,本身又带有COPY语句,这就形成了嵌套的COPY语句,这是IBM主机上的COBOL对标准COBOL的一个扩充,对于这种嵌套语句的一个限制是,它们都不能有REPLACING短语。嵌套COPY语句的结果显示在第58行到第69行,其中的第65行到第69行的内容来源于另外一个复制库文件CMBWORDS。

接下来的几个例子是介绍如何使用伪文本复制库文件的。第71行的COPY语句直接显示了伪文本复制文件是如何编码的,请注意第72行到第77行的描述,我们在字符串‘MAST-’的前后加上了冒号(:),目的是在使用REPLACING短语时更容易操作。第79行的COPY语句将所有的字符串‘:MAST-:’置换成‘MST’,结果显示在第80行到第86行。

第88行的COPY语句则将‘:MAST-:’置换为‘WS-’,结果显示在第89行到第95行。第97行的COPY REPLACING语句则是直接将字符串‘:MAST:’去掉,结果显示在第98行到第104行。使用伪文本作为记录格式的描述,在实际的程序开发中是经常使用的,因为它可以更灵活地适用于各种情况。

第106行的COPY语句使用了SUPPRESS短语,其效果就是在源程序编译清单中不会出现所调用的复制库文件的内容,这样可以缩短编译清单的长度,使程序员能够更好地将精力集中于程序逻辑本身。在汇编语言中也有类似的功能,其格式为PRINT NOGEN。

下面是COPY2程序的完整编译清单,显然我们对它做了一些编辑,因为现在的程序版本是通过不了编译程序的检查的,但为了说明COPY语句的用法,我们将所有的出错信息都删掉了。

        000001   IDENTIFICATION DIVISION.
        000002  *
        000003   PROGRAM-ID. COPY2.
        000004   AUTHOR. NEWMAN LV.
        000005  *
        000006   ENVIRONMENT DIVISION.
        000007  *
        000008   INPUT-OUTPUT SECTION.
        000009  *
        000010   DATA DIVISION.
        000011  *
        000012
        000013   FILE SECTION.
        000014  *
        000015   WORKING-STORAGE SECTION.
        000016  * COPY DIRECTLY
        000017   COPY FILREC1.
        000018C  01  MAST-REC1.
        000019C     05  MAST-ACNO             PIC 9(14).
        000020C     05  MAST-IDNO             PIC X(16).
        000021C     05  MAST-NAME             PIC X(35).
        000022C     05  MAST-BALANCE          PIC S9(13)V99 COMP-3.
        000023C     05  MAST-REMARKS          PIC X(38).
        000024C     05  FILLER                PIC X(39).
        000025  * COPY REPLACING
        000026   COPY FILREC1 REPLACING
        000027              REC1 BY REC2
        000028              FILLER BY MAST-NOTES.
        000029C  01  MAST-REC1.
        000030C     05  MAST-ACNO             PIC 9(14).
        000031C     05  MAST-IDNO             PIC X(16).
        000032C     05  MAST-NAME             PIC X(35).
        000033C     05  MAST-BALANCE          PIC S9(13)V99 COMP-3.
        000034C     05  MAST-REMARKS          PIC X(38).
        000035C     05  MAST-NOTES            PIC X(39).
        000036  * COPY REPLACING TEXT WORDS
        000037   COPY FILREC4.
        000038C  01  PIC-REC4.
        000039C     05  PIC-ACNO              PIC 9(14).
        000040C     05  PIC-IDNO              PIC X(16).
        000041C     05  PIC-NAME              PIC X(35).
        000042C     05  PIC-BALANCE           PIC S9(13)V99 COMP-3.
        000043C     05  PIC-REMARKS           PIC X(38).
        000044C     05  FILLER                PIC X(39).
        000045   COPY FILREC4 REPLACING
        000046              PIC  BY MAST
        000047              X BY Y
        000048              9 BY 0.
        000049C  01  PIC-REC4.
        000050C     05  PIC-ACNO              MAST 0(14).
        000051C     05  PIC-IDNO              MAST Y(16).
        000052C     05  PIC-NAME              MAST Y(35).
        000053C     05  PIC-BALANCE           MAST S9(13)V99 COMP-3.
        000054C     05  PIC-REMARKS           MAST Y(38).
        000055C     05  FILLER                MAST Y(39).
        000056  * NESTED COPY.
        000057   COPY FILREC2.
        000058C  01  MAST-REC2.
        000059C     05  MAST-ACNO             PIC 9(14).
        000060C     05  MAST-IDNO             PIC X(16).
        000061C     05  MAST-NAME             PIC X(35).
        000062C     05  MAST-BALANCE          PIC S9(13)V99 COMP-3.
        000063C     05  MAST-REMARKS          PIC X(38).
        000064C     05  MAST-SLOGAN           PIC X(39).
        000065C  COPY CMBWORDS.
        000066C       88 CMBWORD1             VALUE 'CMB IS THE BEST!'.
        000067C       88 CMBWORD2             VALUE 'CMB ALWAYS FOR YOU!'.
        000068C       88 CMBWORD3             VALUE 'CMB IS AMAZING!'.
        000069C       88 CMBWORD4             VALUE 'CMB ALWAYS GO WITH YOU!'.
        000070  * COPY REPLACING PSEUDO TEXT1
        000071   COPY FILREC3.
        000072C  01  :MAST-:REC3.
        000073C     05  :MAST-:ACNO           PIC 9(14).
        000074C     05  :MAST-:IDNO           PIC X(16).
        000075C     05  :MAST-:NAME           PIC X(35).
        000076C     05  :MAST-:BALANCE        PIC S9(13)V99 COMP-3.
        000077C     05  :MAST-:REMARKS        PIC X(38).
        000078C     05  FILLER                PIC X(39).
        000079   COPY FILREC3 REPLACING ==:MAST-:== BY ==MST-==.
        000080C  01  MST-REC3.
        000081C     05  MST-ACNO              PIC 9(14).
        000082C     05  MST-IDNO              PIC X(16).
        000083C     05  MST-NAME              PIC X(35).
        000084C     05  MST-BALANCE           PIC S9(13)V99 COMP-3.
        000085C     05  MST-REMARKS           PIC X(38).
        000086C     05  FILLER                PIC X(39).
        000087  * COPY REPLACING PSEUDO TEXT2
        000088   COPY FILREC3 REPLACING ==:MAST-:== BY ==WS-==.
        000089C  01  WS-REC3.
        000090C     05  WS-ACNO               PIC 9(14).
        000091C     05  WS-IDNO               PIC X(16).
        000092C     05  WS-NAME               PIC X(35).
        000093C     05  WS-BALANCE            PIC S9(13)V99 COMP-3.
        000094C     05  WS-REMARKS            IC X(38).
        000095C     05  FILLER                PIC X(39).
        000096  * COPY REPLACING PSEUDO TEXT3
        000097   COPY FILREC3 REPLACING ==:MAST-:== BY ====.
        000098C  01  REC3.
        000099C     05  ACNO                  PIC 9(14).
        000100C     05  IDNO                  PIC X(16).
        000101C     05  NAME                  PIC X(35).
        000102C     05  BALANCE               PIC S9(13)V99 COMP-3.
        000103C     05  REMARKS               PIC X(38).
        000104C     05  FILLER                PIC X(39).
        000105  * COPY SUPPRESS
        000106   COPY FILREC1 SUPPRESS.
        000114  *
        000115   PROCEDURE DIVISION.
        000116  *
        000117       DISPLAY 'FOR TEST COPY VERB... '
        000118       STOP RUN.