Sed:在每个TCL过程的开头添加一行

时间:2013-11-30 07:25:34

标签: sed tcl

我有这样的TCL过程,&想要在proc开始后添加一行,puts“puts”进入myproc“”行

proc myproc { {filename "input.txt"}
{var1 "x"} 
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"
你能帮忙吗? &安培;它也应该有效     proc myproc2 {N val} {     把“输入myproc”     #comment line     为{set i 0}设置ret {} {$ i< $ N} {incr i} {lappend ret $ val}     返回$ ret     }

2 个答案:

答案 0 :(得分:3)

如果您只想获得代码的执行跟踪,例如调用堆栈转储等,那么您根本不需要修改源代码。您可以使用tcl本身为您完成。

Tcl没有保留关键字,根本没有。甚至不保留proc。因此,您可以重新定义它:

rename proc _proc

# Now proc no longer exists but we have _proc instead.
# Use it to redefine "proc":

_proc proc {name arguments body} {
    set body "puts \"entered $name\";$body"
    _proc $name $arguments $body
}

在运行任何自己的代码之前,只需执行此操作,您就会发现在每次调用时都会打印出每个proc。

这是很多tcl调试器和分析器的工作方式 - 使用tcl重新自定义。


从您的评论中看起来您似乎也在尝试打印每次调用时堆栈的深度。为此,您需要为每个proc定义添加更多代码。最直接的方式当然是这样的:

_proc proc {name arguments body} {
    set preamble"set dist2top \[info level\];puts \"\$dist2top entered $name\""
    set body "$preamble;$body"
    _proc $name $arguments $body
}

但正如您所看到的,在字符串中编写代码很快就会变得无法管理。您可以使用一些技巧来使其更易于管理。其中一个比较常见的是按行拆分$body并使用list命令来操作代码。它应该至少降低一个引用地狱的水平。我最喜欢的是使用类似于在MVC框架中编写html模板的模板技术。我通常会使用string map

_proc proc {name arguments body} {
    _proc $name $arguments [string map [list %NAME% $name %BODY% $body] {
        set dist2top [info level]
        puts "$dist2top entered: %NAME%"
        %BODY%
    }]
}

_proc定义中的最后一个参数只是一个字符串,但它看起来像一个代码块,使其更容易阅读。这种技术没有令人讨厌的引用地狱。

答案 1 :(得分:0)

使用awk你可以这样做:

awk '/^ *proc/ {$0 = $0 "\nputs \" entered myproc\""} 1' RS= proc-file.tcl

给出这个文件:

proc myproc { {filename "input.txt"}
{var1 "x"} 
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"