我有这样的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
}
答案 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"