[Marco Maggi] - This package provides the ability to create a set of variables and restrict access to them to a set of procedures. This is similar to the creation of an object or a namespace used to hold variables private for an object instance. The first argument of all the functions is "token": the name of a static variable (a "static variable" is a global or namespace variable). It must be a non-existent variable that will be initialised as an array. To compose a unique name for the token array we can use the procedure described in [Generating a unique name]. Now an overview of the procedures. [[task_constructor token pwd]] - Initialises a new task. "pwd" is the optional task working directory: if not given defaults to the return value of [[pwd]]. "pwd" is normalised with respect to the process working directory at the time of the call. Returns the empty string. [[task_destructor token]] - Deletes all the task specific data associated to the task identified by "token". The token array is not deallocated, it must be [[unset]] by the caller. Returns the empty string. [[task_global token varname ?varname ...?]] - Links task-specific global variables to the scope of the caller. This procedure behaves exactly like [[global]]: variables are not created, just linked to the current scope. Using the empty string as variable name will lead to undefined behaviour. Returns the empty string. [[task_globname token varname]] - Returns the real name of a task variable variable: this is the name of the static variable in which the task value is stored. This can be used, for example, in a call to [[vwait]]. [[task_cd token ?directory?]] - Changes the working directory for a task. The [[cd]] built-in command is not called: only an internal variable value is changed. "directory" is an optional directory name, if not given defaults to the task default working directory. "directory" is normalised with respect to the task working directory at the time of the call. Returns the empty string. [[task_pwd token]] - Returns the current task working directory pathname. ---- As simple usage example take a look at the following code: proc begin { task working_directory } { task_constructor $task task_global $task data set data 123 } proc routine { task args } { task_global $task data cd [task_pwd $task] ... set data ... ... } proc end { task } { task_global $task data # do something with "$data" task_destructor $task unset $task return } begin ::task routine ::task end ::task ---- The package code follows. ---- proc task_constructor { this {pwd {}} } { upvar $this token set pwd [expr {([string length $pwd])? \ [file_normalise [pwd] $pwd] : [pwd]}] array set token [list {} [list $pwd $pwd]] return } proc task_destructor { this } { upvar $this token foreach {n v} [array get token] { if { [string length $n] } { unset -nocomplain -- $v } } return } proc task_global { this varname args } { upvar $this token foreach varname [concat [list $varname] $args] { if { ! [info exists token($varname)] } { set token($varname) [unique_name] } uplevel [list upvar \#0 $token($varname) $varname] } return } proc task_globname { this varname } { upvar $this token if { [info exists token($varname)] } { return $token($varname) } else { return -code error [format "unknown task global \"%s\"" $varname] } } proc task_cd { this {directory {}} } { upvar $this token set directory [expr {([string length $directory])? \ $directory : [lindex $token() 0]}] lset token() 1 [file_normalise [lindex $token() 0] $directory] return } proc task_pwd { this } { upvar $this token return [lindex $token() 1] } proc file_normalise { directory pathname } { if { [string length $directory] == 0 } { return -code error -errorcode "LOGIC INVALID_ARGUMENT" \ "normalisation directory is null" } if { [string equal [file pathtype $directory] "relative"] } { return -code error -errorcode "LOGIC INVALID_ARGUMENT" \ [format "normalisation directory is relative \"%s\"" \ $directory] } if { [string length $pathname] == 0 } { return $directory } elseif { [string equal [file pathtype $pathname] "relative"] } { set pathname [file join $directory $pathname] } return [file normalize $pathname] } ---- [Category Design]