实现 Tcl“atreturn”功能?

问题描述 投票:0回答:1

我正在使用基于 Tcl 的框架来构建包 (MacPorts),并且希望实现类似 atexit 的功能,在构建失败和框架中止的情况下,我可以打印一些信息。

一个简单的 atexit 机制就可以工作,带有一个回调,该回调打印我在构建之前设置的消息,并在所谓的

post-build
块中取消设置(仅在成功的情况下执行)。

除了我的代码在隐藏退出命令的安全解释器中运行,因此我无法重命名/覆盖它。

我想我只是重命名/覆盖

return
函数,改编来自 https://wiki.tcl-lang.org/page/AtExit+handlers 的“MS”代码:

 namespace eval AtReturn {
    variable atReturnScripts [list]

    proc atReturn script {
        variable atReturnScripts
        lappend atReturnScripts \
                [uplevel 1 [list namespace code $script]]
    }

    namespace export atReturn
 }

 rename return AtReturn::ReturnOrig
 proc return {{arg {}} {code 0} {args {}}} {
     variable AtReturn::atReturnScripts
     set n [llength $atReturnScripts]
     while {$n} {
        catch [lindex $atReturnScripts [incr n -1]]
     }
#      rename return {}
#      rename AtReturn::ReturnOrig return
#      namespace delete AtReturn
     if {${arg} eq "-code"} {
         AtReturn::ReturnOrig -code ${code} {*}${args}
     } elseif {${arg} ne {}} {
         AtReturn::ReturnOrig ${arg}
     } else {
         AtReturn::ReturnOrig ${code}
     }
 }

但由于某种原因,这让我陷入了无限递归。 (同上,当我使用原始代码恢复 stock

return
函数,然后调用该函数时)。

我是否忽略了某些事情或尝试了不可能的事情?

trace add execution return enter YourCleanupProc
这样的东西怎么样?

callback overriding tcl interpreter
1个回答
0
投票

有多种方法可以在退出过程时运行某些代码,所有方法都使用

trace
实现。有能力修改程序的结果是不正常的。

  1. trace add execution procName leave
    注册一个跟踪,可以查看结果是什么,但在作用域退出后运行。它的结果是在该过程的每个出口上运行(当然,直到显式取消注册)。
  2. trace add variable someUnusedLocalVarName unset
    注册清理范围时运行的跟踪。它允许您观察特定范围的退出,但需要在该范围的运行期间应用;在程序开始运行之前无法设置。

如果你想修改结果,你应该在一些包装命令中运行代码,可能是用

try
catch
构建的,这至少有点侵入性。 (不过,可以使用
uplevel
来让入侵量看起来更少。)

除了替换

exit

 命令(仅真正适用于进程的主解释器)之外,
Tcl 不会在解释器退出时暴露任何执行该操作的内容,即使是部分可靠的。原因是,如果解释器已开始被删除,则不再安全地在其中运行命令。 (C 中的退出处理程序通常不应该调用解释器。)如果安全解释器想要提供类似的东西,它需要其受信任的父级来处理它的回调,可能是通过在开始之前调用安全解释器正式删除流程。

覆盖

return
根本不保证有效。过程中成功或错误的退出路径都不一定使用它。

© www.soinside.com 2019 - 2024. All rights reserved.