条件和条件陷阱
condition 是 CALL ON 或 SIGNAL ON 可以捕获的指定事件或状态。 条件陷阱可以修改 REXX 程序中的执行流。
如何启用条件陷阱
使用 SIGNAL 和 CALL 指令的 ON 或 OFF 子关键字打开或关闭条件陷阱 (请参阅 CALL 和 SIGNAL)。
condition 和 trapname 是作为常量的单个符号。 遵循其中一个指示信息,条件陷阱设置为 ON (已启用) 或 OFF (已禁用)。 所有条件陷阱的初始设置为 OFF。
如果启用了条件陷阱,并且发生了指定的 condition ,那么控制权将传递到例程或标签 trapname (如果已指定 trapname)。 否则,控制传递到例程或标签 condition。 将使用 CALL 或 SIGNAL ,具体取决于是使用 CALL ON 还是 SIGNAL ON 分别设置了条件的最新陷阱。
对条件陷阱的任何 ON 或 OFF 引用都将替换该条件陷阱的先前状态 (ON , OFF 或 DELAY 以及任何 trapname)。 因此, CALL ON HALT 将替换任何当前的 SIGNAL ON HALT (而 SIGNAL ON HALT 将替换任何当前的 CALL ON HALT) ,使用新陷阱名称的 CALL ON 或 SIGNAL ON 将替换任何先前的陷阱名称,任何 OFF 引用将禁用 CALL 或 SIGNAL 的陷阱等等。
什么会被困住
可能被困的条件及其对应事件如下:
- 错误
- 如果命令在返回时出现错误,则会产生错误条件。 如果任何命令指示失败,并且 CALL ON FAILURE 和 SIGNAL ON FAILURE 都未处于活动状态,那么也会发生此问题。 在调用该命令的子句末尾会提出该条件,但如果 ERROR 条件陷阱已处于延迟状态,那么将忽略该条件。 延迟状态是条件已启动但陷阱尚未重置为已启用 (ON) 或已禁用 (OFF) 状态时条件陷阱的状态。 请参阅 注释。
- FAILURE
- 如果命令在返回时指示失败条件,则表明出现失败条件。 该条件在调用该命令的子句的末尾提出,但如果 FAILURE 条件陷阱已处于延迟状态,那么将忽略该条件。
CALL ON FAILURE 和 将所有命令的负面返回代码都记录下来。 SIGNAL ON FAILURE
- 停止
- 如果外部试图中断并结束程序的执行,则会出现“暂停”状态。 通常在发生外部中断时正在处理的条款末尾提出该条件。
- 无值
- 当出现以下情况时,将触发NOVALUE条件:
- 未初始化的变量在表达式中用作术语。
- 在解析指令的VAR子关键词之后,未初始化的变量用作名称。
- 在解析模板、PROCEDURE指令或DROP指令中,未初始化的变量用作变量引用。
您只能对 SIGNAL ON 指定此条件。
注意: SIGNAL ON NOVALUE 可以捕获复合变量中除尾部以外的任何未初始化的变量。/* The following does not raise NOVALUE. */ signal on novalue a.=0 say a.z say 'NOVALUE is not raised.' exit novalue: say 'NOVALUE is raised.' - 语法
- 如果程序运行时检测到任何语言处理错误,则会产生一个语法条件。 这包括各种处理错误,包括真正的语法错误和运行时错误,例如尝试对非数字项进行算术运算。 您只能对 SIGNAL ON 指定此条件。
当条件未被捕获时,会采取什么措施
当条件陷阱当前处于禁用状态(OFF)且指定条件发生时,默认操作取决于条件。
- 对于HALT和SYNTAX,程序处理结束,一条描述事件性质的消息(参见错误编号和消息 )通常会指示出现的情况。
- 对于所有其他条件,条件将被忽略,其状态保持为“关闭”。
当条件被卡住时,会采取什么措施
当条件陷阱当前启用(ON)且指定条件发生时,系统将自动处理 CALL trapname 或 SIGNAL trapname指令 ,而不是通常的控制流程。
您可以在CALL ON或SIGNAL ON指令的NAME子关键字后指定陷阱名称。 如果您没有指定陷阱名称 ,则使用条件本身的名称(ERROR、FAILURE、HALT、NOTREADY、NOVALUE或SYNTAX)。
例如,指令 call on error 为ERROR条件设置了条件陷阱。 如果出现这种情况,则会调用名为ERROR的例程。 指令 call on error name commanderror 将启用陷阱,并在条件满足时调用程序COMMANDERROR。
- SIGNAL行动
- 如果所采取的行动是一个信号,则当前指令的执行立即停止,条件被禁用(设置为关闭),并且信号以与往常完全相同的方式发生(参见信号 )。
如果需要捕获任何新出现的条件,则需要在到达标签时为该条件重新启用新的CALL ON或SIGNAL ON指令。 例如,如果当出现语法条件时启用语法信号,则如果找不到语法信号标签名称,就会发生常规的语法错误终止。
- CALL行动
如果采取的行动是CALL(只能在子句边界发生),则CALL将以常规方式进行,但CALL不会影响特殊变量RESULT。 如果常规应返回任何数据,则忽略返回的字符串。
因为这些条件(错误、失败和暂停)可能会在执行 INTERPRET 指令时出现,因此如果使用了 CALL ON,INTERPRET 的执行可能会中断,并在稍后恢复。
当条件被触发时,在发出CALL之前,条件陷阱被置于延迟状态。 这种状态一直持续到CALL的RETURN,或直到对条件发出明确的CALL(或SIGNAL)ON(或OFF)。 这种延迟状态可防止在例行程序开始时过早出现条件陷阱,从而避免处理条件陷阱。 当条件陷阱处于延迟状态时,它仍然处于启用状态,但如果条件再次出现,则要么忽略(对于错误、失败或未就绪),要么(对于其他条件)延迟任何操作(包括更新条件信息),直到发生以下事件之一:- 对于延迟情况,会处理呼叫或信号。 在这种情况下,新的CALL ON或SIGNAL ON指令处理完毕后,立即发出CALL或SIGNAL。
- 对于延迟情况,会处理取消呼叫或信号中断。 在这种情况下,条件陷阱被禁用,条件默认动作在CALL OFF或SIGNAL OFF指令结束时发生。
- 从子程序返回。 在这种情况下,条件陷阱不再延迟,子程序立即被再次调用。
从CALL返回时,将恢复执行的原始流程(即流程不受CALL影响)。
注:- 编写语法陷阱程序时,必须格外小心。 如有可能,请将例程放在程序的开始部分。 这是必要的,因为如果存在某些扫描错误,例如缺少结束注释,陷阱例程标签可能无法找到。 此外,陷阱程序不应包含任何可能导致扫描更多错误程序的语句。 例如,调用内置函数时,名称前后无需加引号。 如果内置函数名称为大写并包含在引号中,REXX将直接调用该函数,而不会搜索内部标签。
- 在任何情况下,一旦发现故障,都会立即上报。 如果“信号开启”捕获了条件,则当前指令将结束(如有必要)。 因此,事件发生的指令可能只被部分处理。 例如,如果在评估作业中的表达式时出现语法错误,则该作业将不予评分。 请注意,CALL for ERROR、FAILURE、HALT和NOTREADY陷阱仅可能发生在子句边界。 如果在 INTERPRET 指令执行过程中出现上述情况,INTERPRET 的执行可能会中断,稍后再恢复。 同样,其他指令(例如DO或SELECT)可能会在子句边界处被CALL临时中断。
- 每个条件陷阱的状态(ON、OFF或DELAY以及任何陷阱名称 )在进入子程序时保存,然后在RETURN时恢复。 这意味着可以在子例程中使用 CALL ON , CALL OFF , SIGNAL ON 和 SIGNAL OFF ,而不影响调用者设置的条件。 有关子程序调用期间保存的其他信息的详情,请参阅 CALL指令。
- 当外部程序被调用时,即使外部程序是REXX程序,状态陷阱也不会受到影响。 在进入任何REXX程序时,所有条件陷阱的初始设置均为关闭。
- 在交互式追踪过程中,用户输入会得到处理,但所有条件陷阱都暂时设置为关闭。 这可以防止任何意外的控制权转移,例如,当“SIGNAL ON NOVALUE”处于活动状态时,用户意外使用了未初始化的变量。 出于同样的原因,交互式跟踪期间的语法错误不会导致程序退出,而是被特殊捕获,并在给出消息后忽略。
- 系统界面可在程序开始执行前或程序结束后检测到某些执行错误。 语法信号无法检测这些错误。
请注意, 标签是由单个符号后跟冒号组成的子句。 任何数量的连续条款都可以作为标签;因此,在另一种类型的条款之前允许使用多个标签。
记录的条件信息
当任何条件被捕捉并导致信号或呼叫时,该条件将成为当前被捕捉的条件,并且记录与其相关的某些条件信息。
您可以使用内置功能“状态”(见 “状态” )来检查这些信息。
- 当前被困状态的名字
- 条件陷阱(CALL或SIGNAL)处理后的指令名称
- 被困状态
- 与该条件相关的任何描述性字符串。
当条件陷阱(CALL ON或SIGNAL ON)导致控制权传递给标签时,当前状态信息将被替换。 条件信息在子程序或函数调用之间保存和恢复,包括一个因CALL ON陷阱而进行的调用。 因此,由CALL ON调用的例程可以访问相应的条件信息。 在常规退货后,之前的任何条件信息仍然可用。
描述性字符串
- 错误
- 处理后出现错误情况的字符串。
- FAILURE
- 经过处理后导致故障的字符串。
- 停止
- 任何与停止请求相关的字符串。 如果没有提供字符串,则该值为空字符串。
- 无值
- 尝试引用导致NOVALUE条件的变量的派生名称。 NOVALUE状态陷阱只能通过SIGNAL ON启用。
- 语法
- 与错误相关的任何字符串。 如果您没有提供特定的字符串,则该字段为空字符串。 请注意,特殊变量RC和SIGL提供了有关处理错误性质和位置的信息。 您只能通过启用信号灯来启用语法条件陷阱。
如何处理特殊变量
特殊变量是指在REXX程序处理过程中可以自动设置的变量。 有三个特殊变量:RC、RESULT和SIGL。 这些都没有初始值,但程序可以改变它们。 (关于RESULT的信息,请参阅 RETURN。)
- RC
对于错误和失败,REXX的特殊变量RC被设置为命令返回代码,然后才将控制权转移给条件标签。
对于语法错误,RC被设置为语法错误编号。
- SIGL
在因CALL或SIGNAL而发生任何控制转移后,导致控制转移的子句的程序行号将存储在特殊变量SIGL中。 如果控制转移是由于条件陷阱,则分配给SIGL的行号是CALL或SIGNAL发生之前(在当前子程序级别)处理的最后一个子句的行号。 当可以使用错误行的编号来控制文本编辑器时,这对于语法信号特别有用。 通常,遵循语法标签的代码会解析源代码以找到数据源,然后调用编辑器来编辑位于错误行处的源文件。 请注意,在这种情况下,您可能需要再次运行程序,编辑器中的任何更改才能生效。
此外,SIGL还可用于帮助确定错误原因(例如,偶尔出现的功能调用失败),如下例所示:signal on syntax a = a + 1 /* This is to create a syntax error */ say 'SYNTAX error not raised' exit /* Standard handler for SIGNAL ON SYNTAX */ syntax: say 'REXX error' rc 'in line' sigl':' "ERRORTEXT"(rc) say "SOURCELINE"(sigl) trace ?r; nop该代码首先显示错误代码、行号和错误信息。 然后,它会显示出错误的行,最后进入调试模式,让您检查错误行中使用的变量的值。
