|
OpenVMS 用户手册
B.9 LISTER.COM 命令过程
提示输入数据,按列格式化数据,并把它排序到输出文件。这个过程说明如何使用 READ 和 WRITE 命令,以及赋值语句的字符子串覆盖格式。
例子: LISTER.COM
$ ! Procedure to accumulate programmer names and document file names.
$ ! After all programmer names and file names are entered, they are
$ ! sorted in alphabetic order by programmer name and printed on
$ ! the system printer.
$ !
$ SAVE_VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE") (1)
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(0)
$ !
$ OPEN/WRITE OUTFILE DATA.TMP ! Create output file (2)
$ !
$ ! Loop to obtain programmers' last names and file names,
$ ! and write this data to DATA.TMP.
$ !
$ LOOP: (3)
$ INQUIRE NAME "Programmer (press Return to quit)"
$ IF NAME .EQS. "" THEN GOTO FINISHED
$ INQUIRE FILE "Document file name"
$ RECORD[0,20]:='NAME' (4)
$ RECORD[21,20]:='FILE'
$ WRITE OUTFILE RECORD
$ GOTO LOOP
$ FINISHED:
$ CLOSE OUTFILE
$ !
$ DEFINE/USER_MODE SYS$OUTPUT: NL: ! Suppress sort output
$ SORT/KEY=(POSITION:1,SIZE=20) DATA.TMP DOC.SRT (5)
$ !
$ OPEN/WRITE OUTFILE DOCUMENT.DAT (6)
$ WRITE OUTFILE "Programmer Files as of ",F$TIME()
$ WRITE OUTFILE ""
$ RECORD[0,20]:="Programmer Name"
$ RECORD[21,20]:="File Name"
$ WRITE OUTFILE RECORD
$ WRITE OUTFILE ""
$ !
$ CLOSE OUTFILE (7)
$ APPEND DOC.SRT DOCUMENT.DAT
$ PRINT DOCUMENT.DAT
$ !
$ INQUIRE CLEAN_UP "Delete temporary files [Y,N]" (8)
$ IF CLEAN_UP THEN DELETE DATA.TMP;*,DOC.SRT;*
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(SAVE_VERIFY_PROCEDURE,SAVE_VERIFY_IMAGE)
$ EXIT
|
LISTER.COM 命令过程的注解
- LISTER.COM 保存当前校验设置并停掉校验。
- OPEN 命令为写入建立临时文件。
- INQUIRE 命令提示输入程序员名和文件名。如果通过按下 Return 输入一个空行来响应 INQUIRE 命令的提示,那么过程假定没有其他数据输入,并且转移到标号
FINISHED。
- 在赋值给符号 NAME
和 FILE 之后,过程使用赋值语句的字符串覆盖格式来构造符号 RECORD 的值。在 RECORD 的列 1 至 21,写入 NAME 的当前值。命令解释程序用空格填充 NAME 的值使其长度为指定的
20 个字符。
同样,RECORD 的后 20 列填充为 FILE 的值。然后,把 RECORD 的值写入输出文件。 - 在文件关闭之后,过程排序输出文件 DATA.TMP。DEFINE 命令指示 SORT 命令输出到空文件 NL。否则,这些统计将显示在终端上:
排序执行在前 20 列;即,按程序员名排序。 排序的输出文件有名称 DOC.SRT。 - 过程使用 OPEN 命令建立最终的输出文件
DOCUMENT.DAT。写入文件的第一行是标题行,给出标题、当天的日期和时间和列标题。
- 过程关闭文件 DOCUMENT.DAT,并把排序的输出文件 DOC.SRT 附加到这个文件。然后,输出文件排队到系统打印机。
- 过程提示确定是否删除中间文件。如果在 INQUIRE 命令提示中输入真回答 (T、t、Y 或 y),那么就删除文件 DATA.TMP 和 DOC.SRT。否则,保留它们。
执行 LISTER.COM 命令过程的样例
$ @LISTER
Programmer: WATERS
Document file name: CRYSTAL.CAV
Programmer: JENKINS
Document file name: MARIGOLD.DAT
Programmer: MASON
Document file name: SYSTEM.SRC
Programmer: ANDERSON
Document file name: JUNK.J
Programmer: [Return]
Delete temporary files [Y,N]:y
|
这个过程执行的输出文件结果包含以下内容:
Programmer Files as of 31-DEC-1999 16:18:58.79
Programmer Name File Name
ANDERSON JUNK.J
JENKINS MARIGOLD.DAT
MASON SYSTEM.SRC
WATERS CRYSTAL.CAV
|
B.10 CALC.COM 命令过程
执行算术计算,并把结果值转换为十六进制和十进制值。
例子: CALC.COM
$ ! Procedure to calculate expressions. If you enter an
$ ! assignment statement, then CALC.COM evaluates the expression
$ ! and assigns the result to the symbol you specify. In the next
$ ! iteration, you can use either your symbol or the symbol Q to
$ ! represent the current result.
$ !
$ ! If you enter an expression, then CALC.COM evaluates the
$ ! expression and assigns the result to the symbol Q. In
$ ! the next iteration, you can use the symbol Q to represent
$ ! the current result.
$ !
$ SAVE_VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE")
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(0)
$ START:
$ ON WARNING THEN GOTO START (1)
$ INQUIRE STRING "Calc" (2)
$ IF STRING .EQS. "" THEN GOTO CLEAN_UP
$ IF F$LOCATE("=",STRING) .EQ. F$LENGTH(STRING) THEN GOTO EXPRESSION
$ !
$ ! Execute if string is in the form symbol = expression
$ STATEMENT: (3)
$ 'STRING' ! Execute assignment statements
$ SYMBOL = F$EXTRACT(0,F$LOCATE("=",STRING)-1,STRING) ! get symbol name
$ Q = 'SYMBOL' ! Set up q for future iterations
$ LINE = F$FAO("Decimal = !SL Hex = !-!XL Octal = !-!OL",Q)
$ WRITE SYS$OUTPUT LINE
$ GOTO START
$ !
$ !
$ ! Execute if string is an expression
$ EXPRESSION: (4)
$ Q = F$INTEGER('STRING') ! Can use Q in next iteration
$ LINE = F$FAO("Decimal = !SL Hex = !-!XL Octal = !-!OL",Q)
$ WRITE SYS$OUTPUT LINE
$ GOTO START
$ !
$ CLEAN_UP:
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(SAVE_VERIFY_PROCEDURE,SAVE_VERIFY_IMAGE)
$ EXIT
|
CALC.COM 命令过程的注解
- 过程建立一个重新启动过程的出错处理条件。如果发生一个警告或更严重的出错,那么过程转移到重新设置 ON
条件的开始点。
如果用户输入一个错误的表达式,那么这个技术确保过程将不会退出。 - INQUIRE 命令提示输入算术表达式。过程接受的表达式格式如下:
如果按下 Return,那么过程假定结束 CALC
对话期并退出。 如果按格式 "name = expression" 输入,那么过程将在标号 STATEMENT 继续执行。否则,过程转移到标号 EXPRESSION。
- 过程执行赋值语句,并把表达式的结果赋值给符号。然后过程抽取符号名,并把符号的值赋值给 Q。这允许您在过程的下一个循环中使用 Q 或您的符号。然后,过程显示结果并转移回标号 START。
- 过程求表达式的值,并把结果赋值给符号 Q。这允许您在过程的下一个循环中使用
Q。然后,过程显示结果并转移回标号 START。
执行 CALC.COM 命令过程的样例
$ @CALC
Calc: 2 * 30
Decimal = 60 Hex = 0000003C Octal = 00000000074
Calc: Q + 3
Decimal = 63 Hex = 0000003F Octal = 00000000077
Calc: TOTAL = Q + 4
Decimal = 67 Hex = 00000043 Octal = 00000000103
Calc: 5 + 7
Decimal = 12 Hex = 0000000C Octal = 00000000014
Calc:[Return]
$
|
在过程的每个提示之后,用户输入一个算术表达式。过程按十进制、十六进制和八进制格式显示结果。通过按下 Return 输入一行不带数据的空行,结束 CALC 对话期。
B.11 BATCH.COM 命令过程
接受一个命令字符串、命令过程或一列命令,然后以批量作业模式执行这些命令。
例子: BATCH.COM
$ VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE")
$ VERIFY_PROCEDURE = F$VERIFY(0)
$!
$! Turn off verification and save current settings.
$! (This comment must appear after you turn verification
$! off; otherwise it will appear in the batch job log file.)
$!
$!
$! If this is being executed as a batch job,
$! (from the SUBMIT section below) go to the EXECUTE_BATCH_JOB section
$! Otherwise, get the information you need to prepare to execute the
$! batch job.
$!
$ IF F$MODE() .EQS. "BATCH" THEN GOTO EXECUTE_BATCH_JOB (1)
$!
$!
$! Prepare to submit a command (or a command procedure) as a batch job.
$! First, determine a mnemonic process name for the batch job. Use the
$! following rules:
$!
$! 1) If the user is executing a single command, then use the verb name.
$! Strip off any qualifiers that were included with the command.
$! 2) If the user is executing a command procedure, then use the file name.
$! 3) Otherwise, use BATCH.
$!
$ JOB_NAME = P1 (2)
$ IF JOB_NAME .EQS. "" THEN JOB_NAME = "BATCH"
$ IF F$EXTRACT(0,1,JOB_NAME) .EQS. "@" THEN JOB_NAME = F$EXTRACT(1,999,JOB_NAME)
$ JOB_NAME = F$EXTRACT(0,F$LOCATE("/",JOB_NAME),JOB_NAME)
$ JOB_NAME = F$PARSE(JOB_NAME,,,"NAME","SYNTAX_ONLY")
$ IF JOB_NAME .EQS. "" THEN JOB_NAME = "BATCH"
$!
$!
$! Get the current default device and directory.
$!
$ ORIGDIR = F$ENVIRONMENT("DEFAULT")
$!
$!
$! Concatenate the parameters to form the command string to be executed.
$! If the user did not enter a command string, the symbol COMMAND will have
$! a null value.
$!
$ COMMAND = P1 + " " + P2 + " " + P3 + " " + P4 + " " + - (3)
P5 + " " + P6 + " " + P7 + " " + P8
$!
$!
$! If the user is executing a single command and if both the command and the
$! original directory specification are small enough to be passed as
$! parameters to the SUBMIT command, then submit the batch job now.
$!
$ IF (P1 .NES. "") .AND. (F$LENGTH(COMMAND) .LE. 255) .AND. - (4)
(F$LENGTH(ORIGDIR) .LE. 255) THEN GOTO SUBMIT
$!
$!
$! If the single command to be executed in the batch job is very large, or
$! if you have to prompt for commands to execute in the batch job, then
$! create a temporary command procedure to hold those commands and get the
$! fully expanded name of the command procedure.
$!
$ CREATE_TEMP_FILE:
$ ON CONTROL_Y THEN GOTO CONTROL_Y_HANDLER (5)
$ OPEN/WRITE/ERROR=FILE_OPEN_ERROR TEMPFILE SYS$SCRATCH:'JOB_NAME'.TMP (6)
$ FILESPEC = F$SEARCH("SYS$SCRATCH:" + JOB_NAME + ".TMP")
$!
$! By default, have the batch job continue if it encounters any errors.
$!
$ WRITE TEMPFILE "$ SET NOON"
$!
$! Either write the single large command to the file, or prompt for
$! multiple commands and write them to the file.
$!
$ IF COMMAND .NES. " " THEN GOTO WRITE_LARGE_COMMAND
$
$ LOOP:
$ READ /END_OF_FILE=CLOSE_FILE /PROMPT="Command: " SYS$COMMAND COMMAND
$ IF COMMAND .EQS. "" THEN GOTO CLOSE_FILE
$ WRITE TEMPFILE "$ ",COMMAND
$ GOTO LOOP
$
$ WRITE_LARGE_COMMAND:
$ WRITE TEMPFILE "$ ",COMMAND
$
$!
$! Finish the temporary file by defining a symbol so that you will know
$! the name of the command procedure to delete and then close the file.
$! Define the symbol COMMAND to mean "execute the command procedure
$! you have just created." Then submit the batch job and execute
$! this command procedure in the batch job.
$!
$ CLOSE_FILE: (7)
$ WRITE TEMPFILE "$ BATCH$DELETE_FILESPEC == """,FILESPEC,""""
$ CLOSE TEMPFILE
$ ON CONTROL_Y THEN EXIT
$ COMMAND = "@" + FILESPEC
$!
$!
$! Submit BATCH.COM as a batch job, and pass it two parameters.
$! P1 is the command (or name of the command procedure) to execute.
$! P2 is the directory from which to execute the command.
$!
$ SUBMIT: (8)
$ SUBMIT/NOTIFY/NOPRINT 'F$ENVIRONMENT("PROCEDURE")' /NAME='JOB_NAME' -
/PARAMETERS=("''COMMAND'","''ORIGDIR'")
$ GOTO EXIT
$!
$!
$! The user pressed Ctrl/Y while the temporary command procedure was open.
$! Close the command procedure, delete it if it exists, and exit.
$!
$ CONTROL_Y_HANDLER: (9)
$ CLOSE TEMPFILE
$ IF F$TYPE(FILESPEC) .NES. "" THEN DELETE/NOLOG 'FILESPEC'
$ WRITE SYS$OUTPUT "Ctrl/Y caused the command procedure to abort."
$ GOTO EXIT
$!
$!
$! The temporary command procedure could not be created.
$! Notify the user and exit.
$!
$ FILE_OPEN_ERROR: (10)
$ WRITE SYS$OUTPUT "Could not create sys$scratch:",job_name,".tmp"
$ WRITE SYS$OUTPUT "Please correct the situation and try again."
$!
$!
$! Restore the verification states and exit.
$!
$ EXIT: (11)
$ VERIFY_PROCEDURE = F$VERIFY(VERIFY_PROCEDURE,VERIFY_IMAGE)
$ EXIT
$!
$!
$! BATCH.COM was invoked as a batch job. P1 contains the command
$! to execute and P2 the default directory specification.
$! Return a status code that indicates the termination status of P1.
$!
$ EXECUTE_BATCH_JOB: (12)
$ SET NOON
$ VERIFY_PROCEDURE = F$VERIFY(VERIFY_PROCEDURE,VERIFY_IMAGE)
$ SET DEFAULT 'P2'
$ 'P1'
$ IF F$TYPE(BATCH$DELETE_FILESPEC) .EQS. "" THEN EXIT $STATUS
$ STATUS = $STATUS
$ DELETE /NOLOG 'BATCH$DELETE_FILESPEC'
$ EXIT STATUS
|
BATCH.COM 命令过程的注解
- 这个 IF 语句测试 BATCH.COM 是否执行在批量模式下。当交互地调用 BATCH.COM
时,您提供 (作为参数) 一个要执行为一个批量作业的命令字符串或命令过程。如果不提供任何参数,那么 BATCH.COM
提示输入命令,把这些命令写入一个文件,然后把这个命令过程执行为一个批量作业。在 BATCH.COM 准备执行批量作业的命令之后,它使用 SUBMIT
命令把本身提交为一个批量作业,并执行这个作业中的命令。(请参阅注释 8。) 当把 BATCH.COM 调用为一个批量作业时,过程转移到标号 EXECUTE_BATCH_JOB。注意,如果以批量模式执行 BATCH.COM,必须把要执行的命令或命令过程指定为 P1,把默认目录指定为 P2。
- 这些命令准备
要执行的批量作业。首先,过程构造批量作业名。如果传递一个命令字符串,那么 BATCH.COM 使用其动词名称作为作业名。如果传递一个命令过程,那么 BATCH.COM 使用其文件名。如果没有传递的输入,那么 BATCH.COM 把这个作业命名为 BATCH。
- 连接这些参数,以形成要执行的命令字符串。这个命令字符串被赋予符号 COMMAND。
- SUBMIT 命令不能传递大于 255
个字符的参数。因此,过程测试命令字符串和目录名长度是小于 255 个字符的。如果两个字符串都小于 255 个字符
(并且如果用户确实传递了一个命令字符串),那么过程转移到标号 SUBMIT。
- 过程建立一个 Ctrl/Y 处理程序,因而在这段命令过程中如果用户按下 Ctrl/Y,就执行清除操作。
- 过程建立一个临时文件包含要执行的命令。如果用户提供一个长的命令字符串,那么过程转移到 WRITE_LARGE_COMMAND,并把这个命令写入临时文件。否则,过程提示输入要执行的命令。每个命令被写入临时文件。
- 在关闭临时文件之前,把符号赋值语句写入这个文件。这个语句把临时文件的文件名赋值到符号 BATCH$DELETE_FILESPEC。在关闭这个临时文件之后,过程重新设置默认的
Ctrl/Y 处理程序。然后过程定义符号 COMMAND,以便执行时,符号 COMMAND 调用临时的命令文件。
-
过程把本身提交为一个批量作业,使用定义的作业名。(请参阅注释 2。) 过程也传递两个参数:
要执行的命令或命令过程,和命令应该从此执行的目录。然后过程转移到标号 EXIT。(请参阅注释 11。)
- 当临时文件建立时,如果用户输入 Ctrl/Y,本段就执行清除操作。
-
如果不能建立临时文件,本段就写入出错消息。
- 过程重新设置原始的校验设置,然后退出。
-
当 BATCH.COM 以批量模式运行时,就执行这些命令。首先,撤消 ON 出错处理,并且设置用户的默认校验设置。然后,其默认设置为 P2 指出的目录,并且执行 P1 指出的命令或命令过程。如果建立一个临时文件,那么就删除这个文件。在删除
BATCH$DELETE_FILESPEC 之前,保存 P1 的完成状态。这个完成状态通过 EXIT
命令返回。
执行 BATCH.COM 命令过程的样例
$ @BATCH RUN MYPROG
Job RUN (queue SYS$BATCH, entry 1715) started on SYS$BATCH
|
这个例子使用 BATCH.COM 运行批量作业中的程序。B.12 COMPILE_FILE.COM 命令过程
编译、链接和运行用 Pascal 或 FORTRAN 编写的文件。它提示输入要处理的文件,确定文件类型是 .PAS
还是 .FOR。如果文件类型不是 .PAS 或 .FOR,或者如果在当前默认目录中不存在这个文件,那么命令过程输出适当的出错消息。这个过程说明如何使用
IF-THEN-ELSE 语言构造。
例子: COMPILE_FILE.COM
$! This command procedure compiles, links, and runs a file written in Pascal
$! or FORTRAN.
$!
$ ON CONTROL_Y THEN EXIT
$!
$ TOP:
$ INQUIRE FILE "File to process"
$ IF F$SEARCH(FILE) .NES. "" (1)
$ THEN
$ FILE_TYPE = F$PARSE(FILE,,,"TYPE") (2) ! determine file type
$ FILE_TYPE = F$EXTRACT(1,F$LENGTH('FILE_TYPE'),FILE_TYPE) ! remove period
$! Remove type from file specification
$ PERIOD_LOC = F$LOCATE(".",FILE)
$ FILE = F$EXTRACT(0,PERIOD_LOC,FILE)
$ ON WARNING THEN GOTO OTHER
$ GOTO 'FILE_TYPE'
$ ELSE (3)
$ WRITE SYS$OUTPUT FILE, "does not exist"
$ ENDIF (4)
$!
$ GOTO END
$!
$!
$!
$ FOR: (5)
$ ON ERROR THEN GOTO PRINT
$ FORTRAN/LIST 'FILE'
$ GOTO LINK
$!
$ PAS:
$ ON ERROR THEN GOTO PRINT
$ PASCAL/LIST 'FILE'
$ GOTO LINK
$!
$ OTHER:
$ WRITE SYS$OUTPUT "Can't handle files of type .''FILE_TYPE'"
$ GOTO END
$!
$ LINK: (6)
$ ON ERROR THEN GOTO END
$ WRITE SYS$OUTPUT "Successful compilation ...."
$ LINK 'FILE'
$ DEFINE/USER_MODE SYS$INPUT SYS$COMMAND
$ RUN 'FILE'
$ GOTO CLEANUP
$!
$ PRINT: (7)
$ WRITE SYS$OUTPUT "Unsuccessful compilation, printing listing file ...."
$ PRINT 'FILE'
$!
$ CLEANUP:
$ DELETE 'FILE'.OBJ;
$ DELETE 'FILE'.LIS;
$!
$ END:
$ INQUIRE/NOPUNCTUATION ANS "Process another file (Y or N)? "
$ IF ANS THEN GOTO TOP
$ EXIT
|
COMPILE_FILE.COM 命令过程的注解
- IF 命令使用 F$SEARCH 词法函数搜索目录,并且确定这个文件是否存在。
- 跟随
THEN 命令的命令块:
- 使用 F$LENGTH 词法函数确定文件类型的长度
- 确定文件类型
- 除去文件类型中的句点
- 除去文件说明中的文件类型来确定文件名
- 除去文件名中的句点
- 定义如果出错发生则执行的动作
- 转移到符号 FILE_TYPE 定义的标号
- 如果在 "File to process:" 提示中输入的文件在目录中不存在,那么执行跟随 ELSE 命令的命令。
- ENDIF 命令结束 IF-THEN-ELSE
命令语言构造。
- 过程编译这个 FORTRAN 程序,并转移到 LINK 标号。如果在编译期间出错发生,那么过程转移到 PRINT 标号。
-
过程显示程序正确编译,链接和运行程序,并转移到
CLEANUP 标号。如果出错发生,程序就转移到 END 标号。
- 过程把程序的列出文件加入默认打印队列。
执行 COMPILE_FILE.COM 命令过程的样例
$ @COMPILE_FILE
File to process: RAND.PAS
Successful compilation
%DELETE-I-FILDEL,WORK:[DESCH]RAND.OBJ;1 deleted (3 blocks)
%DELETE-I-FILDEL,WORK:[DESCH]RAND.LIS;1 deleted (9 blocks)
Process another file (Y or N)? N [Return]
|
|