说我已经定义了proc f1 proc f2和proc f3。现在我想创建一个TCL解释器,将proc f1 proc f2和proc f3的代码输入到该解释器中,并限制除f1,f2和f3之外的所有命令都在该解释器中。我怎么能这样做?
编辑:
如果在解释器中调用了f1,f2和f3以外的命令,我已经创建了一个错误消息并且应该在解释器中执行代码(假设这个另一个代码来自同一个解释器,在使用f1,f2和f3 procs)获取代码之后应该停止。
答案 0 :(得分:9)
你不能完全这样做,但你可以做一些与大多数目的相似的事情。
你应该做的是通常在解释器中创建命令f1,f2和f3,然后创建一个根本没有Tcl命令的子解释器,并为你想要在该子解释器中公开的命令添加别名到父母的命令。
# First define f1-f3 in whatever way you want
# Now make the context; we'll use a safe interpreter for good measure...
set slave [interp create -safe]
# Scrub namespaces, then global vars, then commands
foreach ns [$slave eval namespace children ::] {
$slave eval namespace delete $ns
}
foreach v [$slave eval info vars] {
$slave eval unset $v
}
foreach cmd [$slave eval info commands] {
# Note: we're hiding, not completely removing
$slave hide $cmd
}
# Make the aliases for the things we want
foreach cmd {f1 f2 f3} {
$slave alias $cmd $cmd
}
# And evaluate the untrusted script in it
catch {$slave invokehidden source $theScript}
# Finally, kill the untrusted interpreter
interp delete $slave
答案 1 :(得分:2)
这是一个简单的解决方案:逐行读取输入。如果第一个标记是f1,f2或f3,则执行命令,按 Control + C 或键入exit
退出循环:
proc f1 {args} { puts "f1:$args" }
proc f2 {args} { puts "f2:$args" }
proc f3 {args} { puts "f3:$args" }
while 1 {
puts -nonewline ">"
flush stdout
gets stdin line
set firstToken [lindex $line 0]
if {[lsearch {f1 f2 f3 exit} $firstToken] != -1} {
eval $line
}
}
此解决方案存在一些问题:
尽管存在这些缺点,但解决方案实施起来非常简单。