假设我已经定义了 proc f1 proc f2 和 proc f3。现在我想创建一个 TCL 解释器,将 proc f1 proc f2 和 proc f3 的代码源到该解释器中,并限制除 f1、f2 和 f3 之外的所有命令都在该解释器中。我怎么能这样做?
编辑:
如果在解释器中调用了除 f1、f2 和 f3 之外的命令,我创建了一条错误消息,并执行源自解释器的代码(假设在获得带有 f1、f2 和 f3 procs 的代码)应该停止。
假设我已经定义了 proc f1 proc f2 和 proc f3。现在我想创建一个 TCL 解释器,将 proc f1 proc f2 和 proc f3 的代码源到该解释器中,并限制除 f1、f2 和 f3 之外的所有命令都在该解释器中。我怎么能这样做?
编辑:
如果在解释器中调用了除 f1、f2 和 f3 之外的命令,我创建了一条错误消息,并执行源自解释器的代码(假设在获得带有 f1、f2 和 f3 procs 的代码)应该停止。
你不能完全做到这一点,但你可以做一些对于大多数目的来说足够相似的事情。
您应该做的是在解释器中正常创建命令 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
这是一个简单的解决方案:逐行读取输入。如果第一个标记是 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
}
}
这个解决方案有几个问题:
尽管存在这些缺点,但该解决方案实施起来非常简单。