【问题标题】:Why does COBOL have both `SECTION` and `PARAGRAPH`?为什么 COBOL 既有 SECTION 又有 PARAGRAPH ?
【发布时间】:2009-11-04 17:39:48
【问题描述】:

为什么 COBOL 同时具有 SECTIONPARAGRAPH

谁能解释一下为什么COBOL 的设计者同时创建了SECTIONs 和PARAGRAPHs?这些自 COBOL 最初发布以来就已经存在,所以我怀疑它们存在的真正原因早已消失(类似于 NEXT SENTENCE 之类的东西,它们仍在语言规范中以实现向后兼容性,但自从引入显式范围终止符)。

我的猜测是 SECTION 可能已被引入以支持程序覆盖。 SECTION 有一个与之关联的可选优先级编号,用于标识它所属的程序覆盖。但是,大多数现代 COBOL 实现忽略或删除了优先级数字(和覆盖)。

目前,我看到PROCEDURE DIVISIONDECLARATIVE 部分仍然需要SECTIONs,但找不到任何理由。我看不出SECTIONPARAGRAPH 之间没有语义差异,除了PARAGRAPH 从属于SECTION

一些 COBOL 商店禁止使用 SECTION 以支持 PARAGRAPH(在北美似乎很常见)。其他人禁止PARAGRAPH 支持SECTION(在欧洲似乎很常见)。还有一些人有关于何时适当的指导方针。所有这一切对我来说似乎都是非常武断的——这就引出了一个问题:为什么首先将它们放入语言规范中?而且,它们今天有什么相关性吗?

如果您回答了这个问题,如果您还可以指出一个参考来支持您的回答,那就太好了。

谢谢

【问题讨论】:

    标签: language-design cobol


    【解决方案1】:

    没有关于这方面的参考,因为我听说它是​​从我店里的一位老顾客那里传给我的,但是......

    在旧的 COBOL 编译器中,至少对于 IBM 和 Unisys,部分能够一次加载到内存中。回到内存稀缺的美好时光,一个太大而无法一次全部加载到内存中的程序可以使用节来模块化以供内存使用。如果不能同时加载所有部分和段落,程序员就可以决定将哪些代码部分一起加载到内存中 - 为了提高效率,您希望将同一执行循环的两个部分一起加载。如今,它或多或少没有实际意义。

    我的商店只使用段落,禁止 GOTO 并要求退出段落,所以我们所有的 PERFORMS 都是 PERFORM 100-PARAGRAPH THRU 100-EXIT 或类似的东西 - 这似乎使段落对我来说更像是部分。但我认为现在并没有太大的不同。

    【讨论】:

    • 呸,我看到 colemanj 的答案和我一样。我只是向下滚动了第一个答案条目。我还不能评论其他人的答案,所以我将把它作为对 colemanj 所说内容的稍微扩展的解释。
    • 我认为你和 colemanj 的答案是正确的,但你的答案更清晰。程序分段是用于在小地址空间中管理“大型”程序的“最新技术”机制。幸运的是,虚拟内存使这个功能过时了(我已经有足够长的时间来体验编写分段程序的“乐趣”)。我所看到的只是可能的“名称间距”使用和一个无法解释的要求,即声明性引用部分而不是段落(正如 Tim Sylvester 所指出的那样)。
    【解决方案2】:

    我在 1978 年左右在 ICL 2903 上学习了 COBOL。我有一个模糊的记忆,即可以为 SECTION 标头分配一个数字范围,这意味着这些 SECTION 标头可以换入和换出内存,当程序太大内存。

    【讨论】:

    • 是的,这些是优先级数字,我敢打赌,你也可以给我一些关于必须使用它们的恐怖故事。我相信如果您让一个独立段(优先级数> = 50)引用另一个独立段,程序可能会遇到真正的麻烦。幸运的是,那些日子现在已经过去了......
    【解决方案3】:

    我知道这是一个老问题,但 OP 要求提供有关在 COBOL 中使用 SECTION 和 PARAGRAPH 的原始理由的文档。

    您无法获得比 CODASYL 期刊文档更多的“原创”。

    在期刊语言规范的第 8 节中,

    “COBOL 分段是一种工具,它提供了一种方法 用户可以与编译器通信以指定目标程序 覆盖要求”

    (第 331 页,第 8.1 节“细分 - 概述”)

    “虽然不是强制性的,但对于一个来源的程序部 程序通常写成一组连续的部分,每个部分 它由一系列密切相关的操作组成 旨在共同执行特定功能。然而当 使用segmentation时,整个Procedure Division必须在 部分。此外,每个部分必须归类为属于 无论是固定部分还是独立部分之一 目标程序。细分绝不会影响对 过程名称的限定,以确保唯一性。”

    (第 331 页,第 8.1.2.1 节“程序段”)

    在她关于比较编程语言的书中(“编程语言:历史和基础”,1969 年)Jean Sammet(他是 CODASYL 委员会的成员,代表 Sylvania Electric)说:

    ".. 存储分配由编译器自动处理。 分配可执行代码的主要单位是一组节 称为 segment。 程序员结合部分指定一个 每个部分名称的优先级编号。 ...编译器是必需的 看到提供了适当的控制传输,以便控制 可以在不同时存储的段之间发生。 ……”

    (p 369 - 371 V.3 COBOL)

    【讨论】:

      【解决方案4】:

      嗯,最简单的原因是 SECTION 为您提供了“模块化”——就像 C 中的函数一样——在“结构化”程序中是必需的。您会注意到使用 SECTION 编写的代码看起来比仅在段落中编写的代码更具可读性,因为每个部分都必须有一个“EXIT”——从 SECTION 中唯一且非常明确的退出点(paragrpah 的退出点远更加模糊和隐含,即直到找到新的段落声明)。考虑这个例子,你可能会想在你的代码中使用部分:

      *==================
       MAINLINE SECTION.
      *==================
           PERFORM SEC-A
           PERFORM SEC-B
           PERFORM SEC-C
           GOBACK.
      *==================
       MAINLINE-EXIT.
      *==================
          EXIT.
      
      *==================
       SEC-A SECTION.
      *==================
      
      .....
      .....
      .....
      .....
      
          IF <cond>
             go to A-EXIT
          end-if
      
      ..... 
      .....
      .....
      .....
      
      .
      
      *==================
       A-EXIT.
      *==================
          EXIT.
      

      不要以为在段落中编写代码时您会有这种特权。您可能不得不编写一个巨大的 ELSE 语句来掩盖在达到某个条件时您不想执行的语句(考虑该组语句要跨 2-3 页运行……另一组 IF / ELSE 会让你缩进)。当然,您必须使用“GO TO”来实现这一点,但您始终可以指示您的专业人员不要使用 GO TO,除非在退出时使用,我认为这是一个公平的交易。

      因此,虽然我也同意可以使用 SECTION 编写的任何内容也可以使用段落编写(几乎没有调整),但我个人的选择是采用一种可以使我的开发人员的工作成为以后会容易一些!

      【讨论】:

      • +1 获取有趣的反馈。您使用 SECTION/PARAGRAPH 来描述特定的编码风格,而不是识别导致将 SECTION 和 PARAGRAPH 都包含到 COBOL 语言规范中的语言设计标准。请注意,在您的示例中,如果删除了 SECTION 标头,将它们放入 PARAGRAPHs 中,并且 PERFORM SEC-APERFORM SEC-A THRU A-EXIT 替换等。您有一个仅使用 PARAGRAPH 的功能等效程序。顺便说一句,将MAINLINE-EXIT 放在GOBACK 之前,否则GO TO MAINLINE-EXIT 肯定会导致麻烦!
      • 那些将“转到”作为对程序设计缺陷的“第一反应”的人 :-) 倾向于认为那些不这样做的人必须编写深层嵌套的 IF/EVALUATE 代码。这不一定是真的,尽管它确实发生了。
      【解决方案5】:

      Cobol 是在 50 年代中期开发的。正如全名所暗示的那样,它是为商业编程而开发的,作为一种比现有的“科学”或“技术”语言(无论如何“语言”和“机器代码”(具体,当然,对于一个特定的架构(我几乎说“特定芯片”,在考虑真空管之前))可能必须通过某些机器上的物理开关/拨号设置),如果幸运的话有一个“汇编程序”。 Cobol 在当时非常先进,为了它的目的。

      我们的目的是让用 Cobol 编写的程序更像英语,而不仅仅是一组“代码”,这对初学者来说意味着什么。

      如果您查看一些与语言相关的命名法 - 段落、句子、动词、从句 - 它是故意遵循英语语言的模式。

      SECTION 不太适合这个,除非你将事情与正式的商业文件联系起来。

      SECTION 和段落也出现在 PROCEDURE DIVISION 之外。与书面英语一样,段落可以单独存在,也可以是 SECTION 的一部分。

      SECTION 可能有一个与“分段功能”相关的优先级编号。这曾经包括 SECTION 的“覆盖”以提供原始级别的内存管理。这是一种“计算功能”而不是英语功能 :-)“分段功能”确实有一些影响,但我从未见过它实际使用过。

      如果没有 DECLARATIVES(我不使用它,并且刚刚注意到手册不清楚),那么对于 PERFORM 是否使用 SECTION 或段落是“选择”。

      如果使用GO TO,合理地,可以用PERFORM ... TRHU ...实现“等价”。如果不是,并且没有无缘无故使用PERFORM ... THRU ...,则存在等价已经。

      与“结构化”代码和现代语言的比较是“向后阅读历史”或只是概述特定的“实践”。从“意大利面条代码”和 ALTER ... TO PROCEED TO ... 所获得的声誉来看,很可能 20 年来,除非您需要“内存管理”,否则很少对 PERFORM 做太多事情是“常见的”,但我没有参考资料或知识来支持这一点。

      SECTION 允许重复的段落名称,否则段落名称必须是唯一的。

      我不能一直把一个特定的手指放在另一个上面。

      如果使用 GO TO,我会使用 SECTION。如果没有,段落。使用声明我会使用部分。如果使用 SECTION,我会以 SECTION 开始 PROCEDURE DIVISION 以避免出现诊断消息。

      当地标准可能会规定,但不一定基于“现代”(甚至“理性”)。根据我的经验,很多是“已知的”,但实际上对 SECTION 和段落有误解。

      对于性能(正在处理大量数据,我的意思是大量数据),一个 SECTION 而不是多个单独段落的 PERFORM 会看到改进。 PERFORM ... THRU ...的效果是一样的,但我不推荐它。 PERFORM 范围之外的 GO TO 是 1) 不好 2) 可能会失去“优化”。当 GO TO 异常结束/异常并且不期望任何逻辑返回时,不应该是问题 *except"。如果认为使用 this 必须“立即”,那么尽管“违反直觉”,但最好使用 PERFORM 来完成" 方面(所以记录它)。

      【讨论】:

        【解决方案6】:

        一方面,段落名称必须是唯一的,除非它们位于单独的部分中,因此部分允许段落的“命名空间”。

        如果我没记错的话,您必须使用SECTION 的唯一原因是DECLARATIVES。除此之外,它们是可选的,主要用于对段落进行分组。我认为(相对而言,无论如何)要求 PERFORM 仅在段落位于同一部分时才使用是很常见的。

        【讨论】:

        • 我忘记了SECTIONs 提供超过PARAGRAPHs 的“命名空间”功能,但这是语言设计者在提出这些结构时使用的理由吗? J.Sammet 前段时间写了一篇关于 COBOL 早期历史的有趣文章,其中对为什么某些语言特性是这样的方式给出了一些见解,但没有提供关于为什么 SECTIONPARAGRAPH 被合并的见解。我只是不明白——但这些人不是傻瓜,所以我想拥有他们一定有充分的理由。谢谢,尼尔
        【解决方案7】:

        一个部分可以包含多个段落。当您执行一个部分时,它会执行该部分中的所有段落。在节内,您可以使用 PERFORM 或 GOTO 分支到节内的段落。

        【讨论】:

        • 因此 EXIT 语句作为 GO TO 的目标。今天,EXIT 只是一个“挂”段落名称的地方。我认为一些早期的编译器要求 EXIT 是执行的 SECTION/PARAGRAPH 范围的最后一段中的唯一语句。需要生成实现从 PERFORMed 范围返回的代码。由于 PARAGRAPH 从属于 SECTION,因此可以预期 PERFORMing a SECTION 将执行所有包含的段落。可以使用PERFORM para-1 THROUGH para-n 执行一系列段落,因此可以仅使用段落来实现相同的功能。
        【解决方案8】:

        我会尽力回答这个问题。如果您唯一的编码暴露是 x86 或 ARM,那么您将遇到很大的困难。是的,这些芯片卖得很多,但这并不意味着它们很好,只是足够便宜,人们不介意扔掉它们。

        大部分信息都可以在“The Minimum You Need to Know to Be an OpenVMS Application Developer”中找到。你会发现它是Dr. Dobb's recommended reading list for all developers 上为数不多的标题之一。是的,我写的。它也是 HP OpenVMS 工程组向希望学习该平台的开发人员推荐的一本书。

        我在那个平台上的 COBOL 主要发生在 1980 年代,当时它是 VAX/VMS。然后它变成了 OpenVMS;阿尔法/OpenVMS;安腾/OpenVMS;很快就会成为 x86/OpenVMS。在具有真实操作系统的真实计算机上,部分具有意义。每个部分都创建了一个 PSECT。在链接器术语中是 Program SECtion 的缩写。根据该部分的内容,设置了各种负载属性。每个 PSECT 将被加载到一个或多个 512 字节内存页中。内存页被设计成与磁盘块的大小完全相同。 VMS 代表虚拟内存系统。 IBM 有几个自己的操作系统,它们在底层是不同的,但它们也是真正的虚拟内存系统。这不是“覆盖链接”。这是一个 x86 术语,是由于严重的架构缺陷而出现的。从 286 天开始阅读紧凑型、小型、中型和大型“内存模型”。还阅读了 EMS 和 XMS 内存分页。 Oiy 太有趣了!

        这是该书中的众多程序之一。

        IDENTIFICATION DIVISION.
        

        程序 ID。 COB_ZILL_DUE_REPORT_SUB。 作者。罗兰休斯。 写日期。 2005-02-08。 日期编译。今天。

        环境部。

        输入-输出部分。

        文件控制。

        SELECT DRAW-STATS
            ASSIGN TO 'DRAWING_STATS'
            ORGANIZATION IS INDEXED
            ACCESS MODE IS SEQUENTIAL
            RECORD KEY IS ELM_NO IN DSTATS-REC
            LOCK MODE IS AUTOMATIC
            FILE STATUS IS D-STAT.
        
        SELECT MEGA-STATS
            ASSIGN TO 'MEGA_STATS'
            ORGANIZATION IS INDEXED
            ACCESS MODE IS SEQUENTIAL
            RECORD KEY IS ELM_NO IN MSTATS-REC
            LOCK MODE IS AUTOMATIC
            FILE STATUS IS M-STAT.
        
        SELECT SORT-FILE ASSIGN TO 'TMP.SRT'.
        
        SELECT SORTED-FILE ASSIGN TO DISK.
        
        SELECT RPT-FILE ASSIGN TO 'ZILL_DUE.RPT'.
        

        数据划分。

        文件部分。

        FD 抽签统计 是全球性的 标签记录是标准的。

        COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
            REPLACING ZILLIONARE_STATS_RECORD BY DSTATS-REC.
        

        FD MEGA-STATS 是全球性的 标签记录是标准的。

        COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
            REPLACING ZILLIONARE_STATS_RECORD BY MSTATS-REC.
        

        FD RPT-文件 省略了标签记录。

        01 RPT-DTL                         PIC X(80).
        

        SD 排序文件。

        COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
            REPLACING ZILLIONARE_STATS_RECORD BY SORT-REC.
        

        FD 排序文件 ID 的值是已排序的文件名。

        COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
            REPLACING ZILLIONARE_STATS_RECORD BY SORTED-REC.
        

        • 数据声明

        工作存储部分。 01 常数。 05 排序文件名 PIC X(7) 值“TMP.SRT”。 05 SORTED-FILE-NAME PIC X(8) VALUE 'STAT.SRT'。

        01 STATUS-VARIABLES.
           05 M-STAT                PIC X(2).
           05 D-STAT                PIC X(2).
           05 EOF-FLAG              PIC X.
              88 IT-IS-END-OF-FILE VALUE 'Y'.
        
        01 STUFF.
           05 TODAYS-DATE.
              10 TODAY_YYYY         PIC X(4).
              10 TODAY_MM           PIC X(2).
              10 TODAY_DD           PIC X(2).
        
           05 TODAYS-DATE-FORMATTED.
              10 FMT_MM             PIC Z9.
              10 FILLER             PIC X VALUE '/'.
              10 FMT_DD             PIC 99.
              10 FILLER             PIC X VALUE '/'.
              10 FMT_YYYY           PIC 9(4).
        
           05 FLT-1                 COMP-2.
           05 WORK-STR              PIC X(65).
        
        01 REPORT-DETAIL.
           05 ELM-NO-DTL            PIC Z9.
           05 FILLER                PIC X(3).
           05 HIT-COUNT-DTL         PIC ZZZ9.
           05 FILLER                PIC X(3).
           05 SINCE-LAST-DTL        PIC ZZZ9.
           05 FILLER                PIC X(5).
           05 PCT-HITS-DTL          PIC Z9.999.
           05 FILLER                PIC X(4).
           05 AVE-BTWN-DTL          PIC ZZ9.999.
        
        01 REPORT-HDR1.
           05 THE-DATE              PIC X(12).
           05 FILLER                PIC X(20).
           05 PAGE-TITLE            PIC X(17).
        
        01 REPORT-HDR2.
           05 FILLER                PIC X(33).
           05 GROUP-TITLE           PIC X(20).
        
        01 REPORT-HDR3.
           05 HDR3-TXT              PIC X(40) VALUE
                'No   Hits   Since   Pct_hits   Ave_btwn'.
        
        01 REPORT-HDR4.
           05 HDR4-TXT              PIC X(40) VALUE
                '--   ----   -----   --------   --------'.
        

        程序部。

        A000-MAIN。

        PERFORM B000-HSK.
        
        SORT SORT-FILE
            ON DESCENDING KEY SINCE_LAST IN SORT-REC
            INPUT PROCEDURE IS S000-DSTAT-INPUT
            GIVING SORTED-FILE.
        
        PERFORM B010-REPORT-DRAWING-NUMBERS.
        
        
        STRING SORT-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
        CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
        
        STRING SORTED-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
        CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
        

        * * 设置报告的第二部分 * 将空间移动到 RPT-DTL。 在前进页面之前编写 RPT-DTL。

        MOVE SPACES TO EOF-FLAG.
        MOVE ' Mega Drawing Numbers' TO GROUP-TITLE.
        
        SORT SORT-FILE
            ON DESCENDING KEY SINCE_LAST IN SORT-REC
            INPUT PROCEDURE IS S001-MSTAT-INPUT
            GIVING SORTED-FILE.
        
        
        PERFORM B010-REPORT-DRAWING-NUMBERS.
        
        
        STRING SORT-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
        CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
        
        STRING SORTED-FILE-NAME, ';*' DELIMITED BY SIZE INTO WORK-STR.
        CALL 'LIB$DELETE_FILE' USING BY DESCRIPTOR WORK-STR.
        
        
        CLOSE RPT-FILE.
        
        CALL 'LIB$SPAWN' USING BY DESCRIPTOR 'EDIT/READ ZILL_DUE.RPT'.
        
        EXIT PROGRAM.
        

        • 初始化我们的数据和文件的段落。

        B000-HSK。 调用“COB_FILL_IN_LOGICALS”。

        MOVE SPACES TO STATUS-VARIABLES.
        
        ACCEPT TODAYS-DATE FROM DATE YYYYMMDD.
        
        MOVE TODAY_YYYY TO FMT_YYYY.
        MOVE TODAY_DD   TO FMT_DD.
        MOVE TODAY_MM   TO FMT_MM.
        
        
        OPEN OUTPUT RPT-FILE.
        
        
        MOVE SPACES TO REPORT-HDR1.
        MOVE TODAYS-DATE-FORMATTED TO THE-DATE.
        MOVE 'Due Number Report' to PAGE-TITLE.
        
        MOVE SPACES TO REPORT-HDR2.
        MOVE 'Drawing Numbers' TO GROUP-TITLE.
        

        • 处理排序后的选择文件的段落和
        • 创建与绘图相关的报告部分
        • 号码。

        B010-报告-图纸-编号。

        MOVE SPACES TO EOF-FLAG.
        
        OPEN INPUT SORTED-FILE.
        
        READ SORTED-FILE
            AT END SET IT-IS-END-OF-FILE TO TRUE.
        
        PERFORM C010-DRAWING-HEADINGS.
        
        PERFORM UNTIL IT-IS-END-OF-FILE
            MOVE SPACES TO REPORT-DETAIL
            MOVE ELM_NO IN SORTED-REC TO ELM-NO-DTL
            MOVE HIT_COUNT IN SORTED-REC TO HIT-COUNT-DTL
            MOVE SINCE_LAST IN SORTED-REC TO SINCE-LAST-DTL
            MOVE PCT_HITS IN SORTED-REC TO PCT-HITS-DTL
            MOVE AVE_BTWN IN SORTED-REC TO AVE-BTWN-DTL
            MOVE REPORT-DETAIL TO RPT-DTL
            WRITE RPT-DTL BEFORE ADVANCING 1 LINE
            READ SORTED-FILE
                AT END SET IT-IS-END-OF-FILE TO TRUE
            END-READ
        END-PERFORM.
        
        CLOSE SORTED-FILE.
        

        • 用于打印主要图纸编号标题的段落
        • 到期。

        C010-绘图-标题。

        MOVE SPACES TO RPT-DTL.
        
        
        MOVE REPORT-HDR1 TO RPT-DTL.
        
        WRITE RPT-DTL BEFORE ADVANCING 2 LINES.
        
        MOVE SPACES TO RPT-DTL.
        
        MOVE REPORT-HDR2 TO RPT-DTL.
        
        WRITE RPT-DTL BEFORE ADVANCING 1 LINE.
        
        MOVE SPACES TO RPT-DTL.
        MOVE REPORT-HDR3 TO RPT-DTL.
        WRITE RPT-DTL BEFORE ADVANCING 1 LINE.
        
        MOVE SPACES TO RPT-DTL.
        MOVE REPORT-HDR4 TO RPT-DTL.
        WRITE RPT-DTL BEFORE ADVANCING 1 LINE.
        

        • 用于将到期编号过滤到排序文件中的段落。
        • 创建一个临时浮点进行比较
        • 输入文件中的浮点值。当更大时
        • 记录被释放到排序文件。

        S000-DSTAT-输入。

        OPEN INPUT DRAW-STATS.
        
        READ DRAW-STATS NEXT
            AT END SET IT-IS-END-OF-FILE TO TRUE.
        
        PERFORM UNTIL IT-IS-END-OF-FILE
        
            MOVE SINCE_LAST IN DSTATS-REC TO FLT-1
        
            IF FLT-1 >= AVE_BTWN IN DSTATS-REC
                MOVE DSTATS-REC TO SORT-REC
                RELEASE SORT-REC
            END-IF
            READ DRAW-STATS
                AT END SET IT-IS-END-OF-FILE TO TRUE
            END-READ
        END-PERFORM.
        
        CLOSE DRAW-STATS.
        

        • 用于将到期编号过滤到排序文件中的段落。
        • 创建一个临时浮点进行比较
        • 输入文件中的浮点值。当更大时
        • 记录被释放到排序文件。

        S001-MSTAT-输入。

        OPEN INPUT MEGA-STATS.
        
        READ MEGA-STATS NEXT
            AT END SET IT-IS-END-OF-FILE TO TRUE.
        
        PERFORM UNTIL IT-IS-END-OF-FILE
        
            MOVE SINCE_LAST IN MSTATS-REC TO FLT-1
        
            IF FLT-1 >= AVE_BTWN IN MSTATS-REC
                MOVE MSTATS-REC TO SORT-REC
                RELEASE SORT-REC
            END-IF
            READ MEGA-STATS
                AT END SET IT-IS-END-OF-FILE TO TRUE
            END-READ
        END-PERFORM.
        
        CLOSE MEGA-STATS.
        

        结束程序 COB_ZILL_DUE_REPORT_SUB。

        抱歉,“代码”功能在此编辑器中的工作方式。

        某些部分必须存在。如果没有 INPUT-OUTPUT SECTION,您的程序将无法执行 I-O。这是您将名称映射到物理存储的地方。

        如果你有一个 INPUT-OUTPUT SECTION 那么你必须有一个 FILE SECTION。这是您定义每个命名文件的记录布局的地方。 LABEL RECORDS 在处理磁盘数据文件时始终为 STANDARD,在编写报告文本文件时为 OMITTED。还有一些条款我不记得了。请注意所有这些 FD 声明中包含的 SD。 FD 是文件定义,SD 是排序定义。

        如果您要使用任何局部变量,则必须有一个 WORKING-STORAGE SECTION。您不能即时声明变量,它们都必须在此处声明。此 PSECT 获得 DATA 段属性等。如果您调用了某个服务或某事并且它的地址不正确,那么尝试在此 PSECT 中执行代码,操作系统会将您的应用程序从鞍座中删除。

        在 PROCEDURE DIVISION 之后创建的所有 PSECT 都标记为 EXEC,写保护。如果您在执行期间尝试覆盖此处的任何内容,操作系统会将您的程序从鞍座中删除。任何其他试图在这里编写的程序也将被淘汰。

        向下扫描到 A000-MAIN 中的 SORT SORT-FILE。 COBOL 排序例程非常棒。请注意,我提供了一个 INPUT PROCEDURE,它是一个段落。在当时运行 ROSCOE 的 IBM 大型机上,这必须是 INPUT SECTION。他们需要 PSECT 上的不同属性,以便系统排序例程可以读/写。

        这是那本书中另一个程序的一个 sn-p。

        *
        

        * FMS 定义 * 复制“MEGA_TEXT_LIB”的“COBFDVDEF”。

        链接部分。

        01 FMS-STUFF.
           05 FMSSTATUS                 PIC S9(9) COMP.
           05 RMSSTATUS                 PIC S9(9) COMP.
           05 TCA                       PIC X(12).
           05 WORKSPACE                 PIC X(12).
        

        使用 FMS-STUFF 进行程序划分。

        链接部分创建共享内存的 PSECT。当您调用返回值的外部例程时,它们需要在此处。您还必须授予您的 PROCEDURE DIVISION 访问链接部分所需的各种内容。

        你可以在后面的代码中从这个 sn-p 看到

        B010-USER-INPUT.
        
        PERFORM C000-FORWARD-LOAD
        
        CALL 'FDV$PUTAL' USING BY DESCRIPTOR SCREEN-REC.
        
        MOVE SPACES TO WORK-STR.
        
        CALL 'FDV$GETAL' USING BY DESCRIPTOR WORK-STR
                               BY REFERENCE TERMINATOR.
        
        
        EVALUATE TERMINATOR
            WHEN FDV$K_FK_E6    SET LOAD-FORWARD TO TRUE
            WHEN FDV$K_FK_E5    SET LOAD-REVERSE TO TRUE
            WHEN FDV$K_FK_F10   SET WE-ARE-DONE TO TRUE
        END-EVALUATE.
        

        只要你正确传递它,你可以传递任何你想要的局部变量。这是需要特殊PSECT属性的写作。

        已经很晚了,我很累,但我似乎记得您可以在 PROCEDURE DIVISION 中的 SECTION 声明中使用 USING 子句。可用于 COBOL 的在线文档,至少被 GOOGLE 索引的文档确实是毫无价值的。如果您想要更详细的信息,请搜索大约 1980 年代的 COBOL 教科书。它不会有任何新东西,但会回答很多问题。

        这是kind of bad tutorial on COBOL structure

        【讨论】:

          【解决方案9】:

          我们在所有 37K MVS 批处理 COBOL 程序中使用 COBOL SECTION 编码。我们使用这种技术来获得更快的运行时间并显着降低 CPU 开销。这种 COBOL 编码技术与高性能批处理汇编器非常相似。

          称之为高性能功能结构化COBOL编程

          一旦定义了一个 SECTION,所有 PERFORM xxxxx 将在下一个编码的 SECTION 而不是 SECTION 中的下一段返回。如果段落在第一个 SECTION 之前编码,那么它们可以正常执行。 (但我们不允许这样做)

          使用 SECTION 比仅使用和 PERFORM 段落具有更高的开销 - U N L E S S - 你使用 GOTO 绕过应该有条件地执行的代码的逻辑。我们的规则是 GOTO 只能指向同一 SECTION 中的 Tag-Line(一个段落) SECTION 中的所有段落都必须是 SECTION 函数的子函数。 EXIT 指令是一个汇编程序 NOP 指令。它允许在下一个 SECTION 之前放置 Tag-Line - 快速退出/返回。

          执行 PERFORM xxxx THRU yyyy 比执行没有 GOTO 的 SECTION 具有更多的 CPU 开销。

          警告:在 SECTION 中执行 PERFORM xxxx Tag-Line 将遍历 SECTION 中的所有代码,直到遇到下一个 SECTION。当前 SECTION 之外的 GOTO Tag-Line 将贯穿新着陆 SECTION 中的所有代码,直到遇到下一个 SECTION。 (但我们不允许这样做)

          【讨论】:

          • 有趣...做过基准测试来证明这些性能差异吗?我的印象是,在执行 SECTIONS 和 PARAGRAPHS 时,IBM 编译器中使用的控制机制完全相同相同。 IBM COBOL 编译器中用于实现从 PERFORM 中返回的控制机制在 this paper 中进行了描述,我不希望执行 SECTION 或 PARAGRAPH 有任何区别。
          • 我知道这是“旧”,但是……这里有很多矛盾和误解。它们可能是由于措辞不佳而生的,但它们就在那里。 “编码器当心”。特别是“警告”没有意义-第一部分不正确,第二部分不必为真。只有在一种意义上,执行包含多个段落的 SECTION 会比执行单个段落“更快”(在 SECTION 之外,如果它们在 inside SECTION 则这样做是荒谬的) : PERFORM A-SECTION (包含B-PARA和C-PARA) PERFORM B-PARA PERFORM C-PARA 首先是代码少。
          • 作为 COBOL 编译器编写者,这是一堆废话。使用 SECTION 与使用段落本质上没有区别。没有理由期望它更快或更慢,无论您​​声称的是什么。当 PARAGRAPH 已经存在时,我不知道你为什么使用非 COBOL 术语“Tag-Line”。您描述的编码技术与“高性能批处理汇编程序”无关。使用 GOTO 绕过条件逻辑并不比使用 ELSE 更可取。 EXIT 不是汇编程序 NOP:它是有条件的返回。 PERFORM xxx THRU yyy 中没有 GOTO。 @BillWoodger++
          猜你喜欢
          • 2020-03-12
          • 1970-01-01
          • 1970-01-01
          • 2016-02-16
          • 1970-01-01
          • 2011-06-06
          • 2012-06-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多