Version 9 of Dumping interpreter state

Updated 2002-10-31 11:52:47

Richard Suchenwirth 2002-10-30 - A wish that comes up every now and then (see Persistent Tcl and Tk applications) is to dump the state of an interpreter to a file, so it can later be restored (by sourceing the resulting file) with the same settings. Here's a simple first shot that "serializes" global variables (scalar or array), interpreter aliases, and procedures, taking care to skip env and Tcl internals. Feel free to improve on this ;-)

As mentioned on comp.lang.tcl, this is not a complete state dump; just a reasonable facimile. Things like open file descriptors, sockets, etc. are particularly difficult to handle, as are various extension specific items.

Richard, what about namespaces and package requires? - RS: Packages are sort of taken care of in the revised code below; namespaces would require traversal of the namespace tree, repeating variable and proc dumping.

AK: Note that tkcon contains dump routines as well, for namespaces too. - RS: Sure - it's just the little mental challenge of building something "with your bare hands"... more fun for a short break than reading yet more documentation or source code ;-)


 proc interp'dump {} {
     set res "\# interpreter status dump\n"
     catch {package require "a non-existing one"}
     foreach package [lsort [package names]] {
         if {![catch {package present $package} version]} {
             append res "package require $package $version" \n
         }
     }
     foreach i [lsort [info globals]] {
         if {$i == "env"} continue  ;# don't dump environment..
         if {[string match tcl_* $i]} continue ;# ..or Tcl system vars
         if {[string match auto_index $i]} continue ;# ..or Tcl system vars
         if {[array exists ::$i]} {
             append res [list array set $i [array get ::$i]]\n
         } else {
             append res [list set $i [set ::$i]]\n
         }
     }
     foreach proc [lsort [info procs]] {
         if {[string match auto_* $proc] || $proc == "unknown"} {
             continue ;# prevents most of the init.tcl procs from dumping
         }
         if {[string match pkg_* $proc]} continue ;# ..or Tcl system vars
         if {[string match tcl* $proc]} continue ;# ..or Tcl system vars
         append res "proc [list $proc] {"
         set space ""
         foreach i [info args $proc] {
             if [info default $proc $i value] {
                 append res "$space{$i [list $value]}"
             } else {
                 append res "$space$i"
             }
             set space " "
         }
         append res "} {[info body $proc]}\n"
     }
     foreach alias [lsort [interp aliases {}]] {
         append res "interp alias {} $alias {} [interp alias {} $alias]\n"
     }
     set res
 }
 if {[file tail [info script]] == [file tail $argv0]} {
    # prepare some playing material
    set scalar hello
    array set arry {foo 1 bar 2 grill 3}
    proc foo {bar} {puts grill-$bar}
    interp alias {} print {} puts stdout
    puts [interp'dump]
 }

Arts and crafts of Tcl-Tk programming