Tcl命令catch的实现

Tcl程序在执行时实际上是在按照顺序执行一条条的Tcl命令。每条Tcl命令执行完毕后都会返回一个状态结果——下面4种状态中的一种:

  • 0 = TCL_OK # 正常结束
  • 1 = TCL_ERROR # 发生错误
  • 2 = TCL_RETURN # 过程返回
  • 3 = TCL_BREAK # 循环中断
  • 4 = TCL_CONTINUE # 循环继续

一般情况下,除了TCL_OK之外,其他状态都被认为是异常状态,会导致Tcl解释器报告错误并终止程序执行。

截获Tcl执行中的错误

在Tcl里,catch命令可以用于截获程序执行过程中发生的错误。比如下面的例子

set result $cache($key)    ;# 从缓存中获取结果
                           ;# 如果$key不存在,会报错,程序终止执行

这种情况下,可以借助catch命令,错误被捕获

set result ""
catch {
  set result $cache($key)
}

catch命令的实现

catch命令的实现其实很简单。就是永远return TCL_OK

其中一个细节通过 ((Interp *)interp)->cmdFramePtr改变命令执行的frame。

int
Tcl_CatchObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *CONST objv[])	/* Argument objects. */
{
    Tcl_Obj *varNamePtr = NULL;
    Tcl_Obj *optionVarNamePtr = NULL;
    int result;
    Interp *iPtr = (Interp *) interp;

    /*
     * TIP #280. Make invoking context available to caught script.
     */

    result = TclEvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);

    ... ...
    Tcl_ResetResult(interp);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
    return TCL_OK;
}