[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS 用户手册


前页 目录 索引


附录 B
详解命令过程

本附录包含使用第 13 章第 14 章第 15 章论述的概念和技术建立完整命令过程。本附录的每一节论述一个命令过程,并提供以下信息:

  • 过程名
  • 一列过程
  • 注解解释过程使用的概念或技术
  • 样例过程的执行结果

B.1 CONVERT.COM 命令过程

这个命令过程把一个绝对时间 (将来的某个时间) 转换为一个相对时间,并且确定在当前时间和指定时间之间的时间长短。这个过程说明如何使用 F$TIME 和 F$CVTIME 词法函数,以及使用赋值语句来执行算术计算和连接符号值。

例子: CONVERT.COM


$ ! Procedure to convert an absolute time to a delta time.
$ ! The delta time is returned as the global symbol WAIT_TIME.
$ ! P1 is the time to be converted.
$ ! P2 is an optional parameter - SHOW - that causes the
$ ! procedure to display WAIT_TIME before exiting
$ !
$ ! Check for inquiry
$ !
$ IF P1 .EQS. "?" .OR. P1 .EQS. "" THEN GOTO TELL          (1)
$ !
$ ! Verify the parameter:  hours must be less than 24
$ !                        minutes must be less than 60
$ !                        time string must contain only hours
$ !                        and minutes
$ !
$ ! Change error and message handling to
$ ! use message at BADTIME
$ !
$ ON WARNING THEN GOTO BADTIME                             (2)
$ SAVE_MESSAGE = F$ENVIRONMENT("MESSAGE")
$ SET MESSAGE/NOFACILITY/NOIDENTIFICATION/NOSEVERITY/NOTEXT
$ TEMP = F$CVTIME(P1)
$ !
$ ! Restore default error handling and message format
$ ON ERROR THEN EXIT
$ SET MESSAGE'SAVE_MESSAGE'
$ !
$ IF F$LENGTH(P1) .NE. 5 .OR. -                            (3)
        F$LOCATE(":",P1) .NE. 2 -
        THEN GOTO BADTIME
$ !
$ ! Get the current time
$ !
$ TIME = F$TIME()                                          (4)
$ !
$ ! Extract the hour and minute fields from both the current time
$ ! value (TIME) and the future time (P1)
$ !
$ MINUTES = F$CVTIME(TIME,"ABSOLUTE","MINUTE")       ! Current minutes (5)
$ HOURS = F$CVTIME(TIME,"ABSOLUTE","HOUR")           ! Current hours
$ FUTURE_MINUTES = F$CVTIME(P1,"ABSOLUTE","MINUTE")  ! Minutes in future time
$ FUTURE_HOURS = F$CVTIME(P1,"ABSOLUTE","HOUR")      ! Hours in future time
$ !
$ !
$ ! Convert both time values to minutes
$ ! Note the implicit string to integer conversion being performed
$ !
$ CURRENT_TIME = HOURS*60 + MINUTES                        (6)
$ FUTURE_TIME = FUTURE_HOURS*60 + FUTURE_MINUTES
$ !
$ ! Compute difference between the future time and the current time
$ ! (in minutes)
$ !
$ !
$ MINUTES_TO_WAIT = FUTURE_TIME - CURRENT_TIME             (7)
$ !
$ ! If the result is less than 0 the specified time is assumed to be
$ ! for the next day; more calculation is required.
$ !
$ IF MINUTES_TO_WAIT .LT. 0 THEN -                         (8)
        MINUTES_TO_WAIT = 24*60 + FUTURE_TIME - CURRENT_TIME
$ !
$ ! Start looping to determine the value in hours and minutes from
$ ! the value expressed all in minutes
$ !
$       HOURS_TO_WAIT = 0
$ HOURS_TO_WAIT_LOOP:                                      (9)
$       IF MINUTES_TO_WAIT .LT. 60 THEN GOTO FINISH_COMPUTE
$       MINUTES_TO_WAIT = MINUTES_TO_WAIT - 60
$       HOURS_TO_WAIT = HOURS_TO_WAIT + 1
$       GOTO HOURS_TO_WAIT_LOOP
$ FINISH_COMPUTE:
$ !
$ ! Construct the delta time string in the proper format
$ !
$ WAIT_TIME == F$STRING(HOURS_TO_WAIT)+ ":" + F$STRING(MINUTES_TO_WAIT)- (10)
  + ":00.00"
$ !
$ ! Examine the second parameter
$ !
$ IF P2 .EQS.  "SHOW" THEN SHOW SYMBOL WAIT_TIME           (11)
$ !
$ ! Normal exit
$ !
$ EXIT
$ !
$ BADTIME:                                                 (12)
$ ! Exit taken if first parameter is not formatted correctly
$ ! EXIT command returns but does not display error status
$ !
$ SET MESSAGE'SAVE_MESSAGE'
$ WRITE SYS$OUTPUT  "Invalid time value: ",P1,", format must be hh:mm"
$ WRITE SYS$OUTPUT "Hours must be less than 24; minutes must be less than 60"
$ EXIT %X10000000
$ !
$ !
$ TELL:                                                    (13)
$ ! Display message and exit if user enters inquiry or enters
$ ! an illegal parameter
$ !
$ TYPE SYS$INPUT
        This procedure converts an absolute time value to
        a delta time value.  The absolute time must be in
        the form hh:mm and must indicate a time in the future.
        On return, the global symbol WAIT_TIME contains the
        converted time value.  If you enter the keyword SHOW
        as the second parameter, the procedure displays the
        resulting value in the output stream. To invoke this
        procedure, use the following syntax:

                       @CONVERT hh:mm [SHOW]
$ EXIT

CONVERT.COM 命令过程的注解

  1. 过程检查参数是否被省略,或者为参数输入的值是否是问号 (?) 字符。在任何一种情况下,过程分支到标号 TELL。
  2. 过程使用 F$CVTIME 函数验证时间值是一个有效 24 小时时钟时间;如果输入时间无效,F$CVTIME 返回一条警告消息。如果 F$CVTIME 函数返回出错,那么过程更改默认 ON 动作把控制指引到标号 BADTIME。
    过程使用 F$ENVIRONMENT 函数保存当前消息设置。然后它设置消息格式,以便不显示警告或出错消息。在检查这个时间值之后,过程恢复默认 ON 条件和消息格式。
  3. 过程检查参数的格式。它必须是按以下格式的时间值:

    hh:mm


    IF 命令检查:(1) 输入值的长度是 5 个字符,和 (2) 第三个字符 (偏移 2) 是冒号。IF 命令包含逻辑 OR 运算符: 如果任意一个表达式为真 (即,如果长度不是 5 或者如果在第三个字符位置没有冒号),那么过程分支到标号 BADTIME。

  4. F$TIME 词法函数把当前时间值放入符号 TIME。
  5. F$CVTIME 函数从当前时间 (已保存在符号 TIME 中) 抽取 "分钟" 和 "小时" 字段。然后 F$CVTIME 函数从想要转换的时间抽取其 "分钟" 和 "小时" 字段。
  6. 这些赋值语句把当前和将来时间转换为分钟。在赋值语句中使用符号 MINUTES、HOURS、FUTURE_HOURS 和 FUTURE_MINUTES 时,系统自动把这些值转换为整数。
  7. 然后,过程从将来时间 (以分钟为单位) 减去当前时间 (以分钟为单位)。
  8. 如果结果小于 0,那么将来时间解释为下一日。在这种情况下,过程添加 24 小时给将来时间,然后减去当前时间 。
  9. 过程进入循环,在此它根据 MINUTES_TO_WAIT 的值计算小时数。每次通过循环,它检查 MINUTES_TO_WAIT 是否大于 60。如果它是,过程从 MINUTES_TO_WAIT 减去 60 并且添加 1 给小时数的累加器 (HOURS_TO_WAIT)。
  10. 当过程退出循环时,它把小时和分钟值连接到一个时间字符串。符号 HOURS_TO_WAIT 和 MINUTES_TO_WAIT 被替换为它们的等价字符串,并且用冒号分隔。其结果字符串被赋值给符号 WAIT_TIME,它拥有将来时间的相对时间值。WAIT_TIME 定义为全局符号,以便当过程 CONVERT.COM 退出时它不会被删除。
  11. 如果输入第二个参数 SHOW,那么过程显示作为结果的时间值。否则,它退出。
  12. 在标号 BADTIME 位置,过程显示一条出错消息,展示错误的输入值以及它需要的格式。在发出出错消息之后,CONVERT.COM 就退出。EXIT 命令返回一个出错状态,其高端数字设置为 1。这样可取消显示出错消息。
    过程用 EXIT 命令明确地指定出错状态,因而可以从另一个过程执行 CONVERT.COM。当 CONVERT.COM 完成时,调用过程可以确定时间是否成功翻译。
  13. 在标号 TELL 位置,过程显示过程做什么的信息。TYPE 命令显示在输入数据流 SYS$INPUT 中列出的行。

执行 CONVERT.COM 命令过程的样例


$ SHOW TIME
10-JUN-1999 10:38:26
$ @CONVERT 12:00 SHOW
   WAIT_TIME = "1:22:00.00"

SHOW TIME 命令显示当前日期和时间。CONVERT.COM 以参数 12:00 和 SHOW 执行。过程把绝对时间 12:00 转换为相对时间值,并显示在终端上。

B.2 REMINDER.COM 命令过程

这个命令过程于指定时间在终端上显示提示消息。过程提示想要显示消息的时间和消息文本。过程使用 CONVERT.COM 把时间转换为相对时间。然后,过程派生一个子进程等待指定时间后显示提示消息。过程说明如何使用 F$ENVIRONMENT、F$VERIFY 和 F$GETDVI 函数。

例子: REMINDER.COM


$ ! Procedure to obtain a reminder message and display this
$ ! message on your terminal at the time you specify.
$ !
$ ! Save current states for procedure and image verification
$ ! Turn verification off for duration of procedure
$
$ SAVE_VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE")               (1)
$ SAVE_VERIFY_PROC = F$VERIFY(0)
$ !
$ ! Places the current process in a wait state until a specified
$ ! absolute time.  Then, it rings the bell on the terminal and
$ ! displays a message.
$ !
$ ! Prompt for absolute time
$ !
$
$ GET_TIME:
$ INQUIRE REMINDER_TIME  "Enter time to send reminder (hh:mm)"    (2)
$ INQUIRE MESSAGE_TEXT "Enter message"
$ !
$ ! Call the CONVERT.COM procedure to convert the absolute time
$ ! to a delta time
$ !
$ @DISK2:[JONES.TOOLS]CONVERT 'REMINDER_TIME'                     (3)
$ IF .NOT. $STATUS THEN GOTO BADTIME
$ !
$ !
$ ! Create a command file that will be executed
$ ! in a subprocess.  The subprocess will wait until
$ ! the specified time and then display your message
$ ! at the terminal.  If you are working at a DEC_CRT
$ ! terminal, the message has double size blinking
$ ! characters. Otherwise, the message has normal letters.
$ ! In either case, the terminal bell rings when the
$ ! message is displayed.
$
$ CREATE WAKEUP.COM                                        (4)
$ DECK                            ! Lines starting with $ are data lines
$ WAIT 'WAIT_TIME'                                         (5)
$ BELL[0,7] = %X07                ! Create symbol to ring the bell
$ IF F$GETDVI("SYS$OUTPUT","TT_DECCRT") .NES. "TRUE" THEN GOTO OTHER_TERM
$ !
$ DEC_CRT_ONLY:
$ ! Create symbols to set special graphics (for DEC_CRT terminals only)
$ !
$     SET_FLASH = "<ESC>[1;5m"    ! Turn on blinking characters
$     SET_NOFLASH = "<ESC>[0m"    ! Turn off blinking characters
$     TOP = "<ESC>#3"             ! Double size characters (top portion)
$     BOT = "<ESC>#4"             ! Double size characters (bottom portion)
$ !
$ ! Write double size, blinking message to the terminal and ring the bell
$ !
$     WRITE SYS$OUTPUT BELL, SET_FLASH, TOP, MESSAGE_TEXT
$     WRITE SYS$OUTPUT BELL, BOT, MESSAGE_TEXT
$     WRITE SYS$OUTPUT F$TIME(), SET_NOFLASH
$     GOTO CLEAN_UP
$ !
$ OTHER_TERM:
$      WRITE SYS$OUTPUT BELL,MESSAGE_TEXT
$      WRITE SYS$OUTPUT F$TIME()
$ !
$ CLEAN_UP:
$      DELETE WAKEUP.COM;*
$ EOD
$ !
$ ! Now continue executing commands.
$ !
$ SPAWN/NOWAIT/INPUT=WAKEUP.COM                            (6)
$ END:                                                     (7)
$ !   Restore verification
$     SAVE_VERIFY_PROC = F$VERIFY(SAVE_VERIFY_PROC, SAVE_VERIFY_IMAGE)
$     EXIT
$ !
$ BADTIME:
$    WRITE SYS$OUTPUT "Time must be entered as hh:mm"
$    GOTO GET_TIME

REMINDER.COM 命令过程的注解

  1. 过程使用 F$ENVIRONMENT 函数把映象校验设置保存在符号 SAVE_VERIFY_IMAGE 中。然后,过程使用 F$VERIFY 函数把过程校验设置保存在符号 SAVE_VERIFY_PROC 中。F$VERIFY 函数也停掉这两类校验。
  2. 过程使用 INQUIRE 命令提示输入应该发送提示消息的时间。这个值用作过程 CONVERT.COM 的输入。过程也提示输入消息的文本。
  3. 过程执行嵌套过程 CONVERT.COM。确信已指定磁盘和目录作为文件说明的一部分;这确保系统可以找出 CONVERT.COM,而不管您是从哪个目录执行 REMINDER.COM。
    CONVERT.COM 把提示转换为相对时间,并把这个时间返回到全局符号 WAIT_TIME。这个相对时间指出从当前时间直到应该发送消息的时间之间的时间间隔。如果 CONVERT.COM 返回出错,过程就分支到标号 BADTIME。
  4. 过程使用 CREATE 命令建立新过程 WAKEUP.COM。这个过程是从一个子进程执行。要允许 CREATE 命令读取开始于美元符的行,使用 DECK 和 EOD 命令包围 CREATE 命令的输入。因此,在 DECK 和 EOD 命令之间的所有行被写入 WAKEUP.COM。
  5. WAKEUP.COM 执行以下任务:
    • 它等待,直到符号 WAIT_TIME 指出的时间。
    • 它建立符号 BELL 使终端响铃。
    • 它确定终端是否是 DEC_CRT 终端并且可以接受换码序列显示双大小、闪烁字符。(要查看是否有 DEC_CRT 终端,可输入 SHOW TERMINAL 命令并查看是否列出这个特征。)
    • 如果终端是 DEC_CRT 终端,那么过程定义符号 SET_FLASH、TOP 和 BOT。这些符号使终端使用闪烁、双大小字符。过程也定义符号 SET_NOFLASH 把终端返回到正常状态。当使用 EDT 编辑程序建立这些定义时要输入换码符 (<ESC>),可按下 ESC 键两次。
      在定义这些符号之后,过程把三行写入终端。第一行响铃,启动闪烁字符,并显示 (使用双大小字符) 消息的上半部。第二行再次响铃并显示消息的下半部。第三行写入当前时间,然后停掉闪烁特征,并把终端返回到正常状态。
      如果没有 DEC_CRT 终端,过程就响起终端铃,并显示消息和时间。
    • DELETE 命令使过程 WAKEUP.COM 在执行之后删除本身。
  6. 在建立 WAKEUP.COM 之后,过程派生一个子进程并指示这个子进程使用 WAKEUP.COM 作为输入命令文件。/NOWAIT 限定词允许您在子进程执行 WAKEUP.COM 命令的同时继续在您的终端上工作。在指定的时间,WAKEUP.COM 在终端上显示您的消息。
    注意,按照默认,SPAWN 命令把全局和局部符号传递给子进程。因此,虽然您是在 REMINDER.COM 中为符号 WAIT_TIME 和 MESSAGE_TEXT 提供值,但是,WAKEUP.COM 也可以存取这些符号。
  7. 过程在退出之前恢复原始的校验设置。

执行 REMINDER.COM 命令过程的样例


$ @REMINDER
Enter time to send reminder (hh:mm): 12:00
Enter message: TIME FOR LUNCH
%DCL-S-SPAWNED, process BLUTO_1 spawned
$
   .
   .
   .
TIME FOR LUNCH
11-DEC-1999 12:00:56.99

过程提示输入时间值和消息。然后,过程派生一个显示消息的子进程。可以继续在您的终端上工作;在指定的时间,子进程响起终端的铃声,显示消息和时间。

B.3 DIR.COM 命令过程

这个命令过程模仿 DCL 命令 DIRECTORY/SIZE=ALL/DATE,显示指定文件的块大小 (已使用和已分配) 和建立日期。它说明如何使用 F$PARSE、F$SEARCH、F$FILE_ATTRIBUTES 和 F$FAO 词法函数。

例子: DIR.COM


$ !
$ ! Command procedure implementation of DIRECTORY/SIZE=ALL/DATE
$ ! command
$ !
$ SAVE_VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE")
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(0)
$ !
$ ! Replace any blank field of the P1 file specification with
$ ! a wildcard character
$ !
$ P1 = F$PARSE(P1,"*.*;*")                                 (1)
$ !
$ ! Define initial values for symbols
$ !
$ FIRST_TIME = "TRUE"
$ FILE_COUNT = 0
$ TOTAL_ALLOC = 0
$ TOTAL_USED = 0
$
$ LOOP:                                                    (2)
$       FILESPEC = F$SEARCH(P1)
$ ! Find next file in directory
$       IF FILESPEC .EQS. "" THEN GOTO DONE
$ ! If no more files, then done
$       IF .NOT. FIRST_TIME THEN GOTO SHOW_FILE
$ ! Print header only once
$ !
$ ! Construct and output the header line
$ !
$       FIRST_TIME =  "FALSE"                              (3)
$       DIRSPEC = F$PARSE(FILESPEC,,, "DEVICE") -
                +F$PARSE(FILESPEC,,, "DIRECTORY")
$       WRITE SYS$OUTPUT ""
$       WRITE SYS$OUTPUT  "Directory ",DIRSPEC
$       WRITE SYS$OUTPUT ""
$       LASTDIR = DIRSPEC
$
$ !
$ ! Put the file name together, get some of the file attributes, and
$ ! type the information out
$ !
$SHOW_FILE:
$       FILE_COUNT = FILE_COUNT + 1
$       FILENAME = F$PARSE(FILESPEC,,, "NAME") -           (4)
                 + F$PARSE(FILESPEC,,, "TYPE") -
                 + F$PARSE(FILESPEC,,, "VERSION")
$      ALLOC = F$FILE_ATTRIBUTES(FILESPEC, "ALQ")
$      USED = F$FILE_ATTRIBUTES(FILESPEC, "EOF")
$      TOTAL_ALLOC = TOTAL_ALLOC + ALLOC
$      TOTAL_USED = TOTAL_USED + USED
$      REVISED = F$FILE_ATTRIBUTES(FILESPEC,"RDT")
$      LINE = F$FAO("!19AS !5UL/!5<!UL!> !17AS",FILENAME,-
               USED, ALLOC, REVISED)
$      WRITE SYS$OUTPUT LINE
$      GOTO LOOP
$
$ !
$ ! Output summary information, reset verification, and exit
$ !
$ DONE:                                                    (5)
$      WRITE SYS$OUTPUT ""
$      WRITE SYS$OUTPUT "Total of ''FILE_COUNT' files, " + -
                        "''TOTAL_USED'/''TOTAL_ALLOC' blocks."
$      SAVE_VERIFY_PROCEDURE = F$VERIFY(SAVE_VERIFY_PROCEDURE,SAVE_VERIFY_IMAGE)
$      EXIT

DIR.COM 命令过程注解

  1. 这个过程使用 F$PARSE 函数把星号放在用户提供的文件说明 P1 的空白字段中。执行 DIR.COM 时,如果没有指定参数,那么 F$PARSE 函数把值 "*.*;*" 赋予 P1。这使 DIR.COM 显示当前默认目录的所有文件。
  2. F$SEARCH 词法函数搜索目录查找 P1 指出的文件。如果 P1 包含任何通配符 (星号),那么 F$SEARCH 函数返回所有匹配的文件说明。在返回最后一个文件说明之后,过程分支到标号 DONE。
  3. 第一次通过循环时,过程为目录显示写入标题。这个标题包括设备和目录名。要获得这些名称,过程使用 F$PARSE 函数。
  4. 过程使用 F$PARSE 词法函数从目录中的每个文件说明抽取文件名。然后,F$FILE_ATTRIBUTES 词法函数获得每个文件的使用块、分配块和建立日期的信息。最后,F$FAO 函数 为目录的每个文件格式化单个显示行。F$FAO 函数使用文件名和文件属性信息作为变元。
  5. 当 F$SEARCH 返回空串时,过程分支到标号 DONE 并显示概要信息,展示在目录中的文件总数、使用块总数和分配块总数。

执行 DIR.COM 命令过程的样例


$ @DIR [VERN]*.COM


目录 DISK4:[VERN]

BATCH.COM;1             1/3     11-DEC-1999 11:43
CALC.COM;3              1/3     11-DEC-1999 11:30
CONVERT.COM;1           5/6     11-DEC-1999 15:23
   .
   .
   .
LOGIN.COM;34            2/3     11-DEC-1999 13:17
PID.COM;7               1/3     11-DEC-1999 09:49
SCRATCH.COM;6           1/3     11-DEC-1999 11:29)

共 15 文件, 22/48 块。

过程返回在目录 [VERN] 中的所有 .COM 文件的信息。

B.4 SYS.COM 命令过程

这个命令过程返回有关当前进程、组中所有进程 (如果当前进程有组特权) 和系统中所有进程 (如果当前进程有全体用户特权) 的统计信息。这个过程说明如何使用 F$PID、F$EXTRACT 和 F$GETJPI 词法函数 。

例子: SYS.COM


$ !
$ ! Displays information about owner, group, or system processes.
$ !
$ ! Turn off verification and save current settings
$ SAVE_VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE")
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(0)
$ CONTEXT = ""                     ! Initialize PID search context  (1)
$ !
$ ! Output header line.
$ !
$ WRITE SYS$OUTPUT "   PID    Username    Term    Process " + -     (2)
         "name   State   Pri Image"
$ !
$ ! Output process information.
$ !
$LOOP:
$ !
$ ! Get next PID.  If null, then done.
$ !
$       PID = F$PID(CONTEXT)                               (3)
$       IF PID .EQS. "" THEN GOTO DONE
$ !
$ ! Get image file specification and extract the file name.
$ !
$       IMAGNAME = F$GETJPI(PID,"IMAGNAME")                (4)
$       IMAGNAME = F$PARSE(IMAGNAME,,,"NAME","SYNTAX_ONLY")
$ !
$ ! Get terminal name.  If none, then describe type of process.
$ !
$       TERMINAL = F$GETJPI(PID,"TERMINAL")                (5)
$       IF TERMINAL .EQS. "" THEN -
                TERMINAL = "-"+F$EXTRACT(0,3,F$GETJPI(PID,"MODE"))+"-"
$       IF TERMINAL .EQS. "-INT-" THEN TERMINAL = "-DET-"
$       IF F$GETJPI(PID,"OWNER") .NE. 0 THEN TERMINAL = "-SUB-"
$ !
$ ! Get more information, put process line together,
$ ! and output it.
$ !
$       LINE = F$FAO("!AS !12AS !7AS !15AS !5AS !2UL/!UL !10AS", - (6)
                PID,F$GETJPI(PID,"USERNAME"),TERMINAL,-
                F$GETJPI(PID,"PRCNAM"),-
                F$GETJPI(PID,"STATE"),F$GETJPI(PID,"PRI"),-
                F$GETJPI(PID,"PRIB"),IMAGNAME)
$       WRITE SYS$OUTPUT LINE
$       GOTO LOOP
$ !
$ ! Restore verification and exit.
$ !
$DONE:
$  SAVE_VERIFY_PROCEDURE = F$VERIFY(SAVE_VERIFY_PROCEDURE,SAVE_VERIFY_IMAGE)
$  EXIT

SYS.COM 命令过程注解


前页 后页 目录 索引