我会尽力回答这个问题。如果你唯一的编程经验是x86或ARM,那么你将会遇到很大的困难。是的,这些芯片销量很大,但这并不意味着它们很好,只是便宜到人们不介意扔掉它们。
许多相关信息可以在“The Minimum You Need to Know to Be an OpenVMS Application Developer”中找到。你会发现这是Dr. Dobb's推荐阅读列表上为数不多的几本书之一。是的,我写了这本书。这也是HP OpenVMS工程组推荐给想要学习该平台的开发者的书籍。
我在那个平台上使用COBOL主要发生在20世纪80年代,当时它是VAX/VMS。然后变成了OpenVMS;Alpha/OpenVMS;Itanium/OpenVMS;很快将成为x86/OpenVMS。在一个真正的计算机和真正的操作系统上,各个部分都有意义。每个部分创建了一个PSECT。在链接器术语中,这是Program SECtion的缩写。根据部分的内容,设置了各种加载属性。每个PSECT将被加载到一个或多个512字节的内存页面中。内存页面的设计大小与磁盘块完全相同。VMS代表虚拟内存系统。IBM有几个自己的操作系统,在底层上是不同的,但它们也是真正的虚拟内存系统。这不是“覆盖链接”。那是一个x86术语,并由于严重的架构缺陷而产生。从286时代开始,阅读关于紧凑型、小型、中型和大型“内存模型”的文章。还要阅读EMS和XMS内存分页。哦,那太有趣了!
这是那本书中发现的众多程序之一。
IDENTIFICATION DIVISION.
程序标识. COB_ZILL_DUE_REPORT_SUB.
作者. Roland Hughes.
编写日期. 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 DRAW-STATS
是全局的
标签记录是标准的。
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-FILE
标签记录被省略。
01 RPT-DTL PIC X(80).
SD 排序文件。
COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
REPLACING ZILLIONARE_STATS_RECORD BY SORT-REC.
FD SORTED-FILE
ID 的值是 SORTED-FILE-NAME。
COPY 'CDD_RECORDS.ZILLIONARE_STATS_RECORD' FROM DICTIONARY
REPLACING ZILLIONARE_STATS_RECORD BY SORTED-REC.
工作存储区段。
01 常量。
05 SORT-FILE-NAME PIC X(7) VALUE '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-主程序。
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-INPUT。
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-INPUT。
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。
对于这个编辑器中“代码”功能的工作方式表示抱歉。
某些部分必须存在。没有输入输出(I-O)段,您的程序无法执行I-O操作。这是您将名称映射到物理存储的位置。
如果您拥有一个I-O段,那么您必须拥有一个文件段。这是您定义每个命名文件的记录布局的位置。在处理磁盘数据文件时,LABEL RECORDS始终为STANDARD,而在编写报表文本文件时则为OMITTED。还有一些其他条款我记不清了。请注意,在所有FD语句中都包含SD。FD是文件定义,SD是排序定义。
如果您要有任何局部变量,则必须拥有一个WORKING-STORAGE SECTION。您不能在运行时声明变量,它们都必须在此处声明。这个PSECT会获得一个数据段属性以及其他一些属性。如果您调用某个服务或其他东西,并且它具有错误的地址,则尝试在此PSECT内执行代码,操作系统将使您的应用程序停止运行。
PROCEDURE DIVISION 后面创建的所有 PSECT 都被标记为 EXEC,是受写保护的。如果您在执行期间尝试覆盖这里的任何内容,操作系统将使您的程序崩溃。任何其他尝试在此处编写的程序也将被彻底清除。
向下滚动到 A000-MAIN 中的 SORT SORT-FILE。COBOL 排序例程非常棒。请注意,我提供了一个输入 PROCEDURE,并且它是一个段落。在那个时代运行 ROSCOE 的 IBM 大型机上,它必须是一个 INPUT SECTION。他们需要在 PSECT 上有不同的属性,以便系统排序例程可以读取/写入。
这是书中另一个程序的片段。
*
* FMS定义
*
将 'MEGA_TEXT_LIB' 库中的 'COBFDVDEF' 复制到当前程序。
LINKAGE部分。
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).
PROCEDURE DIVISION USING FMS-STUFF.
链接部分创建了一个可共享内存的PSECT。当您调用返回值的外部例程时,它们需要在这里。您还必须授予您的PROCEDURE DIVISION访问链接部分所需的各种内容。
正如您从代码中稍后看到的那样
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在线文档真的非常没有价值。如果您想要更详细的信息,请搜索大约1980年代的COBOL教科书。它不会有任何新东西,但它会回答许多问题。
这里有一个关于COBOL结构的不太好的教程。