第一章 Caché 命令大全 BREAK 命令
在断点处中断执行。启用或禁用用户中断。
重点
BREAK的单点调试,指令SL的区别。CTRL-C的禁用用法。extend与flag参数不能一起用。- InterSystems建议使用
ZBREAK命令
大纲
BREAK:pc "extend"
B:pc "extend"
BREAK:pc flag
B:pc flag
参数
| 代码 | 描述 |
|---|---|
| pc | 可选-后置条件表达式。 |
| extend | 可选-指示要启用或禁用的断点类型的字母代码,以带引号的字符串形式指定。有效值列在中断扩展参数中。不能与flag参数一起使用。 |
| flag | 可选-指定中断行为的整数标志。标志值可以加引号,也可以不加引号。有效值为:0和4,用于禁用CTRL-C中断;1和5,用于启用CTRL-C中断。默认值由上下文确定。不能与extend参数一起使用。 |
描述
BREAK命令有三种形式:
- 不带参数的Break会中断当前位置的代码执行。
- Break Extension以定期断点间隔中断代码执行。
- BREAK flag 启用或禁用CTRL-C中断。
注意:旧版本的Caché ObjectScript只接受Break命令的缩写(B)。当前版本接受这两种形式中的任何一种。
所需权限
若要在运行代码时使用BREAK语句,必须将用户分配给为%Development资源提供U(使用)权限的角色(如%Developer或%Manager)。可以通过SQL GRANT语句或使用管理门户[主页]>[系统管理]>[用户]选项将用户分配给角色,以编辑用户的定义。
参数
pc
可选的后置条件表达式。如果后置条件表达式为TRUE(计算结果为非零数值),则Caché执行BREAK命令。如果后置条件表达式为假(计算结果为零),则Caché不执行该命令。
extend
Break Extension支持字母串代码来指定断点行为。双引号是必填项。
flag
中断标志支持四种不同的方式来处理CTRL-C中断:
BREARK 0:解除任何挂起但尚未发出信号的CTRL-C陷阱。禁用CTRL-C的未来信号。BREARK 1:取消任何挂起的CTRL-C陷阱。启用CTRL-C的未来信令。这意味着在执行Break 1之后键入CTRL-C会导致CTRL-C信号。BREARK 4:不取消任何挂起的CTRL-C陷阱。禁用CTRL-C的未来信号。这意味着当将来的中断1或中断5命令启用CTRL-C时,将发出挂起CTRL-C陷阱的信号。BREARK 5:不清除任何挂起的CTRL-C陷阱。启用CTRL-C的未来信令。这意味着挂起的CTRL-C陷阱应该在中断5之后不久由Caché ObjectScript命令发出信号。大多数(但不是所有Caché ObjectScript命令轮询CTRL-C。
无参Break
遇到 无参 Break时会中断代码执行可以在程序源代码中使用无参数中断,带或不带后置条件,以在该点中断程序执行并将控制返回给终端提示符。无参数中断用于调试目的。
如果在例程中包含无参数中断,则会设置断点,从而中断例程执行并将进程返回到终端提示符。通过在代码中嵌入断点,可以建立用于调试的特定上下文。每次执行到中断时,Caché都会暂停例程并返回到终端提示符。然后可以使用其他ObjectScript命令执行调试活动。例如,可以使用WRITE命令检查当前停止点处的变量值,使用SET命令为这些或其他变量提供新值。还可以调用例程行编辑器(XECUTE^%),它提供了修改例程的基本编辑功能。在以中断暂停例程执行后,可以使用无参数GOTO恢复正常执行。或者,通过将此位置指定为GOTO命令参数,可以在不同位置恢复执行。
注意:InterSystems建议使用ZBREAK命令调用Caché Debugger,而不是在代码中使用Break命令。调试器提供更广泛的调试功能。
可以使用%SYSTEM.Process类的BreakMode()方法为当前进程配置无参数中断行为。通过设置Config.Miscellous类中的BreakMode属性,可以在系统范围内配置无参数中断行为。
与所有无参数命令一样,必须在无参数分隔符和其后的同一行命令之间至少插入两个空格。
BREAK Extended 参数以设置常规断点
不必在要挂起例程的每个位置放置无参数中断命令。Break有一系列“扩展”参数(EXTEND),它们可以周期性地挂起例程,就像在整个代码中散布无参数中断一样。
下表列出了BREAK命令扩展参数。
| 代码 | 描述 |
|---|---|
"S" |
使用Break “S”(单步)一次单步执行代码中的一个命令(生成的令牌)。并不是所有的ObjectScript命令都会生成一个令牌;有些命令会生成多个令牌,因此会被解析为多个步骤(见下文)。Caché停止中断由DO命令或XECUTE命令调用的命令,或在FOR循环或用户定义函数内中断,并在命令或循环完成时使用下一个令牌继续。逐步,不进方法,不进入循环。 |
"S+" |
Break “S+”的作用与Break“S”相似,不同之处在于Caché包括DO命令或XECUTE命令调用的命令上的中断,或者在for循环或用户定义函数内的中断。逐渐过程,进循环。 |
"S-" |
使用BREAK “S-”在当前级别禁用中断步进(“S”或“L”),并在上一级别启用单步进。作用类似于在当前级别中断“C”和在上一级别中断“S”。中断,逐步,逐过程。 |
"L" |
使用Break “L”(行步进)单步执行代码,每次单步执行一个例程行,在每行开始处中断。不生成令牌的行将被忽略(见下文)。Caché停止中断由DO命令或XECUTE命令调用的命令,或在FOR循环或用户定义函数内中断,并在命令或循环完成时从下一行继续。逐步,不进方法,不进入循环。 |
"L+" |
Break “L+”的作用类似于Break“L”,不同之处在于,在DO命令或XECUTE命令调用的命令上,或者在for循环或用户定义函数内,Caché还会在每个例程行的开头继续中断。逐渐过程,进循环。 |
"L-" |
使用BREAK“L-”在当前级别禁用中断步进(“S”或“L”),并在上一级别启用行步进。类似于在当前级别中断“C”和在上一级别中断“L”。中断,逐步,逐过程。 |
"C" |
使用BREAK “C”(清除BREAK)在当前级别停止所有中断步进(“L”和“S”)。如果中断状态在上一例程级别生效,则在作业执行退出后,中断在该例程级别恢复。 |
"C-" |
使用BREAK “C-”停止当前级别和所有以前级别的所有中断步进(“L”和“S”)。这允许在所有级别移除单步执行,而不会影响其他调试功能。 |
"OFF" |
BREAK "OFF"删除已为进程建立的所有调试。它删除所有断点和观察点,并关闭所有程序堆栈级别的单步执行。它还会删除与调试和跟踪设备的关联,但不会关闭它们。 |
在生成标记的语句上BREAK “S” 和BREAK “L” 。并非所有ObjectScript命令或行都会生成令牌。例如,BREAK “S” 和BREAK “L”都忽略标签行、注释和Try语句。BREAK “S”在CATCH语句处中断(如果输入了CATCH块);中断“L”不会。
BREAK “S” 和BREAK “L”之间的一个不同之处在于,许多命令行生成一个以上的标记,因此由一个以上的步骤组成。例如,下面都是一行(和一个ObjectScript命令),但Break“S”将每个步骤解析为两个步骤: SET x=1,y=2, KILL x,y, WRITE “hello”,!, IF x=1,y=2.
BREAK “S”比BREAK “L” 更加细致。
要在断点之后恢复代码执行,请在终端提示符下发出GOTO命令。
发出 BREAK "OFF"命令相当于发出以下一系列命令:
ZBREAK /CLEAR
ZBREAK /TRACE:OFF
ZBREAK /DEBUG:""
ZBREAK /ERRORTRAP:ON
BREAK "C-"
启用或禁用中断的中断标志
使用中断标志控制用户中断(如CTRL-C)是启用还是禁用。这些禁用/启用选项之间的实际区别如下:
BREAK 0和BREAK 1可用于创建代码块,其中CTRL-C信号不能中断关键命令序列。然而,交互式用户可能很难使用CTRL-C中断此类块上的循环。这是因为在检测CTRL-C陷阱和轮询CTRL-C信号之间存在轻微延迟。此延迟可允许下一个Break命令循环解除CTRL-C用户中断。
包含BREAK 4和BREAK 5的程序块可用于创建代码,其中CTRL-C信号不能中断关键的命令序列,而不影响交互式用户使用CTRL-C中断该块上的循环操作的能力。
Break的默认标志行为取决于登录模式,如下所示:
- 如果在终端提示符下登录,则默认为中断1。中断(如CTRL-C)始终处于启用状态。在
OPEN或USE命令中指定的B(/BREAK)协议无效。 - 如果在例程中,则默认值
为BREAK 0。中断(如CTRL-C)由OPEN或USE命令中指定的B(/BREAK)协议启用或禁用。
中断标志示例
以下示例使用$ZJOB确定是启用还是禁用中断:
/// d ##class(PHA.TEST.ObjectScript).TestBreak1()
ClassMethod TestBreak1()
{
BREAK 0
DO InterruptStatus
BREAK 1
DO InterruptStatus
WRITE "all done"
InterruptStatus()
IF $ZJOB\4#2=1 {WRITE "Interrupts enabled",!}
ELSE {WRITE "Interrupts disabled",!}
}
DHC-APP>d ##class(PHA.TEST.ObjectScript).TestBreak1()
Interrupts disabled
Interrupts enabled
all done
下面的示例使用for循环中的读取操作来输入一系列数字。它设置BREAK 0以禁用读取操作期间的用户中断。但是,如果用户输入的值不是数字,则中断1会启用用户中断,以便用户可以拒绝或接受他们刚刚输入的值:
/// d ##class(PHA.TEST.ObjectScript).TestBreak2()
ClassMethod TestBreak2()
{
SET y="^"
InputLoop
TRY {
FOR {
BREAK 0
READ "输入一个数字 ",x
IF x="" { WRITE !,"all done" QUIT }
ELSEIF 0=$ISVALIDNUM(x) {
BREAK 1
WRITE !,x," 不是一个数字 ",!
WRITE "你有4秒可以按 CTRL-C",!
WRITE "或接受这个值",!
HANG 4 }
ELSE { }
SET y=y_x_"^"
WRITE !,"数字数组是 ",y,!
}
}
CATCH { WRITE "拒绝错误输入",!
DO InputLoop
}
}
用户名:yx
密码:******
DHC-APP>d ##class(PHA.TEST.ObjectScript).TestBreak2()
输入一个数字 1
数字数组是 ^1^
输入一个数字 2
数字数组是 ^1^2^
输入一个数字 3
数字数组是 ^1^2^3^
输入一个数字 4
数字数组是 ^1^2^3^4^
输入一个数字 5
数字数组是 ^1^2^3^4^5^
输入一个数字 a
a 不是一个数字
你有4秒可以按 CTRL-C
或接受这个值
数字数组是 ^1^2^3^4^5^a^
输入一个数字 2
数字数组是 ^1^2^3^4^5^a^2^
输入一个数字
all done