简单使用open、eval和proc。
open可用于打开、创建文件。
eval带一个或多个变元,可以由一个或多个命令组成,eval采用concat命令的风格连接所有变元,执行命令并且返回执行结果。
proc可以创建一个过程,以便在程序其他地方重复调用。
proc create_report { reportName command } {
set status "."
append status $reportName ".fail"
if { ![file exists $status] } {
eval open $status w+
}
set retval [eval catch { $command } msg]
if { $retval != 0 } {
puts $msg
set fp [open $status w]
close $fp
}
}
create_report "synth" "open .synth1.pass r"
以上程序中需要注意的是:
-
在TCL中,open函数的参数顺序是filename option,不能把w或w+放在filename前。
-
在set retval [eval catch { $command } msg]中,如果用[eval catch {open .synth1.pass r} msg]的写法,则会导致程序报错。
这是因为eval的作用是将多个变元组合起来,其中{open .synth1.pass r}会被看作是字符串,该字符串在被组合后是会去掉{}的。所以eval执行后就变成catch open .synth1.pass r msg。
catch的用法为:catch script ?resultVarName? ?optionsVarName?。script必须被catch识别为脚本,即script在被eval组合后必须是被""或{}包含的字符串。而catch open .synth1.pass r msg中,catch会将open识别为目标脚本,将.synth1.pass识别为optionsVarName,从语法上看catch显然有一个非法的msg参数,所以会报错。
正确做法是:{{open .synth1.pass r}}、“{open .synth1.pass r}”、{“open .synth1.pass r”}、"\"open .synth1.pass r\"",这样保证即使是eval去掉了{}或“”,还有一对{}或“”,使catch能够正确识别目标脚本。
双引号之所以使用"\"open .synth1.pass r\""的写法,是因为双引号内的字符可以进行转义,同时TCL不允许双引号直接嵌套。需要使用转义符\表示内层“”是字符,而不是用来表示字符串的。