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

/amnt/loge/users/nistaff02/nistaff/rhaschke/nst7/man/../o.linux//../foldersrc/nst_tcl_prog.c