2012-05-08 13 views
5

Supongamos que he definido proc f1 proc f2 y proc f3. Ahora quiero crear un intérprete de TCL, obtener el código de proc f1 proc f2 y proc f3 en ese intérprete y restringir todos los comandos que no sean f1, f2 y f3 dentro de ese intérprete. ¿Como puedo hacer eso?Crear un intérprete TCL que solo admita comandos que suministre

EDIT:

Si un comando otra que la F1, F2 y F3 se llaman dentro del intérprete He creado un mensaje de error debe ser emitida y la ejecución del código de origen en el intérprete (suponiendo que este otro código que se origina en el mismo intérprete, después de obtener el código con los procesos f1, f2 y f3) debe detenerse.

Respuesta

9

No puede bastante hacer eso, pero puede hacer algo que sea lo suficientemente similar para la mayoría de los propósitos.

Lo que debe hacer es crear los comandos f1, f2 y f3 en un intérprete normalmente, luego crear un sub-intérprete que no tenga ningún comando Tcl y alias los comandos que desea exponer en ese sub-intérprete intérprete a los comandos en el padre.

# 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 
+2

También es posible que desee definir un comando 'desconocido' para que pueda manejar mejor los comandos no definidos, pero eso es opcional. –

+0

Muchas gracias. Creo que esto es lo que quería. – Narek

2

Aquí hay una solución simple: leer la entrada línea por línea. Si el primer contador es F1, F2, o F3, a continuación, ejecutar el comando, golpear control + C o escriba exit para salir del bucle:

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 
    } 
} 

Hay varios problemas con esta solución:

  1. Eval se considera peligroso
  2. No capacidad de edición tanto, es posible que desee obtener de fantasía y utilizar el paquete tclreadline

A pesar de estos inconvenientes, la solución es muy simple de implementar.

Cuestiones relacionadas