tree1.tcl

Go to the documentation of this file.
00001 /*  tree.tcl --*/
00002 /* */
00003 /*  Implementation of a tree data structure for Tcl.*/
00004 /* */
00005 /*  Copyright (c) 1998-2000 by Ajuba Solutions.*/
00006 /* */
00007 /*  See the file "license.terms" for information on usage and redistribution*/
00008 /*  of this file, and for a DISCLAIMER OF ALL WARRANTIES.*/
00009 /* */
00010 /*  RCS: @(#) $Id: tree1.tcl,v 1.5 2005/10/04 17:15:05 andreas_kupries Exp $*/
00011 
00012 package require Tcl 8.2
00013 
00014 namespace ::struct {}
00015 
00016 namespace ::struct::tree {
00017     /*  Data storage in the tree module*/
00018     /*  -------------------------------*/
00019     /* */
00020     /*  There's a lot of bits to keep track of for each tree:*/
00021     /*  nodes*/
00022     /*  node values*/
00023     /*  node relationships*/
00024     /* */
00025     /*  It would quickly become unwieldy to try to keep these in arrays or lists*/
00026     /*  within the tree namespace itself.  Instead, each tree structure will get*/
00027     /*  its own namespace.  Each namespace contains:*/
00028     /*  children    array mapping nodes to their children list*/
00029     /*  parent      array mapping nodes to their parent node*/
00030     /*  node:$node  array mapping keys to values for the node $node*/
00031 
00032     /*  counter is used to give a unique name for unnamed trees*/
00033     variable counter 0
00034 
00035     /*  Only export one command, the one used to instantiate a new tree*/
00036     namespace export tree
00037 }
00038 
00039 /*  ::struct::tree::tree --*/
00040 /* */
00041 /*  Create a new tree with a given name; if no name is given, use*/
00042 /*  treeX, where X is a number.*/
00043 /* */
00044 /*  Arguments:*/
00045 /*  name    Optional name of the tree; if null or not given, generate one.*/
00046 /* */
00047 /*  Results:*/
00048 /*  name    Name of the tree created*/
00049 
00050 ret  ::struct::tree::tree (optional name ="") {
00051     variable counter
00052 
00053     if {[llength [info level 0]] == 1} {
00054     incr counter
00055     set name "tree${counter}"
00056     }
00057     # FIRST, qualify the name.
00058     if {![string match "::*" $name]} {
00059         # Get caller's namespace; append :: if not global namespace.
00060         set ns [uplevel 1 namespace current]
00061         if {"::" != $ns} {
00062             append ns "::"
00063         }
00064 
00065         set name "$ns$name"
00066     }
00067     if {[llength [info commands $name]]} {
00068     return -code error \
00069         "command \"$name\" already exists, unable to create tree"
00070     }
00071 
00072     # Set up the namespace for the object,
00073     # identical to the object command.
00074     namespace eval $name {
00075     # Set up root node's child list
00076     variable children
00077     set      children(root) [list]
00078 
00079     # Set root node's parent
00080     variable parent
00081     set      parent(root) [list]
00082 
00083     # Set up the node attribute mapping
00084     variable  attribute
00085     array set attribute {}
00086 
00087     # Set up a counter for use in creating unique node names
00088     variable nextUnusedNode
00089     set      nextUnusedNode 1
00090 
00091     # Set up a counter for use in creating node attribute arrays.
00092     variable nextAttr
00093     set      nextAttr 0
00094     }
00095 
00096     # Create the command to manipulate the tree
00097     interp alias {} ::$name {} ::struct::tree::TreeProc $name
00098 
00099     return $name
00100 }
00101 
00102 /* */
00103 /*  Private functions follow*/
00104 
00105 /*  ::struct::tree::TreeProc --*/
00106 /* */
00107 /*  Command that processes all tree object commands.*/
00108 /* */
00109 /*  Arguments:*/
00110 /*  name    Name of the tree object to manipulate.*/
00111 /*  cmd Subcommand to invoke.*/
00112 /*  args    Arguments for subcommand.*/
00113 /* */
00114 /*  Results:*/
00115 /*  Varies based on command to perform*/
00116 
00117 ret  ::struct::tree::TreeProc (type name , optional cmd ="" , type args) {
00118     # Do minimal args checks here
00119     if { [llength [info level 0]] == 2 } {
00120     return -code error "wrong # args: should be \"$name option ?arg arg ...?\""
00121     }
00122 
00123     # Split the args into command and args components
00124     set sub _$cmd
00125     if { [llength [info commands ::struct::tree::$sub]] == 0 } {
00126     set optlist [lsort [info commands ::struct::tree::_*]]
00127     set xlist {}
00128     foreach p $optlist {
00129         set p [namespace tail $p]
00130         lappend xlist [string range $p 1 end]
00131     }
00132     set optlist [linsert [join $xlist ", "] "end-1" "or"]
00133     return -code error \
00134         "bad option \"$cmd\": must be $optlist"
00135     }
00136     return [uplevel 1 [linsert $args 0 ::struct::tree::$sub $name]]
00137 }
00138 
00139 /*  ::struct::tree::_children --*/
00140 /* */
00141 /*  Return the child list for a given node of a tree.*/
00142 /* */
00143 /*  Arguments:*/
00144 /*  name    Name of the tree object.*/
00145 /*  node    Node to look up.*/
00146 /* */
00147 /*  Results:*/
00148 /*  children    List of children for the node.*/
00149 
00150 ret  ::struct::tree::_children (type name , type node) {
00151     if { ![_exists $name $node] } {
00152     return -code error "node \"$node\" does not exist in tree \"$name\""
00153     }
00154 
00155     variable ${name}::children
00156     return $children($node)
00157 }
00158 
00159 /*  ::struct::tree::_cut --*/
00160 /* */
00161 /*  Destroys the specified node of a tree, but not its children.*/
00162 /*  These children are made into children of the parent of the*/
00163 /*  destroyed node at the index of the destroyed node.*/
00164 /* */
00165 /*  Arguments:*/
00166 /*  name    Name of the tree object.*/
00167 /*  node    Node to look up and cut.*/
00168 /* */
00169 /*  Results:*/
00170 /*  None.*/
00171 
00172 ret  ::struct::tree::_cut (type name , type node) {
00173     if { [string equal $node "root"] } {
00174     # Can't delete the special root node
00175     return -code error "cannot cut root node"
00176     }
00177 
00178     if { ![_exists $name $node] } {
00179     return -code error "node \"$node\" does not exist in tree \"$name\""
00180     }
00181 
00182     variable ${name}::parent
00183     variable ${name}::children
00184 
00185     # Locate our parent, children and our location in the parent
00186     set parentNode $parent($node)
00187     set childNodes $children($node)
00188 
00189     set index [lsearch -exact $children($parentNode) $node]
00190 
00191     # Excise this node from the parent list,
00192     set newChildren [lreplace $children($parentNode) $index $index]
00193 
00194     # Put each of the children of $node into the parent's children list,
00195     # in the place of $node, and update the parent pointer of those nodes.
00196     foreach child $childNodes {
00197     set newChildren [linsert $newChildren $index $child]
00198     set parent($child) $parentNode
00199     incr index
00200     }
00201     set children($parentNode) $newChildren
00202 
00203     KillNode $name $node
00204     return
00205 }
00206 
00207 /*  ::struct::tree::_delete --*/
00208 /* */
00209 /*  Remove a node from a tree, including all of its values.  Recursively*/
00210 /*  removes the node's children.*/
00211 /* */
00212 /*  Arguments:*/
00213 /*  name    Name of the tree.*/
00214 /*  node    Node to delete.*/
00215 /* */
00216 /*  Results:*/
00217 /*  None.*/
00218 
00219 ret  ::struct::tree::_delete (type name , type node) {
00220     if { [string equal $node "root"] } {
00221     # Can't delete the special root node
00222     return -code error "cannot delete root node"
00223     }
00224     if { ![_exists $name $node] } {
00225     return -code error "node \"$node\" does not exist in tree \"$name\""
00226     }
00227 
00228     variable ${name}::children
00229     variable ${name}::parent
00230 
00231     # Remove this node from its parent's children list
00232     set parentNode $parent($node)
00233     set index [lsearch -exact $children($parentNode) $node]
00234     set children($parentNode) [lreplace $children($parentNode) $index $index]
00235 
00236     # Yes, we could use the stack structure implemented in ::struct::stack,
00237     # but it's slower than inlining it.  Since we don't need a sophisticated
00238     # stack, don't bother.
00239     set st [list]
00240     foreach child $children($node) {
00241     lappend st $child
00242     }
00243 
00244     KillNode $name $node
00245 
00246     while { [llength $st] > 0 } {
00247     set node [lindex   $st end]
00248     set st   [lreplace $st end end]
00249     foreach child $children($node) {
00250         lappend st $child
00251     }
00252 
00253     KillNode $name $node
00254     }
00255     return
00256 }
00257 
00258 /*  ::struct::tree::_depth --*/
00259 /* */
00260 /*  Return the depth (distance from the root node) of a given node.*/
00261 /* */
00262 /*  Arguments:*/
00263 /*  name    Name of the tree.*/
00264 /*  node    Node to find.*/
00265 /* */
00266 /*  Results:*/
00267 /*  depth   Number of steps from node to the root node.*/
00268 
00269 ret  ::struct::tree::_depth (type name , type node) {
00270     if { ![_exists $name $node] } {
00271     return -code error "node \"$node\" does not exist in tree \"$name\""
00272     }
00273     variable ${name}::parent
00274     set depth 0
00275     while { ![string equal $node "root"] } {
00276     incr depth
00277     set node $parent($node)
00278     }
00279     return $depth
00280 }
00281 
00282 /*  ::struct::tree::_destroy --*/
00283 /* */
00284 /*  Destroy a tree, including its associated command and data storage.*/
00285 /* */
00286 /*  Arguments:*/
00287 /*  name    Name of the tree to destroy.*/
00288 /* */
00289 /*  Results:*/
00290 /*  None.*/
00291 
00292 ret  ::struct::tree::_destroy (type name) {
00293     namespace delete $name
00294     interp alias {} ::$name {}
00295 }
00296 
00297 /*  ::struct::tree::_exists --*/
00298 /* */
00299 /*  Test for existance of a given node in a tree.*/
00300 /* */
00301 /*  Arguments:*/
00302 /*  name    Name of the tree to query.*/
00303 /*  node    Node to look for.*/
00304 /* */
00305 /*  Results:*/
00306 /*  1 if the node exists, 0 else.*/
00307 
00308 ret  ::struct::tree::_exists (type name , type node) {
00309     return [info exists ${name}::parent($node)]
00310 }
00311 
00312 /*  ::struct::tree::_get --*/
00313 /* */
00314 /*  Get a keyed value from a node in a tree.*/
00315 /* */
00316 /*  Arguments:*/
00317 /*  name    Name of the tree.*/
00318 /*  node    Node to query.*/
00319 /*  flag    Optional flag specifier; if present, must be "-key".*/
00320 /*  key Optional key to lookup; defaults to data.*/
00321 /* */
00322 /*  Results:*/
00323 /*  value   Value associated with the key given.*/
00324 
00325 ret  ::struct::tree::_get (type name , type node , optional flag =-key , optional key =data) {
00326     if {![_exists $name $node]} {
00327     return -code error "node \"$node\" does not exist in tree \"$name\""
00328     }
00329 
00330     variable ${name}::attribute
00331     if {![info exists attribute($node)]} {
00332     # No attribute data for this node,
00333     # except for the default key 'data'.
00334 
00335     if {[string equal $key data]} {
00336         return ""
00337     }
00338     return -code error "invalid key \"$key\" for node \"$node\""
00339     }
00340 
00341     upvar ${name}::$attribute($node) data
00342     if {![info exists data($key)]} {
00343     return -code error "invalid key \"$key\" for node \"$node\""
00344     }
00345     return $data($key)
00346 }
00347 
00348 /*  ::struct::tree::_getall --*/
00349 /* */
00350 /*  Get a serialized list of key/value pairs from a node in a tree.*/
00351 /* */
00352 /*  Arguments:*/
00353 /*  name    Name of the tree.*/
00354 /*  node    Node to query.*/
00355 /* */
00356 /*  Results:*/
00357 /*  value   A serialized list of key/value pairs.*/
00358 
00359 ret  ::struct::tree::_getall (type name , type node , type args) {
00360     if {![_exists $name $node]} {
00361     return -code error "node \"$node\" does not exist in tree \"$name\""
00362     }
00363     if {[llength $args]} {
00364     return -code error "wrong # args: should be \"$name getall $node\""
00365     }
00366 
00367     variable ${name}::attribute
00368     if {![info exists attribute($node)]} {
00369     # Only default key is present, invisibly.
00370     return {data {}}
00371     }
00372 
00373     upvar ${name}::$attribute($node) data
00374     return [array get data]
00375 }
00376 
00377 /*  ::struct::tree::_keys --*/
00378 /* */
00379 /*  Get a list of keys from a node in a tree.*/
00380 /* */
00381 /*  Arguments:*/
00382 /*  name    Name of the tree.*/
00383 /*  node    Node to query.*/
00384 /* */
00385 /*  Results:*/
00386 /*  value   A serialized list of key/value pairs.*/
00387 
00388 ret  ::struct::tree::_keys (type name , type node , type args) {
00389     if {![_exists $name $node]} {
00390     return -code error "node \"$node\" does not exist in tree \"$name\""
00391     }
00392     if {[llength $args]} {
00393     return -code error "wrong # args: should be \"$name keys $node\""
00394     }
00395 
00396     variable ${name}::attribute
00397     if {![info exists attribute($node)]} {
00398     # No attribute data for this node,
00399     # except for the default key 'data'.
00400     return {data}
00401     }
00402 
00403     upvar ${name}::$attribute($node) data
00404     return [array names data]
00405 }
00406 
00407 /*  ::struct::tree::_keyexists --*/
00408 /* */
00409 /*  Test for existance of a given key for a node in a tree.*/
00410 /* */
00411 /*  Arguments:*/
00412 /*  name    Name of the tree.*/
00413 /*  node    Node to query.*/
00414 /*  flag    Optional flag specifier; if present, must be "-key".*/
00415 /*  key Optional key to lookup; defaults to data.*/
00416 /* */
00417 /*  Results:*/
00418 /*  1 if the key exists, 0 else.*/
00419 
00420 ret  ::struct::tree::_keyexists (type name , type node , optional flag =-key , optional key =data) {
00421     if {![_exists $name $node]} {
00422     return -code error "node \"$node\" does not exist in tree \"$name\""
00423     }
00424     if {![string equal $flag "-key"]} {
00425     return -code error "invalid option \"$flag\": should be -key"
00426     }
00427 
00428     variable ${name}::attribute
00429     if {![info exists attribute($node)]} {
00430     # No attribute data for this node,
00431     # except for the default key 'data'.
00432 
00433     return [string equal $key data]
00434     }
00435 
00436     upvar ${name}::$attribute($node) data
00437     return [info exists data($key)]
00438 }
00439 
00440 /*  ::struct::tree::_index --*/
00441 /* */
00442 /*  Determine the index of node with in its parent's list of children.*/
00443 /* */
00444 /*  Arguments:*/
00445 /*  name    Name of the tree.*/
00446 /*  node    Node to look up.*/
00447 /* */
00448 /*  Results:*/
00449 /*  index   The index of the node in its parent*/
00450 
00451 ret  ::struct::tree::_index (type name , type node) {
00452     if { [string equal $node "root"] } {
00453     # The special root node has no parent, thus no index in it either.
00454     return -code error "cannot determine index of root node"
00455     }
00456 
00457     if { ![_exists $name $node] } {
00458     return -code error "node \"$node\" does not exist in tree \"$name\""
00459     }
00460 
00461     variable ${name}::children
00462     variable ${name}::parent
00463 
00464     # Locate the parent and ourself in its list of children
00465     set parentNode $parent($node)
00466 
00467     return [lsearch -exact $children($parentNode) $node]
00468 }
00469 
00470 /*  ::struct::tree::_insert --*/
00471 /* */
00472 /*  Add a node to a tree; if the node(s) specified already exist, they*/
00473 /*  will be moved to the given location.*/
00474 /* */
00475 /*  Arguments:*/
00476 /*  name        Name of the tree.*/
00477 /*  parentNode  Parent to add the node to.*/
00478 /*  index       Index at which to insert.*/
00479 /*  args        Node(s) to insert.  If none is given, the routine*/
00480 /*          will insert a single node with a unique name.*/
00481 /* */
00482 /*  Results:*/
00483 /*  nodes       List of nodes inserted.*/
00484 
00485 ret  ::struct::tree::_insert (type name , type parentNode , type index , type args) {
00486     if { [llength $args] == 0 } {
00487     # No node name was given; generate a unique one
00488     set args [list [GenerateUniqueNodeName $name]]
00489     }
00490     if { ![_exists $name $parentNode] } {
00491     return -code error "parent node \"$parentNode\" does not exist in tree \"$name\""
00492     }
00493 
00494     variable ${name}::parent
00495     variable ${name}::children
00496 
00497     # Make sure the index is numeric
00498     if { ![string is integer $index] } {
00499     # If the index is not numeric, make it numeric by lsearch'ing for
00500     # the value at index, then incrementing index (because "end" means
00501     # just past the end for inserts)
00502     set val [lindex $children($parentNode) $index]
00503     set index [expr {[lsearch -exact $children($parentNode) $val] + 1}]
00504     }
00505 
00506     foreach node $args {
00507     if {[_exists $name $node] } {
00508         # Move the node to its new home
00509         if { [string equal $node "root"] } {
00510         return -code error "cannot move root node"
00511         }
00512     
00513         # Cannot make a node its own descendant (I'm my own grandpaw...)
00514         set ancestor $parentNode
00515         while { ![string equal $ancestor "root"] } {
00516         if { [string equal $ancestor $node] } {
00517             return -code error "node \"$node\" cannot be its own descendant"
00518         }
00519         set ancestor $parent($ancestor)
00520         }
00521         # Remove this node from its parent's children list
00522         set oldParent $parent($node)
00523         set ind [lsearch -exact $children($oldParent) $node]
00524         set children($oldParent) [lreplace $children($oldParent) $ind $ind]
00525     
00526         # If the node is moving within its parent, and its old location
00527         # was before the new location, decrement the new location, so that
00528         # it gets put in the right spot
00529         if { [string equal $oldParent $parentNode] && $ind < $index } {
00530         incr index -1
00531         }
00532     } else {
00533         # Set up the new node
00534         set children($node) [list]
00535     }
00536 
00537     # Add this node to its parent's children list
00538     set children($parentNode) [linsert $children($parentNode) $index $node]
00539 
00540     # Update the parent pointer for this node
00541     set parent($node) $parentNode
00542     incr index
00543     }
00544 
00545     return $args
00546 }
00547 
00548 /*  ::struct::tree::_isleaf --*/
00549 /* */
00550 /*  Return whether the given node of a tree is a leaf or not.*/
00551 /* */
00552 /*  Arguments:*/
00553 /*  name    Name of the tree object.*/
00554 /*  node    Node to look up.*/
00555 /* */
00556 /*  Results:*/
00557 /*  isleaf  True if the node is a leaf; false otherwise.*/
00558 
00559 ret  ::struct::tree::_isleaf (type name , type node) {
00560     if { ![_exists $name $node] } {
00561     return -code error "node \"$node\" does not exist in tree \"$name\""
00562     }
00563 
00564     variable ${name}::children
00565     return [expr {[llength $children($node)] == 0}]
00566 }
00567 
00568 /*  ::struct::tree::_move --*/
00569 /* */
00570 /*  Move a node (and all its subnodes) from where ever it is to a new*/
00571 /*  location in the tree.*/
00572 /* */
00573 /*  Arguments:*/
00574 /*  name        Name of the tree*/
00575 /*  parentNode  Parent to add the node to.*/
00576 /*  index       Index at which to insert.*/
00577 /*  node        Node to move; the node must exist in the tree.*/
00578 /*  args        Additional nodes to move; these nodes must exist*/
00579 /*          in the tree.*/
00580 /* */
00581 /*  Results:*/
00582 /*  None.*/
00583 
00584 ret  ::struct::tree::_move (type name , type parentNode , type index , type node , type args) {
00585     set args [linsert $args 0 $node]
00586 
00587     # Can only move a node to a real location in the tree
00588     if { ![_exists $name $parentNode] } {
00589     return -code error "parent node \"$parentNode\" does not exist in tree \"$name\""
00590     }
00591 
00592     variable ${name}::parent
00593     variable ${name}::children
00594 
00595     # Make sure the index is numeric
00596     if { ![string is integer $index] } {
00597     # If the index is not numeric, make it numeric by lsearch'ing for
00598     # the value at index, then incrementing index (because "end" means
00599     # just past the end for inserts)
00600     set val [lindex $children($parentNode) $index]
00601     set index [expr {[lsearch -exact $children($parentNode) $val] + 1}]
00602     }
00603 
00604     # Validate all nodes to move before trying to move any.
00605     foreach node $args {
00606     if { [string equal $node "root"] } {
00607         return -code error "cannot move root node"
00608     }
00609 
00610     # Can only move real nodes
00611     if { ![_exists $name $node] } {
00612         return -code error "node \"$node\" does not exist in tree \"$name\""
00613     }
00614 
00615     # Cannot move a node to be a descendant of itself
00616     set ancestor $parentNode
00617     while { ![string equal $ancestor "root"] } {
00618         if { [string equal $ancestor $node] } {
00619         return -code error "node \"$node\" cannot be its own descendant"
00620         }
00621         set ancestor $parent($ancestor)
00622     }
00623     }
00624 
00625     # Remove all nodes from their current parent's children list
00626     foreach node $args {
00627     set oldParent $parent($node)
00628     set ind [lsearch -exact $children($oldParent) $node]
00629 
00630     set children($oldParent) [lreplace $children($oldParent) $ind $ind]
00631 
00632     # Update the nodes parent value
00633     set parent($node) $parentNode
00634     }
00635 
00636     # Add all nodes to their new parent's children list
00637     set children($parentNode) \
00638     [eval [list linsert $children($parentNode) $index] $args]
00639 
00640     return
00641 }
00642 
00643 /*  ::struct::tree::_next --*/
00644 /* */
00645 /*  Return the right sibling for a given node of a tree.*/
00646 /* */
00647 /*  Arguments:*/
00648 /*  name        Name of the tree object.*/
00649 /*  node        Node to retrieve right sibling for.*/
00650 /* */
00651 /*  Results:*/
00652 /*  sibling     The right sibling for the node, or null if node was*/
00653 /*          the rightmost child of its parent.*/
00654 
00655 ret  ::struct::tree::_next (type name , type node) {
00656     # The 'root' has no siblings.
00657     if { [string equal $node "root"] } {
00658     return {}
00659     }
00660 
00661     if { ![_exists $name $node] } {
00662     return -code error "node \"$node\" does not exist in tree \"$name\""
00663     }
00664 
00665     # Locate the parent and our place in its list of children.
00666     variable ${name}::parent
00667     variable ${name}::children
00668 
00669     set parentNode $parent($node)
00670     set  index [lsearch -exact $children($parentNode) $node]
00671 
00672     # Go to the node to the right and return its name.
00673     return [lindex $children($parentNode) [incr index]]
00674 }
00675 
00676 /*  ::struct::tree::_numchildren --*/
00677 /* */
00678 /*  Return the number of immediate children for a given node of a tree.*/
00679 /* */
00680 /*  Arguments:*/
00681 /*  name        Name of the tree object.*/
00682 /*  node        Node to look up.*/
00683 /* */
00684 /*  Results:*/
00685 /*  numchildren Number of immediate children for the node.*/
00686 
00687 ret  ::struct::tree::_numchildren (type name , type node) {
00688     if { ![_exists $name $node] } {
00689     return -code error "node \"$node\" does not exist in tree \"$name\""
00690     }
00691 
00692     variable ${name}::children
00693     return [llength $children($node)]
00694 }
00695 
00696 /*  ::struct::tree::_parent --*/
00697 /* */
00698 /*  Return the name of the parent node of a node in a tree.*/
00699 /* */
00700 /*  Arguments:*/
00701 /*  name    Name of the tree.*/
00702 /*  node    Node to look up.*/
00703 /* */
00704 /*  Results:*/
00705 /*  parent  Parent of node $node*/
00706 
00707 ret  ::struct::tree::_parent (type name , type node) {
00708     if { ![_exists $name $node] } {
00709     return -code error "node \"$node\" does not exist in tree \"$name\""
00710     }
00711     # FRINK: nocheck
00712     return [set ${name}::parent($node)]
00713 }
00714 
00715 /*  ::struct::tree::_previous --*/
00716 /* */
00717 /*  Return the left sibling for a given node of a tree.*/
00718 /* */
00719 /*  Arguments:*/
00720 /*  name        Name of the tree object.*/
00721 /*  node        Node to look up.*/
00722 /* */
00723 /*  Results:*/
00724 /*  sibling     The left sibling for the node, or null if node was*/
00725 /*          the leftmost child of its parent.*/
00726 
00727 ret  ::struct::tree::_previous (type name , type node) {
00728     # The 'root' has no siblings.
00729     if { [string equal $node "root"] } {
00730     return {}
00731     }
00732 
00733     if { ![_exists $name $node] } {
00734     return -code error "node \"$node\" does not exist in tree \"$name\""
00735     }
00736 
00737     # Locate the parent and our place in its list of children.
00738     variable ${name}::parent
00739     variable ${name}::children
00740 
00741     set parentNode $parent($node)
00742     set  index [lsearch -exact $children($parentNode) $node]
00743 
00744     # Go to the node to the right and return its name.
00745     return [lindex $children($parentNode) [incr index -1]]
00746 }
00747 
00748 /*  ::struct::tree::_serialize --*/
00749 /* */
00750 /*  Serialize a tree object (partially) into a transportable value.*/
00751 /* */
00752 /*  Arguments:*/
00753 /*  name    Name of the tree.*/
00754 /*  node    Root node of the serialized tree.*/
00755 /* */
00756 /*  Results:*/
00757 /*  A list structure describing the part of the tree which was serialized.*/
00758 
00759 ret  ::struct::tree::_serialize (type name , optional node =root) {
00760     if {![_exists $name $node]} {
00761     return -code error "node \"$node\" does not exist in tree \"$name\""
00762     }
00763     Serialize $name $node tree attr
00764     return [list $tree [array get attr]]
00765 }
00766 
00767 /*  ::struct::tree::_set --*/
00768 /* */
00769 /*  Set or get a value for a node in a tree.*/
00770 /* */
00771 /*  Arguments:*/
00772 /*  name    Name of the tree.*/
00773 /*  node    Node to modify or query.*/
00774 /*  args    Optional arguments specifying a key and a value.  Format is*/
00775 /*          ?-key key? ?value?*/
00776 /*      If no key is specified, the key "data" is used.*/
00777 /* */
00778 /*  Results:*/
00779 /*  val Value associated with the given key of the given node*/
00780 
00781 ret  ::struct::tree::_set (type name , type node , type args) {
00782     if {![_exists $name $node]} {
00783     return -code error "node \"$node\" does not exist in tree \"$name\""
00784     }
00785     if {[llength $args] > 3} {
00786     return -code error "wrong # args: should be \"$name set [list $node] ?-key key?\
00787         ?value?\""
00788     }
00789 
00790     # Process the arguments ...
00791 
00792     set key "data"
00793     set haveValue 0
00794     if {[llength $args] > 1} {
00795     foreach {flag key} $args break
00796     if {![string match "${flag}*" "-key"]} {
00797         return -code error "invalid option \"$flag\": should be key"
00798     }
00799     if {[llength $args] == 3} {
00800         set haveValue 1
00801         set value [lindex $args end]
00802     }
00803     } elseif {[llength $args] == 1} {
00804     set haveValue 1
00805     set value [lindex $args end]
00806     }
00807 
00808     if {$haveValue} {
00809     # Setting a value. This may have to create
00810     # the attribute array for this particular
00811     # node
00812 
00813     variable ${name}::attribute
00814     if {![info exists attribute($node)]} {
00815         # No attribute data for this node,
00816         # so create it as we need it.
00817         GenAttributeStorage $name $node
00818     }
00819     upvar ${name}::$attribute($node) data
00820 
00821     return [set data($key) $value]
00822     } else {
00823     # Getting a value
00824 
00825     return [_get $name $node -key $key]
00826     }
00827 }
00828 
00829 /*  ::struct::tree::_append --*/
00830 /* */
00831 /*  Append a value for a node in a tree.*/
00832 /* */
00833 /*  Arguments:*/
00834 /*  name    Name of the tree.*/
00835 /*  node    Node to modify or query.*/
00836 /*  args    Optional arguments specifying a key and a value.  Format is*/
00837 /*          ?-key key? ?value?*/
00838 /*      If no key is specified, the key "data" is used.*/
00839 /* */
00840 /*  Results:*/
00841 /*  val Value associated with the given key of the given node*/
00842 
00843 ret  ::struct::tree::_append (type name , type node , type args) {
00844     if {![_exists $name $node]} {
00845     return -code error "node \"$node\" does not exist in tree \"$name\""
00846     }
00847     if {
00848     ([llength $args] != 1) &&
00849     ([llength $args] != 3)
00850     } {
00851     return -code error "wrong # args: should be \"$name set [list $node] ?-key key?\
00852         value\""
00853     }
00854     if {[llength $args] == 3} {
00855     foreach {flag key} $args break
00856     if {![string equal $flag "-key"]} {
00857         return -code error "invalid option \"$flag\": should be -key"
00858     }
00859     } else {
00860     set key "data"
00861     }
00862 
00863     set value [lindex $args end]
00864 
00865     variable ${name}::attribute
00866     if {![info exists attribute($node)]} {
00867     # No attribute data for this node,
00868     # so create it as we need it.
00869     GenAttributeStorage $name $node
00870     }
00871     upvar ${name}::$attribute($node) data
00872 
00873     return [append data($key) $value]
00874 }
00875 
00876 /*  ::struct::tree::_lappend --*/
00877 /* */
00878 /*  lappend a value for a node in a tree.*/
00879 /* */
00880 /*  Arguments:*/
00881 /*  name    Name of the tree.*/
00882 /*  node    Node to modify or query.*/
00883 /*  args    Optional arguments specifying a key and a value.  Format is*/
00884 /*          ?-key key? ?value?*/
00885 /*      If no key is specified, the key "data" is used.*/
00886 /* */
00887 /*  Results:*/
00888 /*  val Value associated with the given key of the given node*/
00889 
00890 ret  ::struct::tree::_lappend (type name , type node , type args) {
00891     if {![_exists $name $node]} {
00892     return -code error "node \"$node\" does not exist in tree \"$name\""
00893     }
00894     if {
00895     ([llength $args] != 1) &&
00896     ([llength $args] != 3)
00897     } {
00898     return -code error "wrong # args: should be \"$name lappend [list $node] ?-key key?\
00899         value\""
00900     }
00901     if {[llength $args] == 3} {
00902     foreach {flag key} $args break
00903     if {![string equal $flag "-key"]} {
00904         return -code error "invalid option \"$flag\": should be -key"
00905     }
00906     } else {
00907     set key "data"
00908     }
00909 
00910     set value [lindex $args end]
00911 
00912     variable ${name}::attribute
00913     if {![info exists attribute($node)]} {
00914     # No attribute data for this node,
00915     # so create it as we need it.
00916     GenAttributeStorage $name $node
00917     }
00918     upvar ${name}::$attribute($node) data
00919 
00920     return [lappend data($key) $value]
00921 }
00922 
00923 /*  ::struct::tree::_size --*/
00924 /* */
00925 /*  Return the number of descendants of a given node.  The default node*/
00926 /*  is the special root node.*/
00927 /* */
00928 /*  Arguments:*/
00929 /*  name    Name of the tree.*/
00930 /*  node    Optional node to start counting from (default is root).*/
00931 /* */
00932 /*  Results:*/
00933 /*  size    Number of descendants of the node.*/
00934 
00935 ret  ::struct::tree::_size (type name , optional node =root) {
00936     if { ![_exists $name $node] } {
00937     return -code error "node \"$node\" does not exist in tree \"$name\""
00938     }
00939 
00940     # If the node is the root, we can do the cheap thing and just count the
00941     # number of nodes (excluding the root node) that we have in the tree with
00942     # array names
00943     if { [string equal $node "root"] } {
00944     set size [llength [array names ${name}::parent]]
00945     return [expr {$size - 1}]
00946     }
00947 
00948     # Otherwise we have to do it the hard way and do a full tree search
00949     variable ${name}::children
00950     set size 0
00951     set st [list ]
00952     foreach child $children($node) {
00953     lappend st $child
00954     }
00955     while { [llength $st] > 0 } {
00956     set node [lindex $st end]
00957     set st [lreplace $st end end]
00958     incr size
00959     foreach child $children($node) {
00960         lappend st $child
00961     }
00962     }
00963     return $size
00964 }
00965 
00966 /*  ::struct::tree::_splice --*/
00967 /* */
00968 /*  Add a node to a tree, making a range of children from the given*/
00969 /*  parent children of the new node.*/
00970 /* */
00971 /*  Arguments:*/
00972 /*  name        Name of the tree.*/
00973 /*  parentNode  Parent to add the node to.*/
00974 /*  from        Index at which to insert.*/
00975 /*  to      Optional end of the range of children to replace.*/
00976 /*          Defaults to 'end'.*/
00977 /*  node        Optional node name; if given, must be unique.  If not*/
00978 /*          given, a unique name will be generated.*/
00979 /* */
00980 /*  Results:*/
00981 /*  node        Name of the node added to the tree.*/
00982 
00983 ret  ::struct::tree::_splice (type name , type parentNode , type from , optional to =end , type args) {
00984     if { [llength $args] == 0 } {
00985     # No node name given; generate a unique node name
00986     set node [GenerateUniqueNodeName $name]
00987     } else {
00988     set node [lindex $args 0]
00989     }
00990 
00991     if { [_exists $name $node] } {
00992     return -code error "node \"$node\" already exists in tree \"$name\""
00993     }
00994 
00995     variable ${name}::children
00996     variable ${name}::parent
00997 
00998     # Save the list of children that are moving
00999     set moveChildren [lrange $children($parentNode) $from $to]
01000 
01001     # Remove those children from the parent
01002     set children($parentNode) [lreplace $children($parentNode) $from $to]
01003 
01004     # Add the new node
01005     _insert $name $parentNode $from $node
01006 
01007     # Move the children
01008     set children($node) $moveChildren
01009     foreach child $moveChildren {
01010     set parent($child) $node
01011     }
01012 
01013     return $node
01014 }
01015 
01016 /*  ::struct::tree::_swap --*/
01017 /* */
01018 /*  Swap two nodes in a tree.*/
01019 /* */
01020 /*  Arguments:*/
01021 /*  name    Name of the tree.*/
01022 /*  node1   First node to swap.*/
01023 /*  node2   Second node to swap.*/
01024 /* */
01025 /*  Results:*/
01026 /*  None.*/
01027 
01028 ret  ::struct::tree::_swap (type name , type node1 , type node2) {
01029     # Can't swap the magic root node
01030     if {[string equal $node1 "root"] || [string equal $node2 "root"]} {
01031     return -code error "cannot swap root node"
01032     }
01033 
01034     # Can only swap two real nodes
01035     if {![_exists $name $node1]} {
01036     return -code error "node \"$node1\" does not exist in tree \"$name\""
01037     }
01038     if {![_exists $name $node2]} {
01039     return -code error "node \"$node2\" does not exist in tree \"$name\""
01040     }
01041 
01042     # Can't swap a node with itself
01043     if {[string equal $node1 $node2]} {
01044     return -code error "cannot swap node \"$node1\" with itself"
01045     }
01046 
01047     # Swapping nodes means swapping their labels and values
01048     variable ${name}::children
01049     variable ${name}::parent
01050 
01051     set parent1 $parent($node1)
01052     set parent2 $parent($node2)
01053 
01054     # Replace node1 with node2 in node1's parent's children list, and
01055     # node2 with node1 in node2's parent's children list
01056     set i1 [lsearch -exact $children($parent1) $node1]
01057     set i2 [lsearch -exact $children($parent2) $node2]
01058 
01059     set children($parent1) [lreplace $children($parent1) $i1 $i1 $node2]
01060     set children($parent2) [lreplace $children($parent2) $i2 $i2 $node1]
01061 
01062     # Make node1 the parent of node2's children, and vis versa
01063     foreach child $children($node2) {
01064     set parent($child) $node1
01065     }
01066     foreach child $children($node1) {
01067     set parent($child) $node2
01068     }
01069 
01070     # Swap the children lists
01071     set children1 $children($node1)
01072     set children($node1) $children($node2)
01073     set children($node2) $children1
01074 
01075     if { [string equal $node1 $parent2] } {
01076     set parent($node1) $node2
01077     set parent($node2) $parent1
01078     } elseif { [string equal $node2 $parent1] } {
01079     set parent($node1) $parent2
01080     set parent($node2) $node1
01081     } else {
01082     set parent($node1) $parent2
01083     set parent($node2) $parent1
01084     }
01085 
01086     # Swap the values
01087     # More complicated now with the possibility that nodes do not have
01088     # attribute storage associated with them.
01089 
01090     variable ${name}::attribute
01091 
01092     if {
01093     [set ia [info exists attribute($node1)]] ||
01094     [set ib [info exists attribute($node2)]]
01095     } {
01096     # At least one of the nodes has attribute data. We simply swap
01097     # the references to the arrays containing them. No need to
01098     # copy the actual data around.
01099 
01100     if {$ia && $ib} {
01101         set tmp               $attribute($node1)
01102         set attribute($node1) $attribute($node2)
01103         set attribute($node2) $tmp
01104     } elseif {$ia} {
01105         set   attribute($node2) $attribute($node1)
01106         unset attribute($node1)
01107     } elseif {$ib} {
01108         set   attribute($node1) $attribute($node2)
01109         unset attribute($node2)
01110     } else {
01111         return -code error "Impossible condition."
01112     }
01113     } ; # else: No attribute storage => Nothing to do {}
01114 
01115     return
01116 }
01117 
01118 /*  ::struct::tree::_unset --*/
01119 /* */
01120 /*  Remove a keyed value from a node.*/
01121 /* */
01122 /*  Arguments:*/
01123 /*  name    Name of the tree.*/
01124 /*  node    Node to modify.*/
01125 /*  args    Optional additional args specifying which key to unset;*/
01126 /*      if given, must be of the form "-key key".  If not given,*/
01127 /*      the key "data" is unset.*/
01128 /* */
01129 /*  Results:*/
01130 /*  None.*/
01131 
01132 ret  ::struct::tree::_unset (type name , type node , optional flag =-key , optional key =data) {
01133     if {![_exists $name $node]} {
01134     return -code error "node \"$node\" does not exist in tree \"$name\""
01135     }
01136     if {![string match "${flag}*" "-key"]} {
01137     return -code error "invalid option \"$flag\": should be \"$name unset\
01138         [list $node] ?-key key?\""
01139     }
01140 
01141     variable ${name}::attribute
01142     if {![info exists attribute($node)]} {
01143     # No attribute data for this node,
01144     # except for the default key 'data'.
01145     GenAttributeStorage $name $node
01146     }
01147     upvar ${name}::$attribute($node) data
01148 
01149     catch {unset data($key)}
01150     return
01151 }
01152 
01153 /*  ::struct::tree::_walk --*/
01154 /* */
01155 /*  Walk a tree using a pre-order depth or breadth first*/
01156 /*  search. Pre-order DFS is the default.  At each node that is visited,*/
01157 /*  a command will be called with the name of the tree and the node.*/
01158 /* */
01159 /*  Arguments:*/
01160 /*  name    Name of the tree.*/
01161 /*  node    Node at which to start.*/
01162 /*  args    Optional additional arguments specifying the type and order of*/
01163 /*      the tree walk, and the command to execute at each node.*/
01164 /*      Format is*/
01165 /*          ?-type {bfs|dfs}? ?-order {pre|post|in|both}? -command cmd*/
01166 /* */
01167 /*  Results:*/
01168 /*  None.*/
01169 
01170 ret  ::struct::tree::_walk (type name , type node , type args) {
01171     set usage "$name walk $node ?-type {bfs|dfs}? ?-order {pre|post|in|both}? -command cmd"
01172 
01173     if {[llength $args] > 6 || [llength $args] < 2} {
01174     return -code error "wrong # args: should be \"$usage\""
01175     }
01176 
01177     if { ![_exists $name $node] } {
01178     return -code error "node \"$node\" does not exist in tree \"$name\""
01179     }
01180 
01181     # Set defaults
01182     set type dfs
01183     set order pre
01184     set cmd ""
01185 
01186     for {set i 0} {$i < [llength $args]} {incr i} {
01187     set flag [lindex $args $i]
01188     incr i
01189     if { $i >= [llength $args] } {
01190         return -code error "value for \"$flag\" missing: should be \"$usage\""
01191     }
01192     switch -glob -- $flag {
01193         "-type" {
01194         set type [string tolower [lindex $args $i]]
01195         }
01196         "-order" {
01197         set order [string tolower [lindex $args $i]]
01198         }
01199         "-command" {
01200         set cmd [lindex $args $i]
01201         }
01202         default {
01203         return -code error "unknown option \"$flag\": should be \"$usage\""
01204         }
01205     }
01206     }
01207 
01208     # Make sure we have a command to run, otherwise what's the point?
01209     if { [string equal $cmd ""] } {
01210     return -code error "no command specified: should be \"$usage\""
01211     }
01212 
01213     # Validate that the given type is good
01214     switch -exact -- $type {
01215     "dfs" - "bfs" {
01216         set type $type
01217     }
01218     default {
01219         return -code error "invalid search type \"$type\": should be dfs, or bfs"
01220     }
01221     }
01222 
01223     # Validate that the given order is good
01224     switch -exact -- $order {
01225     "pre" - "post" - "in" - "both" {
01226         set order $order
01227     }
01228     default {
01229         return -code error "invalid search order \"$order\":\
01230             should be pre, post, both, or in"
01231     }
01232     }
01233 
01234     if {[string equal $order "in"] && [string equal $type "bfs"]} {
01235     return -code error "unable to do a ${order}-order breadth first walk"
01236     }
01237 
01238     # Do the walk
01239     variable ${name}::children
01240     set st [list ]
01241     lappend st $node
01242 
01243     # Compute some flags for the possible places of command evaluation
01244     set leave [expr {[string equal $order post] || [string equal $order both]}]
01245     set enter [expr {[string equal $order pre]  || [string equal $order both]}]
01246     set touch [string equal $order in]
01247 
01248     if {$leave} {
01249     set lvlabel leave
01250     } elseif {$touch} {
01251     # in-order does not provide a sense
01252     # of nesting for the parent, hence
01253     # no enter/leave, just 'visit'.
01254     set lvlabel visit
01255     }
01256 
01257     if { [string equal $type "dfs"] } {
01258     # Depth-first walk, several orders of visiting nodes
01259     # (pre, post, both, in)
01260 
01261     array set visited {}
01262 
01263     while { [llength $st] > 0 } {
01264         set node [lindex $st end]
01265 
01266         if {[info exists visited($node)]} {
01267         # Second time we are looking at this 'node'.
01268         # Pop it, then evaluate the command (post, both, in).
01269 
01270         set st [lreplace $st end end]
01271 
01272         if {$leave || $touch} {
01273             # Evaluate the command at this node
01274             WalkCall $name $node $lvlabel $cmd
01275         }
01276         } else {
01277         # First visit of this 'node'.
01278         # Do *not* pop it from the stack so that we are able
01279         # to visit again after its children
01280 
01281         # Remember it.
01282         set visited($node) .
01283 
01284         if {$enter} {
01285             # Evaluate the command at this node (pre, both)
01286             WalkCall $name $node "enter" $cmd
01287         }
01288 
01289         # Add the children of this node to the stack.
01290         # The exact behaviour depends on the chosen
01291         # order. For pre, post, both-order we just
01292         # have to add them in reverse-order so that
01293         # they will be popped left-to-right. For in-order
01294         # we have rearrange the stack so that the parent
01295         # is revisited immediately after the first child.
01296         # (but only if there is ore than one child,)
01297 
01298         set clist        $children($node)
01299         set len [llength $clist]
01300 
01301         if {$touch && ($len > 1)} {
01302             # Pop node from stack, insert into list of children
01303             set st    [lreplace $st end end]
01304             set clist [linsert $clist 1 $node]
01305             incr len
01306         }
01307 
01308         for {set i [expr {$len - 1}]} {$i >= 0} {incr i -1} {
01309             lappend st [lindex $clist $i]
01310         }
01311         }
01312     }
01313     } else {
01314     # Breadth first walk (pre, post, both)
01315     # No in-order possible. Already captured.
01316 
01317     if {$leave} {
01318         set backward $st
01319     }
01320 
01321     while { [llength $st] > 0 } {
01322         set node [lindex   $st 0]
01323         set st   [lreplace $st 0 0]
01324 
01325         if {$enter} {
01326         # Evaluate the command at this node
01327         WalkCall $name $node "enter" $cmd
01328         }
01329 
01330         # Add this node's children
01331         # And create a mirrored version in case of post/both order.
01332 
01333         foreach child $children($node) {
01334         lappend st $child
01335         if {$leave} {
01336             set backward [linsert $backward 0 $child]
01337         }
01338         }
01339     }
01340 
01341     if {$leave} {
01342         foreach node $backward {
01343         # Evaluate the command at this node
01344         WalkCall $name $node "leave" $cmd
01345         }
01346     }
01347     }
01348     return
01349 }
01350 
01351 /*  ::struct::tree::WalkCall --*/
01352 /* */
01353 /*  Helper command to 'walk' handling the evaluation*/
01354 /*  of the user-specified command. Information about*/
01355 /*  the tree, node and current action are substituted*/
01356 /*  into the command before it evaluation.*/
01357 /* */
01358 /*  Arguments:*/
01359 /*  tree    Tree we are walking*/
01360 /*  node    Node we are at.*/
01361 /*  action  The current action.*/
01362 /*  cmd The command to call, already partially substituted.*/
01363 /* */
01364 /*  Results:*/
01365 /*  None.*/
01366 
01367 ret  ::struct::tree::WalkCall (type tree , type node , type action , type cmd) {
01368     set subs [list %n [list $node] %a [list $action] %t [list $tree] %% %]
01369     uplevel 2 [string map $subs $cmd]
01370     return
01371 }
01372 
01373 /*  ::struct::tree::GenerateUniqueNodeName --*/
01374 /* */
01375 /*  Generate a unique node name for the given tree.*/
01376 /* */
01377 /*  Arguments:*/
01378 /*  name    Name of the tree to generate a unique node name for.*/
01379 /* */
01380 /*  Results:*/
01381 /*  node    Name of a node guaranteed to not exist in the tree.*/
01382 
01383 ret  ::struct::tree::GenerateUniqueNodeName (type name) {
01384     variable ${name}::nextUnusedNode
01385     while {[_exists $name "node${nextUnusedNode}"]} {
01386     incr nextUnusedNode
01387     }
01388     return "node${nextUnusedNode}"
01389 }
01390 
01391 /*  ::struct::tree::KillNode --*/
01392 /* */
01393 /*  Delete all data of a node.*/
01394 /* */
01395 /*  Arguments:*/
01396 /*  name    Name of the tree containing the node*/
01397 /*  node    Name of the node to delete.*/
01398 /* */
01399 /*  Results:*/
01400 /*  none*/
01401 
01402 ret  ::struct::tree::KillNode (type name , type node) {
01403     variable ${name}::parent
01404     variable ${name}::children
01405     variable ${name}::attribute
01406 
01407     # Remove all record of $node
01408     unset parent($node)
01409     unset children($node)
01410 
01411     if {[info exists attribute($node)]} {
01412     # FRINK: nocheck
01413     unset ${name}::$attribute($node)
01414     unset attribute($node)
01415     }
01416     return
01417 }
01418 
01419 /*  ::struct::tree::GenAttributeStorage --*/
01420 /* */
01421 /*  Create an array to store the attrributes of a node in.*/
01422 /* */
01423 /*  Arguments:*/
01424 /*  name    Name of the tree containing the node*/
01425 /*  node    Name of the node which got attributes.*/
01426 /* */
01427 /*  Results:*/
01428 /*  none*/
01429 
01430 ret  ::struct::tree::GenAttributeStorage (type name , type node) {
01431     variable ${name}::nextAttr
01432     variable ${name}::attribute
01433 
01434     set   attr "a[incr nextAttr]"
01435     set   attribute($node) $attr
01436     upvar ${name}::$attr data
01437     set   data(data) ""
01438     return
01439 }
01440 
01441 /*  ::struct::tree::Serialize --*/
01442 /* */
01443 /*  Serialize a tree object (partially) into a transportable value.*/
01444 /* */
01445 /*  Arguments:*/
01446 /*  name    Name of the tree.*/
01447 /*  node    Root node of the serialized tree.*/
01448 /* */
01449 /*  Results:*/
01450 /*  None*/
01451 
01452 ret  ::struct::tree::Serialize (type name , type node , type tvar , type avar) {
01453     upvar 1 $tvar tree $avar attr
01454 
01455     variable ${name}::children
01456     variable ${name}::attribute
01457 
01458     # Store attribute data
01459     if {[info exists attribute($node)]} {
01460     set attr($node) [array get ${name}::$attribute($node)]
01461     } else {
01462     set attr($node) {}
01463     }
01464 
01465     # Build tree structure as nested list.
01466 
01467     set subtrees [list]
01468     foreach c $children($node) {
01469     Serialize $name $c sub attr
01470     lappend subtrees $sub
01471     }
01472 
01473     set tree [list $node $subtrees]
01474     return
01475 }
01476 
01477 /*  ### ### ### ######### ######### #########*/
01478 /*  Ready*/
01479 
01480 namespace ::struct {
01481     /*  Get 'tree::tree' into the general structure namespace.*/
01482     namespace import -force tree::tree
01483     namespace export tree
01484 }
01485 package provide struct::tree 1.2.2
01486 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1