TOC PREV NEXT INDEX

Put your logo here!


2 USER'S GUIDE

2.1 OVERVIEW

The Sequencer is intended as a general purpose tool, allowing both technical and scientific staff to ease the definition and execution of sequences of commands, intended to control the telescopes and instruments.

The Sequencer is based on Tcl/Tk. This is an embeddable interpreter, with a quite powerful core allowing a.o. control structures and arithmetic operations. Tcl/Tk was first released as free software in early 1990, and since then the number of its users has grown exponentially. The amount of good quality add-ons to Tcl/Tk available on the Internet is constantly growing, and several of the extensions find their way into the Tcl/Tk core every time a new version is released. The current Internet home site for Tcl/Tk is SourceForge (www.sourceforge.net/project/tcl). A good WWW starting point for more information about Tcl/Tk is the Tcl'ers WIKI (URL http://mini.net/cgi-bin/wikit/name). More references to Tcl/Tk information available via the Internet are given in section 2.8.

The Sequencer in its present version is just another of these extensions incorporated into the Tcl/Tk core. It adds a series of commands which give access to CCS facilities. Using these commands as basic building blocks, combining them together into procedures (scripts), one can easily add higher level commands. Compared with standard programming languages as C, small scripts are most of the time easier to write and debug, and the code is much more compact (hence maintainable). It is obvious that for many applications the Sequencer will be a handy prototyping tool. And even in some cases there may be no need to convert this Sequencer-language prototype to C-language, in particular whenever performance improvements are irrelevant.

The present release of the Sequencer contains 2 applications with this interpreter. These shells address mainly the needs of technically oriented people, and will not satisfy the generic public. The reason is quite simple: being an extension to Tcl/Tk, the Sequencer's syntax is the one inherited from Tcl/Tk; such syntax - as the syntax of any popular programming or shell language - will not be mastered or even appreciated by many observers. It simply does not allow to describe easily and intuitively the steps required to execute a sequence of observations.

The Sequencer needs therefore to be extended towards the higher level. There are a couple of directions which can offer solutions:

· The development of higher level commands; such procedures can hide to some extent the intricacies of the system and the scripting language - at least if these higher level commands do not allow lots of arguments and/or options.
· The use of tables; tables describing sequences of repeated actions are easy to construct on any hardware platform, very intuitive, and straightforward to interpret by an interpreter like the Sequencer. This can be considered a specific case of the previous point.
· The use of visual programming tools; this area looks quite promising. If carefully designed and implemented, it gives a means to "write" and execute sequences in a very intuitive way. This is being investigated right now.

Careful readers will have noticed that technically speaking the Sequencer is more than one application. First of all we have the interpreter-shells, able to interpret existing scripts, and secondly there is (or will be) a tool to assist in the creation of sequencer-scripts. Although in principle the tool can be used by anybody (provided there are different user levels), writing a script with an editor will in most cases outperform the script created with the tool.

The two shells that are part of the Sequencer module are called seqSh and seqWish. The latter includes the usual Tk widget commands, while the former does not have any Tk/windowing capabilities or commands and consequently does not require a DISPLAY environment variable. The name sequencer as application name is reserved for the tool described above.

With the integration of the Sequencer module into one of the latest Tcl cores, dynamic loading became available1. This means that extensions with extra functionality can be loaded during runtime, if they are built according to a certain scheme. There is no longer the need to create a monolithic interpreter containing all the extensions you may ever need: they can be loaded into memory as the need presents itself. Some of the functionality of the Sequencer is offered this way. A detailed explanation of this feature is given in section 2.6.

2.2 SCRIPTING LANGUAGE SYNTAX

The Tcl and Sequencer shells2 language have only a few basic rules. A complete description can be found in [1], chapter 2, and in [2]. This is summarized in the rest of this section, paying special attention to potential traps and pitfalls.

2.2.1 Basic rules

The Sequencer shells interpret commandlines. These commandlines can be given interactively, one by one, or they can be grouped together in a script. A script is a collection of one or more commandlines, often grouped together in a file. The basic syntax for all Sequencer shell commandlines is:

command arg1 arg2 arg3 ...

So each commandline consists of one or more words, whereby words are separated by spaces or blanks. The first word of a commandline is the command, which is either the name of a built-in command (programmed in C) or a Sequencer shell procedure (programmed in Tcl/Sequencer). The following words are the arguments passed to that command. Arguments are string-valued, i.e. they are always passed as strings to the command.

The commandline is terminated by a newline or a semicolon. All commandlines return a string as a result, which in some cases (depending on the command and its arguments) can be an empty string. This exposes one of the fundamentals of Tcl: everything is a string.

On top of this simple piece of syntax there are only the rules for substitution and quoting. These are the only mechanisms employed by the Tcl interpreter before it runs a command. After single pass substitution the arguments are, as said, passed as strings to the command, which has to interpret them. Features like control flow, procedures, and expressions are implemented as commands rather than grammar. They are not understood directly by the Tcl interpreter.

2.2.2 Substitution

The Tcl interpreter can perform 3 different types of substitution:

1. variable substitution: when a variable has been set previously, it can be de-referenced by using a $-sign in front of the variable name. The Tcl interpreter replaces in the commandline the occurrences of the $-sign followed by a variable name with the string-value of this variable. Example:
set myVar 53; expr $myVar*$myVar
will associate the string 53 with variable name myVar, and then calculate the square of the variable myVar. It is equivalent to
expr 53*53
2. command substitution: this allows to use the result of one commandline as an argument in another commandline. Command substitution is invoked by square brackets. Nesting is allowed.
Example:
set c [expr $myVar*$myVar]
makes the Tcl interpreter first evaluate everything inside the brackets, and that result (the string 2809) is used as the second argument for the set command.
3. backslash substitution: the backslash character has in fact two functions. It is an escape character for the previous substitutions and also allows to use various unprintable characters like newline in a commandline. Example:
set squareBrackets \[\]; set doubleQuote \"
set newLine \n

2.2.3 Quoting

In 2.2.1 we have seen that blanks are separators for Tcl words. This leads to a problem when a single argument is or should be a string containing blanks. We need something that allows to group words3 together. There are actually two ways to obtain that.

1. Double quotes. Blanks and even newlines within double quotes are part of the Tcl word. Substitutions as described in 2.2.2 still take place. Double quotes do not nest, as the opening and closing double quote are the same ASCII character.
Example:
set result "The square of $myVar is [expr $myVar*$myVar]"
puts stdout $result
will print the string The square of 53 is 2809 to stdout.
2. Curly braces. The only character that is special after an opening curly brace is a closing curly brace. All other characters, including blanks, newlines and double quotes have no special meaning and are part of the Tcl word. Substitutions are prevented within matching curly braces. Braces nest.
Example:
set result {The square of $myVar is [expr $myVar*$myVar]}
puts stdout $result
will print the string The square of $myVar is [expr $myVar*$myVar] to stdout.

2.2.4 Potential pitfalls

Although the rules for the Tcl syntax are simple and few, many people experience some difficulties with it in the beginning, mainly because the behaviour is different from what one is used to in another language. So take care about the following!

· The grouping of words by quoting is done before substitutions are performed. I.e. the values of variables or command-results do not affect grouping.
Example:
set a \[expr
set b \]
set c 50
puts stdout "The square of c is $a $c*$c $b"
will print the string The square of c is [expr 50*50 ]
· There is only a single round of substitutions before command invocation. I.e. the result of a substitution is not interpreted a second time.
Example:
set a 50
set b \$a
set c $b
will set c to the string $a, not to the string 50.
· A left curly brace can only be preceded by whitespace (word separator), another left brace (nesting) or opening square bracket (command substitution). Likewise, a right curly brace can only be followed by whitespace, another right brace or closing square bracket. The Tcl interpreter will trip over and complain about any other character.
· A double quote character can only be an opening quote for grouping if it is preceded by whitespace.
Example:
set tenInch 10"
is perfectly legal and will set tenInch to the string 10".
· Square brackets used for command substitution do not require spaces around them.
Example:
set a [expr 11*11][expr 12*12]
will set a to the string 121144. Remark that a space between the first closing and second opening bracket would produce a syntax error.
· For command substitution, newlines and semi-colons are significant as commandline terminators (contrary to quoting). Use the backslash substitution to escape such terminations.
Example:
set theNameOfThisVariableIsSoLongTheLineWillWrap [expr 12345*
6789]
will produce a syntax error. To avoid that, append a backslash to the end of the first line.
· Although e.g. the set command can manipulate arrays, the Tcl interpreter itself does not know any special data types. This means that in the case of arrays, the parsing of the round brackets is done by the command, not the Tcl interpreter.
· It is very important where you have opening braces for the arguments of all commands that can take scripts or lists as arguments (control flow commands, procedures,...). A construct like
if {$myVar != 1}
{
echo "unexpected value for myVar: $myVar"
}
will result in an error, as the if command needs two arguments, and the newline after the first argument terminates the commandline. This behaviour is due to the fact that control structures are depending on commands, and not grammar, like in C. So the above example will be correct if we write it as
if {$myVar != 1} {
echo "unexpected value for myVar: $myVar"
}
Remark that the space on the first line between the closing brace of the first argument and the opening brace of the second is essential.

2.3 SEQUENCER SHELL COMPONENTS

The Sequencer shells seqSh and seqWish are statically built on top of Tcl/Tk 8.3.3; seqWish, which includes Tk functionality, contains all of the following extensions4:

· [incr Tcl] version 3.2 - the extension that supports object oriented programming in Tcl/Tk. This also includes [incr Tk] version 3.2, which gives the framework to build megawidgets, and iwidgets 3.0.1, which is a set of megawidgets.
· TclX version 8.3 and TkX version 8.3 - the extended Tcl/Tk command set, adding a.o. several UNIX commands, file I/O commands and math commands
· BLT version 2.4u - the Bell Lab Toolkit; consists of about a dozen graphical commands, all in the blt:: namespace
· msqltcl version 1.99 - an extension that provides high-level access to a Mini SQL (mSQL) database server. Mini SQL (mSQL) is a freely available, lightweight database engine.
· Img version 1.2.4 - a package which enhances Tk, adding support for many other Image formats: BMP, XBM, XPM, GIF (with transparency), PNG, JPEG, TIFF and postscript.

seqSh on the other hand does not have X-capabilities by default, i.e. it contains only Tcl, [incr Tcl], TclX and msqltcl. However, dynamic loading permits to add Tk, TkX, [incr Tk], iwidgets, BLT and Img at runtime into seqSh.

These listed extensions are available as static packages, i.e. they are linked statically into the Sequencer shells, and are as such available from the very start-up of the Sequencer shells. There is nothing extra to be done to have access to the functionality offered by these extensions. Other extensions (like expect) can be loaded dynamically as the need arises. For a detailed explanation of these extensions please refer to their accompanying documentation and manpages. The rest of this section will concentrate on the specifics of the Sequencer shells.

All the Sequencer shell specific extensions to Tcl show up as commands with the prefix seq_. In as far as these extensions are atomic and have a clear mapping to a CCS function, the rest of the command name is the one of the corresponding CCS command, with the same case (e.g. seq_dbGetAttrInfo). For the other commands similar naming conventions are used. Both Sequencer shells (seqSh and seqWish) include an identical set of seq_ commands.

For all CCS functionality required in the Sequencer shells, atomic commands are made, attempting to map a single CCS function into a single Sequencer shell command. These basic commands can then be used to build more complex ones, i.e. Tcl/Sequencer procedures. From the user's perspective, there is no difference between procedures and C-coded commands, except perhaps for a slight performance penalty in the case of Tcl scripts.

In what follows the different Sequencer shell commands are grouped according to functionality, and are described shortly. More detailed explanation can be found in the references (chapter 4). Remark that there are currently no differences between full (RTAP-based) CCS and CCS-light: all commands and libraries available in the former are also available for the latter. On the other hand, if the Sequencer shells are built in an environment without CCS, the CCS-calls will obviously not be part of it. One notorious exception to this is for the error handling, where a CCS-like replacement for some err* calls exist and are being used in the Sequencer shells. In particular, seq_errResetStack, seq_errAdd and seq_errCloseStack exist also for a no-CCS environment.

2.3.1 CCS Environment Interface

· seq_ccsInit
Maps into ccsInit(3); to register the Sequencer shell with CCS as the process with an arbitrary name (<myProcName>). After this command has been issued, this process is known to CCS as <myProcName>, which is one of the parameters required to address this process via CCS (cf. msgSendCommand(3)).
· seq_ccsExit
To execute ccsExit(3), and reset internal linked lists containing information about commands with pending replies or about registered events.
· seq_ccsAsyncInput
This command does not have a counterpart in CCS; it enables or disables the acceptance of asynchronous CCS messages. If enabled, and when messages come in, they will be dispatched immediately using the services provided by seq_msgDispatch (see 2.3.2); otherwise they will be rejected returning an error to the originator.

2.3.2 CCS Message System Interface

· seq_msgSendCommand
Maps into msgSendCommand(3); to send a command to a certain destination identified by the parameters of the command. If successful, this command will return a command handle. This handle is internally linked to the relevant information of this command, permitting a proper identification and filtering of incoming replies. Part of this information is a unique integer number which is passed as the msgCMDID parameter in the msgSendCommand(3) call, and it is therefore imperative that the recipient processes of such commands return the original command identifier in their reply. When all replies on a certain command have been dealt with, the respective command handle is automatically deleted. Checking of the CDT of the receiving process can be enabled/disabled by means of the seq_ccsCmdCheck variable or by using the -(no)check option with the command.
· seq_msgRecvReply
Although without a direct one-to-one relationship with a CCS message system call, this command is similar to a msgRecvMsg(3) with a properly set filter. It allows to receive a single or all replies to a previously given command, which is identified by its handle (the cmdId returned by seq_msgSendCommand(n)).
An alternative way to retrieve and deal with incoming replies is provided by the event mechanism (see 2.3.7). This allows to attach a callback to a command handle, which will be executed in the background (at global level) whenever a reply comes in.
· seq_msgSendReply
Maps into msgSendReply(3); it is used to return a reply to a process which sent a SCRIPT command to the Sequencer shell (see seq_msgDispatch). Normally, the Sequencer shell will return an empty reply immediately after receiving the SCRIPT command, and a second, final reply after evaluating the script. This is done automatically. If intermediate replies are needed (e.g. in the VERBOSE mode), seq_msgSendReply has to be used, from within the evaluation of the script.
· seq_msgList
Does not have a corresponding CCS message system call. It lists the commands for which there are still replies pending. The information returned includes the cmdId, the name of the command, plus the environment and process it was sent to.
· seq_msgCheck
Does not have a corresponding CCS message system call. It is a boolean function, checking if there are still replies pending on a certain command. This may not always be obvious, as the number of replies on a command is many times not known in advance.
· seq_msgFlush
Does not have a corresponding CCS message system call. It flushes either the currently available replies, or waits for all pending replies from a certain environment/process.
· seq_msgDispatch, seq_msgDispatchBreak
When asynchronous messages/events are enabled, seq_msgDispatch will be executed automatically whenever a message is available on the queue. It will pull this message from the queue, and process it as required. The Sequencer shells can deal with all standard CCS message types, as shown below:
a. The most frequent/typical case is of course a reply (or error-reply) message. If it is of this type, the message will be copied over to dynamically allocated memory, until a request is made for this reply. If the message is a reply to a command to which a callback-script has been associated, this script will be executed.
b. The Sequencer shells can also receive a limited set of commands. If the message is the command SCRIPT, it will send an immediate acknowledge, evaluate the body of the command, and return a final reply with the result of the evaluation (if this result does not fit into a single reply, seq_msgDispatch will chop it up automatically into multiple replies). If the message is any other command (except of course the commands supported by CSS, like PING), it will send an error reply.
c. Similarly, if the message is a database event, the callback-script associated to it will be evaluated. If this evaluation causes problems, the event will be disabled, so errors do not pop up continuously.
d. Finally, if the message is of the obituary type, the script contained in the global Tcl variable seq_obiScript will be executed. Remark that any process interested in receiving obituaries needs to have an entry in RtapEnvTable, with the Care-about-Terminations field properly set; on the other hand, all processes doing a ccsInit/ccsExit will generate obituaries by default, ie. even when they are not listed in RtapEnvTable.

seq_msgDispatchBreak is a companion command, to break out from the waiting on the message queue when it is empty. The latter is never the case when seq_msgDispatch has been set up via seq_ccsAsyncInput.

Both these commands (seq_msgDispatch and seq_msgDispatchBreak) are normally not given directly by the user. seq_msgDispatch gets "automatically" invoked after a message of any type comes on the queue.

2.3.3 CCS On-line Database Interface

· seq_dbDirAddrToName
Convert a direct address into a symbolic address. Maps into dbDirAddrToName(3).
· seq_dbGetAlias
To retrieve the alias-name of a point. Maps into dbGetAlias(3).
· seq_dbGetAttrInfo
To retrieve the information on an attribute. Maps into dbGetAttrInfo(3).
· seq_dbGetAttrNames
To get the names of the attributes of a point. Maps into dbGetAttrNames(3).
· seq_dbGetFamilyNames
To retrieve the point names of parent and children of a point. Maps into dbGetFamilyNames(3).
· seq_dbGetFieldNames
To get the field names of a table attribute. Maps into dbGetFieldNames(3).
· seq_dbGetDirAddr
To convert a symbolic address into a direct one. Maps into dbGetDirAddr(3). The direct address returned can e.g. be used to write into an OLDB table containing sampling/plotting configuration information. At present only the seq_dbDirAddrToName command can use this type of address as an argument.
· seq_dbReadSymbolic
To read the value of an attribute. Maps into dbReadSymbolic(3).
· seq_dbWriteSymbolic
To write a value to an attribute. Maps into dbWriteSymbolic(3).
· seq_dbListCreate, seq_dbListAdd, seq_dbListRemove, seq_dbListDestroy, seq_dbListExtract, seq_dbListPut, seq_dbListList
To manipulate multi-read/write lists. Most of these commands have a one-to-one mapping into a CCS equivalent.
· seq_dbMultiRead, seq_dbMultiWrite
The execution of the db multi-read/write operation. Equivalent to dbMultiRead(3) resp. dbMultiWrite(3).
· seq_dbGetCwp
To retrieve the pathname of the current working point. Maps into dbGetCwp(3).
· seq_dbSetCwp
To set the current working point to a pathname. Maps into dbSetCwp(3).
· seq_dbLockPoint
To lock a db point. Maps into dbLockPoint(3).
· seq_dbUnlockPoint
To unlock a db point. Maps into dbUnlockPoint(3).

Remark that seq_dbGetDirAddr, seq_dbDirAddrToName, seq_dbLockPoint and seq_dbUnlockPoint are only available in a full CCS environment (i.e. with RTAP).

2.3.4 CCS Logging System Interface

· seq_logData: logs a single message (up to 255 characters) on the local host.
· seq_logTclErrors
This command will send all output that normally goes to stderr also to the CCS error log. As this may produce quite some overhead (depending on the amount of output), its use should be limited to debugging purposes.
· seq_logFitsAction, seq_logFitsComment, seq_logFitsEvent, seq_logFitsParRecord, seq_logStringParRecord, seq_logIntParRecord, seq_logRealParRecord
To generate FITS ops-logs

A specific command to retrieve logs can be implemented using the Tcl/TclX file access commands and the CCS logging system filtering utilities.

2.3.5 CCS Error System Interface

· seq_errResetStack
To reset the error stack (used after successful recovery from error). Maps into errResetStack(3).
· seq_errAdd
To add an error to the error stack. Maps into errAdd(3).
· seq_errCloseStack
To log the and close the error stack (no error recovery possible). Maps into errCloseStack(3).
· seq_errDisplay
To display the current error stack in a separate window. Related to errDisplay(3).
· seq_errGetStackSize
To get the number of error frames currently occupying the error stack. Maps into errGetStackSize.
· seq_errGetFromStack
Returns a particular error frame from the stack, in the same format as seq_errPrint. Maps into errGetFromStack.
· seq_errLog
To reset the stack, add one error and close the stack. Does not have a CCS counterpart
· seq_errPrint
Returns all the elements of the error structure corresponding to the last CCS error on the stack at the time an errCloseStack command was given internally by the sequencer shell. The latter happens any time when a seq-command fails due to some CCS error. Does not have a CCS counterpart

2.3.6 CCS Scan System Interface

· seq_scanConfig <args>: to configure the scan system; this is a simple interface on top of the CCS scan system scanConfig utility, passing it the list of arguments as given in <args>.

2.3.7 CCS Event Handling

The CCS event handling is dealing exclusively with database events. The Sequencer shells extend this concept to replies on CCS messages which were sent before (see 2.3.2). The format of these commands is for the replies identical to the one for the database events. The distinction is internally made based on the type of handle which is passed as an argument of each of the commands described below. Hence it is clear that only the database event part has a CCS counterpart.

· seq_evtAttach
To attach to a database event, or to a reply event. See also evtAttach(3)
· seq_evtDetach
To detach from a database event, or from a reply event. See also evtDetach(3)
· seq_evtSingleDisable
To disable a database or reply event. See also evtSingleDisable(3)
· seq_evtSingleEnable
To enable a database or reply event. See also evtSingleEnable(3)
· seq_evtList
To list information related to database events. Has no CCS counterpart, and is not (yet) implemented for reply events.

2.3.8 Error handling

Errors occurring during the execution of commands which are Sequencer extensions to Tcl/Tk are by default logged automatically, using the standard CCS error system calls. E.g. if seq_msgSendCommand is used to send a command to an inactive application, seq_msgSendCommand will fail and the error stack will be logged automatically, identifying the Sequencer shell as topmost layer.

Similarly, if seq_msgSendCommand is used to send a command to a properly running application which replies with an error message on the execution of the command, the subsequent seq_msgRecvReply command will of course retrieve this error stack and log it without the need of additional instructions (done internally via an errCloseStack call). This default behaviour can be modified and more control over this error stack can be obtained by setting the global Tcl variables seq_errLogging and/or seq_errReplyMerging to appropriate values - see section 2.7 and the manpages of the seq_err* commands.

On top of this feature, and the CSS error system interface (see 2.3.5), there are two Sequencer shell commands which allow additional error manipulation and logging.

· seq_catch
To evaluate a command and return its completion status. This command is similar to the Tcl core command catch, except that eventual errors are logged to the CCS error system. This provides a tracing facility which anyhow has to be enabled very explicitly.
· seq_logTclErrors: See2.3.4

2.3.9 OSLX

· seq_oslxCmd
To give an interface to OSLX functionality. It is accessible at script level after giving the command package require SeqOslx.

The OSLX functionality is available as a dynamically loadable package (see 2.6). You need to issue the command package require SeqOslx to have this function available in any of the Sequencer shells. The SeqOslx package is also available under CCS-light.

2.3.10 Convenience procedures

The Sequencer shells include a number of convenience procedures, which have no CCS counterparts. They are

· seq_deleteHandle
will delete a handle plus related resources, where the handle can be either of the command, event, script or multi-read/write list type. Only for a (full or light) CCS environment.
· seq_relToAbsPath
will return the absolute pathname corresponding to a relative pathname
· seq_findFile
will return the absolute pathname of a file, after it has been searched for in ./, ../, $INTROOT/ and $VLTROOT (in that order).
· seq_waitTillActive
will wait until a certain process is active, i.e. until it can receive CCS messages. Only for a (full or light) CCS environment.
· seq_waitTillDead
will wait until a certain process is inactive. Only for a (full or light) CCS environment.
· seq_isoTime
returns the current UTC time in ISO 8601 format (i.e. as `yyyy-mm-ddThh:mm:ss').
· seq_fitsDate
returns the current UTC date in the format `yyyy-mm-dd'
· seq_timeOfDay
returns the current UTC time-of-the-day in the format `hh:mm:ss'.
· seq_isoTimeToClock
will convert a UTC time-string in ISO-format to the internal clock value (integer, timezone adjusted) corresponding to this UTC time.

2.3.11 Debugging help

The environment installed with the seq-module includes some debugging facilities of scripts written in the Sequencer language, at different levels:

· tclCheck
This is a contribution to the Tcl archive which allows to check the syntax of the script. It is a C program which can run a basic check on the syntax of a Tcl script. Very useful to detect mismatching curly braces, brackets, etc. Using this utility does not require any modification in your script
· seq_debug
The Sequencer shells contain a global Tcl variable, called seq_debug, which is an array with all debugable seq_* commands as elements. Assigning a particular element the value 1 (bit 0) will log the stack level, command-name plus arguments to stderr; setting bit 1 means the return-value will get printed; bit 2 stands for the timestamp, while bit 3 is for internal, command-specific debug info. If bit 1 is set, the return value is printed as "OK" or "ERR" followed by the return-string put in between greater-than and less-than signs, e.g. `OK >13. The default value of 0 means no debugging info gets printed.
To use this feature, some instructions have to be added to your scripts, modifying the default value of 0 for the particular command(s) you want to trace. This would typically be in an initialization procedure.
· seq_redirect
This command allows to redirect output sent to any file descriptor to a disk file instead. The size of the resulting file can be kept under control. The seq_debug global Tcl-variable described above can be used in combination with this seq_redirect command, allowing to store the debug-output into a file (whose size is kept under control).
· dputs, breakpoint, showInfo
These are additional commands which can be inserted anywhere in a script where more information or access to particular variables is required. This can obviously be done at numerous places. Although these are very powerful commands, it also requires some effort to enable/disable these additional instructions in the necessary places - and it doesn't work within [incr Tcl] code..
· seqWish
The interactive version of seqWish brings up a Tk-application (based on TkCon, see further down in section 2.4.1) which can communicate with other Tk-based applications. In other words, the commands you type in the seqWish window can be executed in the interpreter of another Tk-based application on your screen. This is useful as a debugging aid of hermetic Tk- or seqWish scripts. Without modifying or editing the source of such applications directly, you can look into its variables, change the definition of procedures, make the CCS error display pop up (via the seq_errDisplay command), etc.
To use this feature, click on the "Console" menu, then select "Attach Console" followed by the selection of your Tk-application under the "Foreign Tk Interpreters" section.
There are two caveats related to the use of this feature, as it relies on Tk's send command:
a. It will not work with a pure seqSh/Tcl script (i.e. it needs Tk)
b. xhost-style access must be enabled, and the list of enabled hosts must be empty. This is because the send command is potentially a serious security loophole, since any application that can connect to your X server can send scripts to your Tk-applications. These incoming scripts can use Tcl to read and write your files and invoke subprocesses under your name.
The latter observation is of course true for all Tk applications, and not only during debugging. More information on securing Tk applications can be obtained from the appropriate Tcl/Tk literature, the Tcl/Tk FAQs (see also section 2.8) and manpages (xhost(1), xauth(1), send(n), etc.).

2.4 RUNNING THE SEQUENCER SHELLS

2.4.1 Before you start

To run a Sequencer shell, ensure the binaries seqSh and seqWish are in your path and type from your login shell prompt (characters in italics are output):

$ seqWish5

A new window will pop up with the seqWish console (based on J. Hobbs' TkCon application), as illustrated in Figure 1. This is now the standard when seqWish is started up interactively. The previous behaviour can still be enforced by using the -noTkCon runstring option. Tkcon contains a lot of fancy stuff like command- and variable name completion, history scrolling via keyboard arrows, possibility to save stdin/stdout/stderr or the command-history to a file, etc. Extensive documentation on TkCon is available from its author via the URL http://www.cs.uoregon.edu/research/tcl/script/tkcon/.

The Sequencer interpreter can run interactively, as a shell, or it can also be started to execute immediately a script, and finish when the script tells it has finished. The Sequencer shells can actually get their input in each of the following ways:

· Via a script file. This means the shell was invoked with the name of a script, like in
$ seqWish ~/myScriptFile
In this case, ~/myScriptFile contains all Tcl/Seq commands the shell should execute. Alternatively, one can make ~/myScriptFile executable, edit it, and put on the first line
#!/vlt/bin/seqWish
whereby /vlt/bin must be replaced by the path where the seqWish binary is installed. Remark however that this line should not exceed a system defined maximum number of characters (on most systems only 32), or else exec() will fail - see the exec(2) manpages. This results in misleading error messages. A workaround for this can be found in most of the Sequencer scripts which are part of the VLT SW distribution, which have their header inserted by vltMake.
· Via the -c runstring option (only valid for seqSh, not seqWish!)
$ seqSh -c <command>
where <command> is any Tcl/Seq command to execute. It may contain a series of commands to execute, separated by `;'. The shell will execute <command> and then exit. This is useful to obtain on stdout some values which can be used as input for other processes. Example:
$ seqSh -c `seq_ccsInit; puts [seq_dbGetAlias @wte67:PARAMS]'
will send to stdout the following string:
<alias>PARAMS
and then terminate. This output could be used to pipe into another process.
· Interactively, when none of the above options have been applied. In this case, a prompt will appear, inviting the user to enter the commands via the standard input device (normally the keyboard); this interactive input must be given either in the new console window or in the original terminal window from which seqWish was started, according to whether or not the -noTkCon option is specified.
$ seqWish -noTkCon
seqWish>_
To this category belongs also the typical constructs where input is piped into the shell:
$ echo `seq_ccsInit; puts [seq_dbGetAlias @wte67:PARAMS]' | seqSh
<alias>PARAMS
$

Remark that seqWish enters the event-loop automatically when it sees an EOF; this is different from seqSh's standard behaviour, which is to terminate when it reaches the EOF. That means for the above examples with seqWish that the input should include an exit command, if the desired behaviour is to exit when the EOF is reached. If the other way around seqSh should not terminate, a vwait or commandloop command is needed - see the manpages of vwait(n) resp TclX(n).

Contrary to the standard Tk shell (wish), you will not see a small blank square window popping up on your display if you run the shell interactively. If you want to see this window, type

seqWish>wm deiconify .

Although there are no major differences between running the Sequencer interactively vs. non-interactively, one should be aware of the following:

· In an interactive shell the result string returned by a command executed from the prompt is normally echoed back to the user. If an error occurs, the error message will be displayed preceded by the string "Error:". The set command is treated as a special case: if set is called with two arguments (i.e. to assign a value to a variable), the result will not be echoed. Such behaviour deviating from standard Tcl is introduced by TclX. If set is called with one argument (the name of the variable), then the result will be echoed, as usual.
· If the interactive shell does not recognize a command entered from the prompt, then the UNIX command path as specified in the environment variable PATH will be searched for a command of that name. If such command is found, it will be executed with any arguments remaining on the Tcl commandline being passed as arguments to the command. Scripts on the other hand should use the Tcl exec or system commands to run UNIX commands.
· In an interactive shell the Sequencer will most likely spend most of its time in the idle loop, after sending the prompt and while waiting for user input. During this idle loop, events (X-events, file events, CCS events,...) are handled. If the same commands are given from a script, the Sequencer shell may not go through its idle loop until the last commandline in the script is evaluated, hence it may appear not to be as responsive as when commands are given interactively. You can get around this by inserting update commands in your script.
· Depending on the commands given in the initialization script, an interactive windowing shell may or may not display its main window. Currently, seqWish withdraws this window at start-up, if run interactively. Give the command wm deiconify . if you want this window to be displayed.

2.4.2 Starting up

In all cases, before the Sequencer shell starts interpreting user commands, it initializes itself in the following way:

1. It initializes the Tcl, TclX, Tk, TkX, [incr Tcl], [incr Tk], Msqltcl and BLT extensions in that order for seqWish; for seqSh, it initializes Tcl, TclX, [incr Tcl] and Msqltcl. If anything fails, the Sequencer shell will tell so and quit. The list of environment variables used/needed by each of these applications, and the list of global Tcl variables set by them can be found in the respective manpages of these extensions.
2. It initializes the Sequencer extensions:
· it sets the version number and makes it available via the infox appversion command
· it sets the global Tcl variable seq_ccsProcName to the string sequencer. This variable is used as the default process name for the seq_ccsInit command.
· the global Tcl variable tcl_precision is initialized to a default value set at compilation time (see Makefile). This variable is used whenever a real is converted to a string, e.g. using the expr command or seq_dbReadSymbolic
· it defines the global Tcl variable seq_library, by looking first if there is an environment variable named SEQ_LIBRARY; if not, it looks for the shell libraries relative to the working directory, the integration directory $INTROOT and finally the VLT root directory $VLTROOT.
· it sets the global Tcl variable seq_ccsType, which reflects for what environment the Sequencer was built: full for CCS+RTAP, light for CCS-light, none if without CCS.
· it defines the global Tcl variable seq_moduleId, and sets up the proper callbacks to ensure this is never modified to a too long or too short string. This variable is used as the module identifier in all errAdd calls
· it sets the global Tcl variable seq_ccsCmdCheck to NO_CHECK
· the Sequencer shell atomic commands are declared
· the script file seqInit.tcl is evaluated. It is searched for on the path given by the global Tcl variable seq_library (see higher). The main task of this script is to insert $seq_library at the top of the list of paths searched automatically when an unknown command is given. This list is kept in the global Tcl variable auto_path.
seqInit.tcl also determines your application window's icon (appearing when you press your window manager's iconify button on the application window), as follows: based on the the application name (e.g. seqWish or panel) a pixmap icon is searched for, with name <applicationName>Icon.xpm. If such colour icon exists, it will be used for the application (image name seqIcon, widget name .seqIcon). If not, a black and white bitmap with name <applicationName>Icon.xbm is searched for, which will end up as the application's icon if found. If none of the two icons are found, no icon will be defined, and the default window manager's icon will be used. This leaves the path open for easy definition of custom icons within the application's initialization code. Remark that overloading an explicitly given icon with another one may require to give the instructions
wm withdraw .; # unmap the window from the screen
wm deiconify .; # or anything else which forces a re-mapping
in order for the window manager to notify the change. The title for the icon window is anyway set by seqWish to <applicationName>@<hostName>.
If during any of these activities an error occurs, the Sequencer shell will inform you and quit.
3. If the Sequencer shell is run interactively, a file named .seqShRc resp .seqWishRc in the user's home directory will be sourced if it exists. This is intended as a facility to load development scripts, not as a means to support final applications, which should not rely like this on the user's environment.

From that point on, if there were no errors, user input is taken and evaluated.

If CCS functionality is required, i.e. the Sequencer shell is not just used as a shell that incorporates the TclX, BLT, Msqltcl and [incr Tcl] extensions, one should not forget to give a seq_ccsInit command. Try always to supply the first argument (CCS process name), or alternatively redefine the global Tcl variable seq_ccsProcName. Otherwise in a multiple user, multiple process environment one can end up with numerous processes which for CCS are all called Sequencer, and all commands addressed to Sequencer will be going to a single process (the one which did the last seq_ccsInit). Fortunately for the Sequencer shells this is only a problem for incoming commands, not replies.

2.4.3 Example Sequencer script6

#************************************************************************

# E.S.O. - VLT project

#

# seqExample.tcl

#

#

# who when what

# -------- -------- ---------------------------------------------

# eallaert 15/10/94 initial version

#

#***********************************************************************

# NAME

# seqExample - Sequencer-script for demonstration purposes

#

# SYNOPSIS

# seqExample

#

# DESCRIPTION

# This script does a number of things:

# 1. It sets the precision for reals to the maximum value

# 2. It initializes itself with CCS

# 3. It waits until another CCS application (PARTNER) is up and running

# 4. It goes into an interactive commandloop

# 5. It sends an INIT command to PARTNER and waits for a reply

# 6. 3 more commands are sent to PARTNER, without waiting for the reply

# 7. Wait for replies on the 2nd and 3rd command

# 8. Wait for replies on the 1st command

#

# CAUTIONS

# This script requires a PARTNER to execute!!

#

#-----------------------------------------------------------------------

# 1. We want full precision for DB double values, so let's set it up here

set tcl_precision 17

# 2. Let's declare our Sequencer to CCS, giving him a personalized name.

# We'll also want to be wide open for asynchronous commands.

seq_ccsInit seq_$env(USER)

seq_ccsAsyncInput open

# 3. We are supposed to wait here until our PARTNER is ready. This guy

# is started by somebody else, and he doesn't know our name. That

# means we'll have to poll him (with a PING command). Fortunately we

# know he's on our environment.

while {[catch "seq_msgSendCommand $seq_ccsEnvName PARTNER PING" cmdId]} {

sleep 1

}

seq_msgRecvReply $cmdId errNr lastReply

# 4. OK, he's alive. Let's tell it and go in an interactive commandloop.

echo {

PARTNER alive and kicking....

You can now send him a few commands, or have any set of Sequencer commands executed interactively; type CTRL-D on a fresh line to go on

}

commandloop {return $seq_ccsProcName>} {return $seq_ccsProcName=>}

# 5. Fine. Now ready for the real stuff: let's send PARTNER some commands

# First comes the initialization command, and we'd better wait for a

# positive reply on that one.

set cmdId [seq_msgSendCommand $seq_ccsEnvName PARTNER INIT]

set msg [seq_msgRecvReply -all $cmdId errNr]

if {$errNr != 0} {

puts stderr "Something went wrong: received error msg \"$msg\""

puts stderr "I cannot continue. Quitting..."

exit 1

} else {

# bring the good news...

echo $msg

}

# 6. Next some more commands, of which some can take their time to finish;

# let's send them out all, and wait for the slow ones at the end

set cmdId1 [seq_msgSendCommand $seq_ccsEnvName PARTNER CMD1 arg1]

set cmdId2 [seq_msgSendCommand $seq_ccsEnvName PARTNER CMD2 arg2 arg3]

set cmdId3 [seq_msgSendCommand $seq_ccsEnvName PARTNER CMD3]

set reply1 ""

# Some more action could come e.g. right here:

# ........

# 7. Get replies on CMD2 and CMD3 (they should finish relatively quickly).

set reply2 [seq_msgRecvReply -all $cmdId2 errNr]

if {$errNr != 0} {

# do handling for error reply

#....

}

set reply3 [seq_msgRecvReply -all $cmdId3 errNr]

if {$errNr != 0} {

# do handling for error reply

#....

}

# 8. Now we have to wait for the reply on our slow coach.

if {[catch "seq_msgRecvReply -500 $cmdId1 errNr lastReply" msg]} {

# check if the error is simply "msg queue empty" or other

if {![cequal $msg "reply timed out"]} {

echo "Got an error on receiving replies on CMD1: $msg"

echo "Cannot proceed. Quitting..."

exit

}

} else {

# seq_msgRecvReply was OK; let's see what sort of message came in

if {!$lastReply} {

# more replies pending; get them all

set reply [seq_msgRecvReply -all $cmdId1 errNr lastReply]

if {$errNr != 0} {

set msg $reply

}

}

if {$errNr == 0} {

# Concatenate first reply with rest of them

set reply ${msg}\n$reply

} else {

# got an error reply; jump out of the procedure with an error

error $msg

}

}

# And so it goes on...

....

2.4.4 Subprocesses

The Sequencer shells can of course also schedule other processes. It has for that purpose the exec command. This command normally waits until its subprocess is completed, and the return value is the standard output of the child process. If on the other hand the last argument of the exec command is &,the child process will be executed in the background, and the return value will be the process id(s) of the child(ren).

If such a background process terminates, it is still possible to retrieve its exit-status within the parent process, via the wait command (see TclX manpage). But until such a wait command is issued, the exited child process will appear as a so-called zombie in the process table. A zombie process is a process that sent a SIGCHLD signal to its parent, while the parent did not (yet) pay attention to this signal. This misleadingly suggests something is wrong, and actually some implementations of the "top" utility even insinuate that such zombie processes still consume CPU cycles, which is not the case.

Anyway, the existence of some zombies is normally not so alarming: if such a process is launched again, the system will re-use the process table of the zombie. So if a Sequencer application exec's only a limited set of children in the background, it is not necessary to do extra clean-up. When the parent Sequencer shell exits, its zombie-children will be removed from the process table.

If on the other hand a Sequencer application can schedule in the background an infinite set of different processes which then terminate as zombies, it could exhaust the process table if no measures are taken. There are some alternatives to cope with this (see also the TclX manpages):

· run occasionally the wait -nohang command, either periodically (via after) or whenever some background idle task is performed. Remark however that the application needs to ensure that this does not interfere with pieces of code that check if a background process has terminated (i.e. other uses of the wait command).
· keep track of the children process ids, and check them occasionally with the wait command.
· ignore the SIGCHLD signal (via the command signal ignore SIGCHLD). This can only be done if the application does not exec processes in the foreground, as otherwise these children would be lost: their termination would not be properly captured by the parent Sequencer shell.

2.5 THE SEQUENCER AS AN IMBEDDABLE INTERPRETER

The Sequencer comes with a C-library (libseqC.a and/or libseqC.sl) which allows it to be embedded into any application written in C-language. This opens interesting perspectives, as it means that a certain application can be partially written in C, and partially as a Sequencer script. Remark that this is quite different from e.g. sending a command to the Sequencer shell asking it to execute a certain script - in the latter case 2 processes are involved, in the former only one.

The library function which has to be called in this case to initialize the Sequencer-embedded application is seqInitInterp. Once this is done, the evaluation of any script can be requested calling seqEval.

A word of warning though: if you ask the interpreter to do a ccsInit() (passing him a script which contains a seq_ccsInit command), it means the interpreter will watch out for CCS messages/events in its event loop, i.e whenever a script contains update, or a call is made at C-level to Tcl_MainLoop() or Tcl_DoOneEvent(), and you may end up completely confused if you have your own event loop declared for such messages. In other words, one should decide whether the interpreter or the additional C code should take care of CCS messages/events, and not mix the two up.

2.6 DYNAMICALLY LOADABLE EXTENSIONS

The Sequencer shells, being based on Tcl 8.3.3, include the possibility to load binary extensions (or packages) on the fly. This means that in many cases you can start off with a very slim core, occupying little memory, and add packages as you are running the interpreter, without having to re-compile this core in order to make the new commands available. In other words, seqSh and seqWish can be extended with commonly available or your own packages, during runtime.

Of course such packages should comply with certain rules, in particular how they are compiled/built and how they initialize. Although several alternatives may exist - and are described in the Tcl manpages - in what follows these alternatives are narrowed down in a cookbook recipe fashion, for a loadable extension with package-name Ext (and VLT module name ext).

2.6.1 Initialization of a loadable extension

Whenever a package is loaded dynamically, it needs to get initialized, a.o. to add new commands to the interpreter. The Tcl core relies on a set of naming rules for the initialization procedure of any package, so it knows how to invoke this procedure.

The name of the initialization procedure which will be invoked is determined by the package-name. It will have the form Ext_Init, where Ext is the same as the package-name (with the first letter converted to upper case and all other letters converted to lower case). The initialization procedure must match the following prototype:

typedef int Ext_Init (Tcl_Interp *interp);

This initialization procedure must contain a call to Tcl_PkgProvide, like:

Tcl_PkgProvide (interp, "Ext", "1.0");

where the second argument is a string with the package name, and the third argument is a string with the version number, in the format <major_nr>.<minor_nr>.

At this point the initialization can proceed as usual, setting variables and creating commands with the Tcl_CreateCommand procedure.

The initialization procedure must return TCL_OK or TCL_ERROR to indicate whether or not it completed successfully; in the event of an error it should set interp->result to point to an error message. The result of the load command will be the result returned by the initialization procedure (see the manpage of the Tcl load command).

2.6.2 Compiling loadable extensions

Loadable extensions need to be created as shared libraries. This requires that the compiler generates position independent code (option -fPIC for gcc), and that the linker is informed that the library to build is a shared one (option -shared for gcc).

In general, libraries are not self-contained: they depend on a set of other libraries, like the math library (libm). Your shared library needs to be built declaring this list of dependent libraries, otherwise there may be undefined externals when seqSh/seqWish try to load this new package. Of course, these libraries need not be specified if they are already known by seqSh/seqWish, but it is always safer to declare them explicitly, just in case you'd like to load your package in another interpreter. The list of dependent libraries of a shared library or executable can be retrieved with the chatr utility on HP-UX or ldd on Solaris.

Remark that the exact path where your dependent libraries are searched at link-time and run-time depends a.o. on the setting of SHLIB_PATH under HP-UX and LD_LIBRARY_PATH on Solaris. It is highly recommended to go through the documentation of vltMake and shared libraries on your system.

2.6.3 Loading a package

Once this package has been built successfully following the rules explained above, and the resulting shared library libseq.sl has been installed in e.g. $TCLTK_ROOT/lib, it can be loaded into seqSh or seqWish, using the load command:

seqSh>load $TCLTK_ROOT/lib/libext.sl

If as in the example the package-name is not explicitly provided as an argument to the load command, Tcl will try to guess it as follows: take the last element of the library filename, strip off the first three characters (lib), and use any following alphabetic and underline characters as the module name, up to when a non-alphabetic character appears. So the result in our case is ext. As the first character is for the package handling anyway upshifted, ext is in this context equivalent to Ext, which is just fine. The resulting "guessed" name for the initialization procedure is Ext_Init, which is correct, and which is (or should be) part of libext.sl. Ext_Init will be called as soon as the actual loading of the shared library into shared memory is ready.

There are a few alternatives to this scheme, in particular via the package command (see the proper manpages), but they all rely one way or the other on the load command.

2.6.4 Examples from the Sequencer

Actually, the Sequencer is also built as a package, contained in libseq.sl. However, due to the RTAP licensing scheme, this package cannot be loaded dynamically, as it will result in an undefined external. When the Sequencer is built in a CCS-light environment, or without CCS, it will not contain any commercial products with restrictive license schemes like RTAP; so a shared seq-library built under CCS-light or without CCS can be loaded dynamically into any Tcl shell.

Another component of seqWish, namely the package to load pixmap images, is also built as a loadable extension, and can be used by any shell which includes Tk. The package name is SeqXpm, the shared library is libseqXpm.sl.

Finally, the SeqOslx extension is also built as a loadable extension. It is actually used as an example in the VLT software context, under the example subdirectory of the seq module. Check a.o. Makefile.seqOslx.

2.7 SEQUENCER VARIABLES

All global variables set/and used by Tcl/Tk, TclX, BLT, Msqltcl and iTcl are of course a subset of the global variables accessed by the Sequencer shells. The most important ones are:

· argc: number of commandline arguments
· argv0: the name of the executable script file or the shell's name
· argv: the commandline arguments; take into account that argument name-value pairs which are recognized by the shell itself should come first on the commandline, and will not be part of argv. E.g.
$ seqWish -display myXTerm:0.0 -myArg1 Val1 -myArg2 Val2
seqWish> set argv
-myArg1 Val1 -myArg2 Val2
...

· auto_path: list of paths to search to locate Tcl scripts. Used by the auto_load command and the unknown command handler. Initialized by TclX (TclInit.tcl), and extended by seqInit.tcl
· env: array variable whose elements are all of the process's environment variables.
· tcl_interactive: set to 1 by TclX if the shell is invoked interactively
· tcl_precision7: the number of significant digits to retain when real values are converted to strings.
· tcl_prompt1: contains Tcl code to generate the prompt used when interactively prompting for commands. The code in this hook will be evaluated and the result will be used for the prompt. Initially set to the programs's name followed by a greater-than sign (e.g. seqWish >).
· tcl_prompt2: contains Tcl code to generate the prompt used when interactively prompting for continuation of an incomplete command. The code in this hook will be evaluated and the result will be used for the prompt. Initially set to =>.
· tk_library: set by Tk to hold the path name of the directory containing a library of standard Tk scripts and demos. This variable is set from the environment variable TK_LIBRARY, if it exists, or from a compiled-in default otherwise
· tk_strictMotif: if set to 1 by the application, Tk will try to observe Motif compliance.

The public, global variables added to this list by the Sequencer shells are:

· seq_ccsCmdCheck: enables/disables the CCS message system command/reply checking based on CDTs. Must be set to either NO_CHECK or CHECK_CMD. The default is NO_CHECK. Remark that the value of this variable at the time a command is sent has also an impact on the behaviour of seq_msgRecvReply for replies on this command, i.e. whether the CDT will be accessed to format the reply or not. See the seq_msgRecvReply manpage
· seq_ccsEnvName: a read-only variable, containing the name of the environment under which the Sequencer shell is running. The initial value is an empty string, and it is set by a successful seq_ccsInit
· seq_ccsProcName: initialized to seqNAME as defined in the include file seq.h. Can also be retrieved with the infox appName command. It is used as the default name under which to register the Sequencer shell with seq_ccsInit
· seq_ccsStatus: reflects the CCS status of the Sequencer. This variable is either undefined (no seq_ccsInit given), or it is set to OPEN or CLOSED, depending on whether a seq_ccsInit was followed by a seq_ccsAsyncInput open or not.
· seq_ccsType: a global Tcl variable, read-only, which reflects how the shell was linked. It is set to either full, light or none, depending on whether the shell was linked with full CCS, CCS-light or without CCS.
· seq_debug: a global Tcl array-variable, which reflects the debug-info flag for each of the primary seq_* commands it can handle. Each of the elements of this array can be set to 0 (default - no debug info) or have any combination of the following bits set: bit 0 (print stack level, command name plus arguments to stderr), 1 (return-value gets printed), 2 (print timestamp) and 3 (print internal, command-specific debug info). If bit 1 is set, the return value is printed as "OK" or "ERR" followed by the return-string put in between greater-than and less-than signs, e.g. `OK >13.1<`. This provides basic functionality to debug scripts at the seq-level - see also section 2.3.11.
· seq_errLogging: a global Tcl variable reflecting how the logging of errors occuring during the execution of seq_* commands are dealt with; auto (default) leads to automatic logging of all unrecoverable errors (by issuing an errCloseStack), off will not log any error (by issuing an errResetStack), while manual will not issue any err*Stack command nor access the "display stack". In the latter case it is assumed that the script will take care of the error stack via "seq_err* -internal|-reply" commands. In all cases, the corresponding error stack will be copied over to the "display stack".
· seq_errReplyMerging: a global Tcl variable which determines how the merging of error-replies will take place; internal will append the reply-stack to the internal error stack, local will make the reply-stack append to the default stack of seq_errAdd etc, while off (default) leaves the error reply stack alone. In the former two cases, the error reply stack will be reset after merging, without any logging. In the latter case, it will get logged automatically if seq_errLogging is set to auto, in which case it will also be copied over to the "display stack".
· seq_library: set by the Sequencer shell to hold the path name of the directory containing a library of standard Sequencer scripts. This variable is set from the environment variable SEQ_LIBRARY, if it exists, or after locating the shell library scripts under either ../lib, $INTROOT/lib or $VLTROOT/lib.
· seq_moduleId: initialized to "seq", and used throughout the Sequencer interpreter for CCS error and logging system calls. The package name is also derived from this default value (presently seq): it is the same, with the first character converted to uppercase (i.e. Seq).
· seq_obiScript: a global Tcl variable containing the script to be executed when an obituary message is received. This script can contain some variables (single characters preceded by a %-sign) giving information about the obituary itself; they are substituted just before evaluation of the script.

2.8 INTERNET RESOURCES ON TCL/TK

There is of course a lot more information on Tcl/Tk available "out there" than ever can be contained in this User Manual, and the list is growing at an accelerating pace. As a starter, this section shows some of the Tcl/Tk documentation resources available on the Internet. These resources are given here as URLs8.

· the new home of the Tcl/Tk core is ActiveState:
http://www.activestate.com
· the central archive with most contributions/extensions to Tcl/Tk used to be at
http://www.NeoSoft.com/tcl/
· recently the Tcl/Tk community acquired the tcl.tk domain:
http://www.tcl.tk
contains a wealth of links to all sorts of Tcl/Tk documentation.
· a real good place to start when one has particular questions or when looking for an exhaustive list of links or a bibliography is the FAQs at
http://resource.tcl.tk/resource/doc/faq/
· there is also an on-line tutor available at
http://www.msen.com/~clif/TclTutor.html
· or you can look at some Tcl programming ideoms at
http://www.doc.ic.ac.uk/~np2/patterns/tcl/index.html
· the home pages for iTcl, iWidgets and BLT all used to start off from the same site:
http://www.tcltk.com/
however, this site has been down lately, and it is not clear to which other site this info is going to be relocated. In any case, the code sources for these extensions are currently on SourceForge.
· there are some html-pages ordered as an index to a set of Tcl/Tk references available on the WWW:
http://www.sco.com/Technology/tcl/Tcl.html
· of course there are also newsgroups dedicated to Tcl/Tk:
news:comp.lang.tcl
news:comp.lang.tcl.announce
The latter newsgroup is moderated. An archive of it can be found at
http://www.findmail.com/list/tcl_announce/

1
Dynamic loading has been supported in Tcl since the release of Tcl 7.5

2
As far as syntax is concerned, Tcl and the Sequencer are identical, and are used interchangeably in this context.

3
Remark that from this point on there is a difference between normal words and Tcl words: the former cannot contain whitespace or newlines, the latter is like any C string.

4
Remark that up to and including the November 1996 release of the Sequencer, RTD was a standard part of seqWish. This is no longer the case: RTD is now a loadable extension. If any RTD function is required within seqWish, if suffices to give first the command package require Rtd.

5
Most of the examples given here use seqWish; this can be substituted by seqSh according to your needs

6
The lines of code needed to make this script executable are automatically inserted by vltMake, provided the Makefile is properly defined, i.e. according to the VLT standards.

7
The use of this variable is extended by the Sequencer interpreter to DB-reads as well. The Sequencer shells will also initialize this variable to a compiled-in default.

8
All of these URLs were checked at the time of inclusion in this manual; of course there is no guarantee that at the time of reading they are all still correct, in particular the ones referring to home-directories of individuals.



Quadralay Corporation
http://www.webworks.com
Voice: (512) 719-3399
Fax: (512) 719-3606
sales@webworks.com
TOC PREV NEXT INDEX