NAME
nst_tcl_prog -- create unit to execute tcl script
PROTOTYPE
unitptr nst_tcl_prog( char *pcProg, unitptr uHost)
ARGUMENTS
- char *pcProg
- the tcl script
- unitptr uHost
- host unit
RETURN VALUE:
A pointer to the created unit or NULL in the case of an error.
SYNOPSIS:
Creates a unit that executes a Tcl-script whose source text is given
as a string pcProg. Many properties of the created unit are similar
to those of the NST prog_unit for C programs.
All globally declared variables will retain
their values between invocations of the nst_tcl_prog unit.
The start of the Tcl-script can be prefixed by a specification of
global Tcl variables that shall become visible as NST input or
output pins of the created unit. Additionally, it is possible
to declare a number of Tcl routines for external use. In this case,
the created unit will become a class container with one method subunit
for each declared routine (see below).
A #loadlib command allows to extend the set of predefined
functions with additional functions from shared libraries.
All Tcl and Tk commands are available, since the unit provides
just a convenient wrapper of Tcl/Tk. Additionally, there are
a few non-standard extension functions, such as exec_opnd,
adapt_opnd and exec_opnds to call NST units from the script.
INITIALIZATION OF CREATED UNIT:
For NST, the Tcl script is conceptually divided into an
initialization part that is only evaluated once at creation
of the NST unit, and an execution part that is evaluated at
each NST execution call.
The initialization
part consists of all commands up to (and including) the last
procedure definition. Any commands following the last procedure
definition are considered as execution part. If there is no
procedure defined, everything is considered as execution part
and the initialization part is empty.
Even if no procedure is needed, an empty dummy procedure
may be useful to separate a script into an initialization
and an execution part.
Beyond this, the unit has no NST init method (ie., does not
respond to the NST_INIT control call in any way.
EXECUTION OF CREATED UNIT:
If neither the initialization part nor the execution part
open any windows, the execution part is just executed in the
normal fashion, after which control returns to the NST level.
However, if one or more windows have been opened (mapped),
the execution part will be followed by an implicit start
of the Tcl event loop for managing the windows. This will
make execution stay within the created unit. Return to
the NST level can then be achieved in two ways:
1. pressing the Escape button while the cursor is in
one of the Tcl windows. 2. invoking the exit command
via suitable event bindings. While in standard Tcl exit
would terminate the process, here it just terminates
the execution of the nst_tcl_prog unit and gives #
control back to the NST level.
The basis for 1. is an implicit binding
bind all <Escape> { exit }
and the basis for 2. is a redefinition of exit made during
initialization. Both changes can be overwritten by the
Tcl code, if undesired.
ADAPTATION OF THE CREATED UNIT:
The adapt_unit call currently is without any effect.
CONTROL MODES:
Currently, there are no publicly useable control modes
defined.
NST INPUT AND OUTPUT FIELDS:
These are defined by some special non-Tcl directives that
must precede the Tcl code. The definition resembles the
syntax used for the prog unit and uses the special
keywords INP and OUT, optionally followed by a type
specifier (currently, one of float, scalar or string, with
string as the default if no type specifier is given)
followed by a comma-separated list of variable names.
Example:
INP float a(5); INP scalar u,v,w(4); OUT s,t[2];
will create a unit with three input fields: a
packed field of 5 float values for array variable a,
a scalar field of 2 float values for variables u and
v, and a further scalar field of 4 float values for
array variable w. Finally, there will be two output
fields for string s and string array t. The latter
will give rise to a field with two pins, each of type
string.
All variables declared in this way will become available
as global Tcl variables. Of course, even the float and
scalar variables will be strings in Tcl. However,
if non-numeric values are assigned to variables
that are associated with numeric pins, the pins will
be set to NaN.
Arrays variables (such as a,w and t) have elements
indexed from 0 on. Since Tcl arrays are associative,
additional elements may be introduced; these, however,
remain invisible in the NST interface.
ADDING CALLBACKS:
Typically, a Tcl/Tk program wants to invoke many different
actions in response to Gui events. Within a NST circuit,
some of these actions may be implemented as NST units.
These can be called from within the Tcl script by means
of the extension functions exec_opnd, adapt_opnd,
init_opnd and reset_opnd. Each of these functions
takes one or more argument parameters. For each parameter
that is a name, NST will look for a correspondingly named
unit to execute, adapt, init or reset (if the named unit is nested
within other named units, the name must specify the
whole path, e.g. box:foo ). For each argument that
is a number i, NST will invoke the corresponding
i-th successor unit (if the number is positive) or
the -i-th predecessor unit (if the number is negative)
of the nst_tcl_prog unit.
Example:
exec_opnd 1 2 box:foo
executes successor units 1 and 2 and box:foo.
There is an additional exec_opnds function (described
below) to invoke an interactively adjustable number
of successor units.
CLASS CONTAINERS AND METHOD SUBUNITS:
Each presence of a procedure name, followed by a colon,
within the initial interface definition part will
define a "method subunit" of corresponding name that
will be hosted inside the created tcl_prog unit (which
itself will then become a class container ).
The subsequent interface definitions, up to the next
occurrence of a "name:" (or the end of the declaration
part) will then specify the interface
of this method subunit and will not contribute to
the interface of the tcl_prog unit itself.
Example:
INP a; method1: method2: OUT e,f;
will define a class container with one input field
for a string variable a, a pinless class subunit
method1 and a second class subunit method2 with two
output fields for string variables e and f.
Whenever such definition is made, execution of the
created class subunit will result in a call of a
Tcl command of the same name, with no parameters.
Therefore, it is expected that after such definition
there follows Tcl code for corresponding Tcl
procedures (otherwise, calling the class subunits
will produce a runtime error).
Example:
proc method1 {} { puts "I have no inputs/outputs!" }
proc method2 {} { global e f
set e "result1"
set f "result2"
}
Note that we must access the interface via the
global variables defined in the header part. Note also
that the Tcl syntax admits no commas between the variables
after the global statement (but the INP and OUT
declarations expect their variables to be separated
by commas!).
PROG_UNIT AS AN OPERATOR UNIT:
The presence of a call to the parameterless function
exec_opnds makes the tcl_prog unit into an operator unit.
Each call of exec_opnds is translated into an exec call
for each of the tcl_prog unit's operands (the number of
operand units can be interactively adjusted in Neo,
or set with nst_operands_of() at the programming level).
If the exec_opnds call appears within the scope of
a function that belongs to a method subunit (i.e., a
function whose name is declared in the header that precedes
the tcl script), the operator status will instead
be given to the corresponding method subunit (or its
referencing use_method or use_named unit).
In particular for iterators implemented in this way,
there usually will be nested references to the same
method subunit. To avoid side-effects, it is recommendable
to use for the referencing use_method unit the
BY_REDIRECTION policy for transporting of output
values.
NAMED AREAS:
Named areas in Tcl windows can accommodate the graphics output
of other NST units, similarly as for the familiar input_window
unit. The following command creates a named area into which NST units
can draw:
named_area a=myarea width height
Here, named_area is the command name, .a=myarea specifies
with its part left of the '=' sign the path name
of the named area (in this example, ".a"; in general,
this must be a valid Tk widget path name), the part right to
the equality sign specifies a NST window name (here myarea).
Other NST units, such as plot_xy etc, can then draw into
the named area by specifying myarea as the window name
(this is the same mechanism as available with NST
input_windows, however, currently the Tcl unit offers
only color map named areas).
In the same way as for the input_window unit, additional
colons after the '=' select the type of the named area:
named_area a=:myarea width height; # for RGB
named_area .a=::myarea width height; # for RGB 3D
Named areas are the main bridge between Tcl windows and
the "old" NST graphics units.
NST WINDOW STYLE:
By specifying the directive #nststyle in the header preceding
the tcl script (the # must be the first char in the line)
the layout of the Tcl windows will use the coloring, font and
some other style elements of the familiar NST windows.
#nststyle evaluates a script held in the file nststyle.tcl.
This script introduces a few variables (all starting with
Nst ) into the name space.
LOAD AND SAVE:
Currently, no variable values are save or restored by a load.
The only saved and restored information are the geometry
(size and position) of all toplevel windows and their states.
REQUIRED TCL AND TK PATHS:
Everything should run fine without any special TCL and TK paths
set. If there are problems, one might set the following three
environment variables (the given paths are only examples to
show the proper syntax):
TCLLIBPATH=/usr/lib/tcl8.3:/usr/lib/tk8.3
TK_LIBRARY=/usr/lib/tk8.3
TCL_LIBRARY=/usr/lib/tcl8.3
EXTENDING THE SET OF BUILT-IN COMMANDS (SO FAR UNUSED!):
The set of predefined commands can be dynamically extended
with zero or more directives of the form
#loadlib "sharedLibName"
that must precede the program text. Each sharedLibName must specify
a shared object containing definitions of the to-be-added
commands (if no path is given, sharedLibName is searched in
LD_LIBRARY_PATH). Directives #verbose and #silent
can be used to activate/deactivate a listing of the loaded
command definitions.
A source file for adding three commands min, fun,
and quad_sum would have to contain the following
definitions:
char *TCL_COMMANDS[] = {"min","fun","quad_sum",(char*)0};
int min(ClientData pD, Tcl_Interp *pI,
int iArgc, char *pcArgv[]) { ... }
float fun(...) { ... }
float quad_sum(...) { ... }
Here, the identifier *TCL_COMMANDS[] is a fixed convention.
Each defined C-function must conform to the usual Tcl
C interface requirements. Currently, the ClientData
argument will be unused.
Avoiding Name Conflicts:
When extending the tcl_prog unit with shared libraries, it is important
to avoid name conflicts by loaded symbols, e.g., by choosing
some reasonably safe prefix string for each identifier.
To restrict the visibility of such prefixes to the C implementation
level (and to avoid having to use it also for the call names
of the functions within code processed by the tcl_prog unit itself)
include the prefix strings before the call names in the TCL_COMMANDS
list (in this list, any identifier that has a colon ':' at its
end will be interpreted as a prefix specifier (with the colon excluded)
for the following symbols).
This mechanism is the same as used for the prog_unit (cf. an
example there)
SEE ALSO:
prog_unit
FILE
/local/homes/rhaschke/nst7/man/../o.linx86//../foldersrc/nst_tcl_prog.c