Extending Tcl

Clif Flynt, in Tcl/Tk (Third Edition), 2012

15.5 Embedding the Tcl Interpreter

The most common use of Tcl is as an interpreter with extensions to add functionality. The most common commercial use of the Tcl interpreter is to embed it within a C, C\# or C++ application. In this architecture, the mainline code is compiled and the Tcl interpreter is invoked to run specific scripts—to read a configuration file, display a GUI, to allow a user to customize behavior, etc.

This technique is very powerful, since it provides you with the speed and power of a compiled language with the versatility and ease of customization of an interpreted language.

Examples of this style of programming include most of the high-end CAD and EDA packages, Cisco's IOS, the TuxRacer game, the sendmail tclmilter and the Apache Rivet package. These applications define configuration options and simple operations in a Tcl script file and then perform the CPU-intensive operations within a compiled section.

Embedding the Tcl interpreter within a C application requires a few items:

1.

The Tcl include files (tcl.h, tk.h).

2.

The Tcl library for the target system (libTcl.a, libTcl.so, libTcl.dll.)

3.

Some support code in the application to link to the Tcl interpreter.

The include files and libraries are included with the standard Tcl distributions, or they will be created if you compile Tcl and Tk from source (described in the next section).

Embedding Tcl or Tk into a C or C++ application uses these functions:

Tcl_FindExecutableFills internal Tcl variable that is used by info nameofexecutable. This is not absolutely required, but is good to include.
Tcl_CreateInterpCreates a new interpreter. After this command has been completed the new interpreter can be used for some applications. The compiled commands will be available, but Tcl commands that are implemented in scripts (for example, parray) will not be loaded until Tcl_Init has been called.
Tcl_InitLoads the Tcl initialization scripts to fully initialize the interpreter and create all standard commands.
Tk_InitLoads the Tk initialization scripts. This is only valid if you have linked the Tk interpreter into your application.
Tcl_EvalEvaluates a Tcl script and returns TCL_OK or TCL_FAIL.
Tcl_ExitClean up and exit.

The Tcl_FindExecutable and Tcl_CreateInterp function calls can be done in any order. Both of these should be done before calling the Tcl_Init or Tk_Init functions. The Tcl_Init function should be invoked before Tk_Init. The Tcl_Eval function should not be called until the previous functions have returned.

The first two function calls when initializing an embedded Tcl interpreter should be Tcl_FindExecutable and Tcl_CreateInterp. These two calls can be done in either order, but both should be done before calling Tcl_Init.

Syntax: void Tcl_FindExecutable (argv0)

Determines the complete path to the executable. If the argv0 argument includes a rooted path that is used, else the current working directory and argv[0] value are used.

argv0C and C++ applications pass the command line arguments as an array of strings. The first element of this array will be the name of the executable.

Syntax: Tcl_Interp *Tcl_CreateInterp ()

Creates a new interpreter and defines the basic commands.

The Tcl_CreateInterp command returns a pointer to the new Tcl interpreter. This is actually a pointer to the Tcl interpreter state structure. Multiple interpreters share the same code base, but each have their own state structure.

This interpreter pointer is passed to most Tcl library functions.

The Tcl_Init and Tk_Init functions both require the tt Tcl_Interp pointer.

Syntax: int Tcl_Init (interp)

Initializes the Tcl Interpreter. This involves loading and evaluating the init.tcl script and other scripts in the library.

interpA pointer to the Tcl_Interp structure returned by a call to Tcl_CreateInterp.

The Tcl_Init and Tk_Init functions return an integer return that conforms to normal C conventions–a ‘‘0" (TCL_OK) indicates success and a non-zero return (TCL_FAIL) indicates an error. Information about the failure can be obtained by using Tcl_GetVar to retrieve the contents of the errorInfo global variable.

After an interpreter has been created and initialized your application can send scripts to be evaluated. These scripts can be simple Tcl commands, or long and complex scripts. There are several flavors of the Tcl_Eval command depending on whether the script is already in a Tcl object, a file, or included in the code as a string. The most basic function is Tcl_Eval.

Syntax: Tcl_Eval (interp, string)

Evaluate a string of Tcl commands within an interpreter.

interpA pointer to the Tcl_Interp structure returned by a call to Tcl_CreateInterp.
stringA printable string consisting of one or more Tcl commands.

The last step is to invoke Tcl_Exit to exit your application. This is preferred over the normal exit function because it will do a bit more cleanup of the Tcl interpreter and make sure no data is left in limbo.

Syntax: Tcl_Exit (status)

Clean up the Tcl interpreter state and exit.

statusAn integer status to return to the OS. The standard is to return 0 for a success and non-zero for some exception exit.

The next example is a minimal main.c which will create and initialize a Tcl interpreter and then load and evaluate the commands in a file.

Example 14

main.c

#include <stdlib.h>

#include <tcl.h>

#include <tk.h>

main(int argc, char *argv[]) {

 // Tcl ‘glue’ variables

 Tcl_Interp *interp; /* Interpreter for application. */

 int rtn;

 // Create the interp and initialize it.

 Tcl_FindExecutable(argv[0]);

 interp = Tcl_CreateInterp();

 if (Tcl_Init(interp) == TCL_ERROR) {

 return TCL_ERROR;

 }

 if (Tk_Init(interp) == TCL_ERROR) {

 return TCL_ERROR;

 }

 // Run the Tcl script file - hardcoded for myScript.tcl

 rtn = Tcl_Eval(interp, "source myScript.tcl");

 if (rtn != TCL_OK) {

 printf("Failed Tcl_Eval: %d \n%s\n", rtn,

 Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY));

 exit(-1);

 }

 Tcl_Exit(0);

}

In the previous example, the script performs all the operations. It might load another extension, create a GUI, create a web server or anything else.

If you're embedding Tcl within a set of compiled code, you probably have a set of compiled functions that you'd like the Tcl scripts to have access to. These can be built into the executable, rather than loaded from a compiled library, as is done with extensions.

The functions described in the previous sections about building a Tcl extension are also used to create new commands to be used with an embedded interpreter.

The next example shows a main.c with a new command being created. The new command is factorcount, which finds the number of factors a value has by dividing the value by all smaller integers to see which will divide it evenly. This function has no use except that it chews up fewer CPU cycles when compiled than it does when interpreted.

Example 15

main.c with new command

#include <stdlib.h>

#include <math.h>

#include <tcl.h>

#include <tk.h>

#include "./factorcountInt.h"

main(int argc, char *argv[]) {

 // Tcl ‘glue’ variables

 Tcl_Interp *interp; /* Interpreter for application. */

 int rtn;

 // Create the interp and initialize it.

 interp = Tcl_CreateInterp();

 Tcl_FindExecutable(argv[0]);

 if (Tcl_Init(interp) == TCL_ERROR) {

 return TCL_ERROR;

 }

 if (Tk_Init(interp) == TCL_ERROR) {

 return TCL_ERROR;

 }

 // Add the factorcount command

 Tcl_CreateObjCommand(interp, "factorcount",

 Factorcount_Cmd, (ClientData) NULL, NULL);

 // Run the Tcl script file - hardcoded for myScript.tcl

 rtn = Tcl_Eval(interp, "source myScriptFactor.tcl");

 if (rtn != TCL_OK) {

 printf("Failed Tcl_Eval: %d \n%s\n", rtn,

 Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY));

 exit(-1);

 }

}

The Factorcount_Cmd function is mostly code to check that the Tcl command was called correctly. In a real application there would probably be more logic than checking that the script writer used the right parameters.

Example 16

factor.c

#include "./factorcountInt.h"

int Factorcount_Cmd(ClientData factorcount,

 Tcl_Interp *interp,

 int objc,

 Tcl_Obj * CONST *objv) {

 /* ClientData factorcount; /* Not used. */

 /* Tcl_Interp *interp; /* Current interpreter. */

 /* int objc; /* Number of arguments. */

 /* Tcl_Obj *CONST objv[]; /* Argument objects. */

 // Tcl variables

 int result;

 Tcl_Obj *returnValue;

 // function variables

 int product; // Product to find factors for - from user

 int count; // Count of factors

 int i; // loop variable

 int f2; // Temporary factor variable

 // Assume everything will be ok

 result = TCL_OK;

 /*

 * Initialize the return value

 */

 returnValue = NULL;

 /*

 * Check that we have a command and number

 */

 if (objc < 2) {

 Tcl_WrongNumArgs(interp, 1, objv,

 "factorCount number");

 return TCL_ERROR;

 }

 if (TCL_OK !=

 Tcl_GetIntFromObj(interp, objv[1], &product)) {

 result = TCL_ERROR;

 goto done;

 }

 count = 0;

 for (i=1; i < product; i++) {

 f2 = product/i;

 if (f2*i == product) {

 count++;

 }

 }

 returnValue = Tcl_NewIntObj(count);

done:

 /*

 * Set the return value and return the status

 */

 if (returnValue != NULL) {

 Tcl_SetObjResult(interp, returnValue);

 }

 return result;

}

The factorcountInt.h file is mostly the previously described boilerplate with these lines to define the new command:

factorcountInt.h

/***

extern "C" {

***/

EXTERN EXPORT(int,Factorcount_Cmd) _ANSI_ARGS_

 ((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST *));

/***

 }

***/

The example script to go with this script will create a small GUI and invoke the factorcount command to evaluate the user input.

Example 17
Script Example

set done 0

label .l1 -text "Enter Number:"

entry .e1 -textvar product

button .b1 -text "go" -command {set answer [factorcount $product]}

button .b2 -text "done" -command {set done 1}

label .l2 -text "Factors:"

label .l3 -textvar answer

grid .l1 .e1

grid .b1 .b2

grid .l2 .l3

vwait done

Script Output

The script uses vwait to force the script to run until the user exits. An application that intends to be GUI driven might follow Tcl_Eval with a call to Tcl_MainLoop to enter the event loop and stay there until the interpreter exits.

Syntax: Tk_MainLoop ()

Calls the event loop processing code repeatedly. Returns when the last window is destroyed.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000154

Introduction to the Tcl Language

Clif Flynt, in Tcl/Tk (Third Edition), 2012

3.2 Command Evaluation and Substitutions

Much of the power of the Tcl language is in the mechanism used to evaluate commands. The evaluation process is straightforward and elegant but, like a game of Go, it can catch you by surprise if you do not understand how it works.

Tcl processes commands in two steps. First, it performs command and variable substitutions, and then it evaluates the resulting string. Note that everything goes through this evaluation procedure. Both internal commands (such as set) and subroutines you write are processed by the same evaluation code. A while command, for example, is treated just like any other command. It takes two arguments: a test and a body of code to execute if the test is true.

3.2.1 Substitution

The first phase in Tcl command processing is substitution. The Tcl interpreter scans commands from left to right. During this scan, it replaces phrases that should be substituted with the appropriate values. Tcl performs two types of substitutions:

A Tcl command within square brackets ([…]) is replaced by the results of that command. This is referred to as command substitution.

A variable preceded by a dollar sign is replaced by the value of that variable. This is referred to as variable substitution.

After these substitutions are done, the resulting command string is evaluated.

3.2.2 Controlling Substitutions with Quotes, Curly Braces, and the Backslash

Most Tcl commands expect a defined number of arguments and will generate an error if the wrong number of arguments is presented to them. When you need to pass an argument that consists of multiple words, you must group the words into a single argument with curly braces or with quotes.

The difference between grouping with quotes and grouping with braces is that substitutions will be performed on strings grouped with quotes but not on strings grouped with braces. Examples 6 and 7 show the difference between using quotes and curly braces.

The backslash may be used to disable the special meaning of the character that follows the backslash. You can escape characters such as the dollar sign, quote, or brace to disable their special meaning for Tcl. Examples 8 and 9 show the effects of escaping characters. A Tcl script can generate an error message with embedded quotes with code, as in the following.

puts "ERROR: Did not get expected \"+OK\" prompt"

The following examples show how quotes, braces, and backslashes affect the substitutions. The first example places the argument to puts within curly braces. No substitutions will occur.

Example 6
Script Example

set x 2

set y 3

puts {The sum of $x and $y is returned by [expr $x+$y]}

Script Output

The sum of $x and $y is returned by [expr $x+$y]

In Example 7, puts has its argument enclosed in quotes, so everything is substituted.

Example 7
Script Example

set x 2

set y 3

puts "The sum of $x and $y is [expr $x+$y]"

Script Output

The sum of 2 and 3 is 5

In Example 8, the argument is enclosed in quotes, so substitution occurs, but the square brackets are escaped with backslashes to prevent Tcl from performing a command substitution.

Example 8
Script Example

set x 2

set y 3

puts "The sum of $x and $y is returned by \[expr $x+$y\]"

Script Output

The sum of 2 and 3 is returned by [expr 2+3]

Example 9 escapes the dollar sign on the variables to prevent them from being substituted and also escapes a set of quotes around the expr string. If not for the backslashes before the quotes, the quoted string would end with the second quote symbol, which would be a syntax error. Sets of square brackets and curly braces nest, but quotes do not.

Example 9
Script Example

set x 2

set y 3

puts "The sum of \$x + \$y is returned by \"\[expr \$x+\$y\]\""

Script Output

The sum of $x + $y is returned by "[expr $x+$y]"

Splitting Lists

The {*} operator will convert a list to its component parts before evaluating a command. This is commonly used when one procedure returns a set of values that need to be passed to another procedure as separate values, instead of as a single list.

The set command requires two arguments to assign a value to a variable - the name of the variable and the value. You cannot assign the variable name and value to a string and then pass that string to the set command.

# This is an error

set nameANDvalue "a 2"

set $nameANDvalue

The {*} operator can split the string "a 2" into two components: the letter a and the number 2.

Example 10
Script Example

# This works

set nameANDvalue "a 2"

set {*}$nameANDvalue

puts $a

Script Output

2

3.2.3 Steps in Command Evaluation

When a Tcl interpreter evaluates a command, it makes only one pass over that command to perform substitutions. It does not loop until a variable is fully resolved. However, if a command includes another Tcl command within brackets, the command processor will be called recursively until there are no further bracketed commands. When there are no more phrases to be substituted, the command is evaluated, and the result is passed to the previous level of recursion to substitute for the bracketed string.

The next example shows how the interpreter evaluates a command. The indentation depth represents the recursion level. Let's examine the following command.

set x [expr [set a 3] + 4 + $a]

The expr command performs a math operation on the supplied arguments and returns the results. For example, expr 2+2 would return the value 4.

The interpreter scans the command from left to right, looking for a phrase to evaluate and substitute. The scanner encounters the left square bracket, and the command evaluator is reentered with that subset of the command.

expr [set a 3] + 4 + $a

The interpreter scans the new command, and again there is a bracket, so the command evaluator is called again with the following subset.

set a 3

There are no more levels of brackets and no substitutions to perform, so this command is evaluated, the variable a is set to the value 3, and 3 is returned. The recursive call returned 3, so the value 3 replaces the bracketed command, and the command now resembles the following.

expr 3 + 4 + $a

The variables are now substituted, and $a is replaced by 3, making the following new command.

expr 3 + 4 + 3

The interpreter evaluates this string, and the result (10) is returned. The substitution is performed, and the command is now as follows.

set x 10

The interpreter evaluates this string, the variable x is set to 10, and tclsh returns 10. In particular, note that the variable a was not defined when this command started but was defined within the first bracketed portion of the command. If this command had been written in another order, as in the following,

set x [expr $a + [set a 3] + 4 ]the Tcl interpreter would attempt to substitute the value of the variable a before assigning the value 3 to a.

If a had not been previously defined, it would generate an error.

If a had been previously defined, the command would return an unexpected result depending on the value. For instance, if a contained an alphabetic string, expr would be unable to perform the arithmetic operation and would generate an error.

A Tcl variable can contain a string that is a Tcl command string. Dealing with these commands is discussed in Chapter 5.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000038

Tcl/Tk Features

Clif Flynt, in Tcl/Tk (Third Edition), 2012

1.8 Shipping Products

When it comes time to ship a product, you can either ship the Tcl scripts and Tcl interpreter or merge your Tcl script into an interpreter to create a Tcl-based executable. The advantage of shipping the Tcl scripts is that competent users (or clever programs) can modify and customize the scripts easily. The disadvantages include the need for the user to have the proper revision level of Tcl available for the script to run and the possibility that someone will reverse engineer your program.

A Tcl script can be wrapped into a copy of the interpreter, to create a binary executable that will run only this script. (See the discussions of starkit, ActiveState's tclapp, and Dennis Labelle's Freewrap in Chapter 18.) With these techniques, you can develop your program in a rapid development environment and ship a single program that does not require installation of the Tcl interpreter and has no human-readable code.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000014

Namespaces, Packages and Modules

Clif Flynt, in Tcl/Tk (Third Edition), 2012

8.2.1 How Packages Work

A Tcl package includes an index file that lists the procedures and commands defined in the package. The Tcl interpreter resolves unknown procedures by searching the index files in the directories listed in the global variable auto_path for required packages. The auto_path variable is defined in the init.tcl script, which is loaded when a Tcl or Tk interpreter is started.

This section describes creating the index files and adding your package directories to the list of places the interpreter will search. Note that when you create an index for a package that has procedures defined within a namespace, only the procedure names listed in a namespace export command will be indexed.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000087

Programming Tools

Clif Flynt, in Tcl/Tk (Third Edition), 2012

18.5.1 freewrap

Language executable

Primary Site http://sourceforge.net/projects/freewrap/

Contact [email protected]

Tcl Revision Supported Tcl: 8.0-8.6 and newer; Tk: 8.0-8.6 and newer

Supported Platforms UNIX, MS Windows, Mac, Mac OS-X

The freewrap wrapper uses the zip file feature of including an executable preamble. The freewrap application adds support for treating a zip file as a file system to the Tcl interpreter, and then adds that interpreter to a zip file, creating a compressed executable program.

One nice feature of this technique is that if you have a copy of freewrap that was compiled on a target platform, you can use that copy to create an executable for that platform from any other platform. For instance, you can create Windows and Solaris executables on a Linux platform.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B978012384717100018X

Using Strings and Lists

Clif Flynt, in Tcl/Tk (Third Edition), 2012

5.7.4 Global Information Variables

Tcl has several global variables that describe the version of the interpreter, the current state of the interpreter, the environment in which the interpreter is running, and so on. Some of these variables are simple strings or lists, and some are associative arrays. Associative arrays will be discussed in more detail in the next chapter. The information variables include the following.

argvA list of command line arguments.
argcThe number of list elements in argv.
envAn associative array of environment variables.
tcl_versionThe version number of a Tcl interpreter.
tk_versionThe version number of the Tk extension.
tcl_pkgPathA list of directories to search for packages to load.
errorInfoAfter an error occurs, this variable contains information about where the error occurred within the script being evaluated.
errorCodeAfter an error occurs, this variable contains the error code of the error.
tcl_platformAn associative array describing the hardware and operating system the script is running under. The tcl_platform associative array has several indices that describe the environment the script is running on. These indices include:
userThe username of the user running the interpreter.
byteOrderThe order of bytes on this hardware. Will be LittleEndian or BigEndian.
osVersionThe version of the OS on this system.
machineThe CPU architecture (i386, sparc, and so on).
platformThe type of operating system. Will be macintosh, unix, or windows.
osThe name of the operating system. On a UNIX system this will be the value returned by uname -s. For MS Windows systems it will be Windows NT, or Windows 95. Microsoft Windows platforms are identified as the base version of the OS. Windows 2000 is identified as Windows NT, and Windows 98 and ME are identified as Windows 95.
New array indices have been added in Tcl8.5 and Tcl8.6. These include:
threadedWill be 1 if the interpreter is compiled with threading enabled, else 0
pointerSizeThe size of a pointer on this machine.
wordSizeThe size of a word on this machine.
Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000051

Tips and Techniques

Clif Flynt, in Tcl/Tk (Third Edition), 2012

19.7 Bottom Line

This chapter has discussed several tricks, techniques, and tips for writing efficient and maintainable Tcl scripts. These include the following.

You can use other wish interpreters or new windows to debug a wish application.

Some applications should be written as separate programs, invoked with exec, rather than as extensions or Tcl scripts.

The Tcl interpreter is not the UNIX command shell or COMMAND.COM.

Be aware of possible leading zeros in numbers.

Most Tcl commands do not modify the content of their arguments. append, lappend, set, lset, and incr are exceptions.

Use the Tcl interpreter to parse data whenever possible, rather than writing new code to parse data.

Use a single global array for shared data instead of many variables. If you must use many variables, group them into a global list and evaluate that list to declare the globals in procedures.

Use data rather than code to control GUI contents whenever practical.

Use the profiler package or time command to analyze code before you try to optimize it.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000191

Basic Object-Oriented Programming in Tcl

Clif Flynt, in Tcl/Tk (Third Edition), 2012

Invoking Methods from Within Methods

Any existing command, procedure or object method can be evaluated within the body of a method. As you would expect, if you attempt to evaluate a procedure or an object method that has not yet been defined, the Tcl interpreter will generate an error.

Note that methods are not commands. When an object is instantiated, the object name is used as the name of a command, and the methods are subcommands within that command. This is expanded from the namespace ensemble command discussed in Chapter 8.

You can invoke methods for other objects with the name of the object and the method name, just as you would evaluate an object's method from the global or a procedure scope.

In order to evaluate a method within the current object, TclOO provides the virtual command my. Each object has a my command that is the current object.

In the next example a class is created with three methods to show evaluating the objects methods.

 showValue Displays the value of the object variable.

 external Invokes the showValue method of another object.

 internal Invokes the showValue method of the current object.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000099

Applications with Multiple Environments

Clif Flynt, in Tcl/Tk (Third Edition), 2012

16.4 Bottom Line

Tcl supports several techniques for controlling several application environments within a single interpreter.

The event loop can be used to invoke Tcl procedures with information about the environment that caused the event.

Slave interpreters contain a private copy of a Tcl interpreter.

Tcl supports creating threads at both the script and compiled code layer.

The fileevent command will invoke a script when data is available on an IO channel.

fileevent channel direction ?script?

The upvar command can map a global state variable into a procedure scope.

upvar ?level? variableName newName

The trace command can be used to evaluate a procedure when a variable is modified.

trace add type name ops script

The bind command will bind a script to a widget and will invoke that script when a specific event occurs.

bind tag event script

A slave interpreter is created with the interp create command.

interp create ?-safe? ?--? ?name?

Tcl interpreters can be full functioned or safe. A safe interpreter has no capability to interact outside of the application.

Code is evaluated within a slave interpreter with the interp eval command.

interp eval name script

A safe interpreter can be given access to a channel created in a full-featured interpreter with the interp transfer command.

interp transfer primaryInterp channel destInterp

Script level threading is supported with the Thread package. Commands within the Thread package exist within the thread:: namespace.

A new thread can be created within a script with the thread::create command.

thread::create ?-joinable? ?-preserved? ?script?

A script can be sent to a thread for evaluation with the thread::send or thread::eval commands.

thread::send ?-async? ?-head? threadID script ?variableName?

A new thread can be created at the C layer using the Tcl_CreateThread function.

Tcl_CreateThread (idPtr, func, clientData, stack, flags)

One thread can wait for another thread to exit with the Tcl_JoinThread function.

void Tcl_JoinThread (threadID, result)

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000166

The Mechanics of Using the Tcl and Tk Interpreters

Clif Flynt, in Tcl/Tk (Third Edition), 2012

Changing File Association on Windows Vista and Windows 7

The simplest way to add a new file association in Windows Vista and Windows 7 is to create a new file with the extension you wish to add, right click the new file and select the Open with and add the new application for that extension as shown in the following illustration.

1.

Create a new file:

2.

Give it a name with the new extension:

3.

Right click the file icon, and select Open with, and select Choose default program…

4.

Click the Browse button at the bottom.

5.

Edit the top line to point to the folder where the Tcl binaries are installed (the common default is C:Tcl). Select bin and finally select the application you wish to use to evaluate the .tc8 files. This will probably be tclsh or wish.

Running scripts via the mouse works well for wish-based programs that do not require any command line arguments. If you need to invoke a script with command line options, you must invoke the script from a DOS command window, the Run selection, or via a shortcut.

You can create a shortcut by right-clicking on an empty space on the Windows screen and selecting the New and Shortcut menu items. In the Shortcut window, enter (or browse to) your Tcl script, followed by whatever options you wish, as shown in the following illustration.

This will create a shortcut on your desktop, and when you click that shortcut Windows will invoke the wish interpreter to evaluate the script with the command line options you entered. Using a shortcut, or the Run menu selection, Microsoft Windows will examine the registry to find out how to evaluate your script. If you want to invoke your script from a DOS-style command window, you will need to explicitly tell Windows what interpreter to use for the script. A technique that will always work is typing the complete path to the interpreter and the name of the script as follows.

C:\tcl\bin\wish myscript.tcl

If you do not wish to type ungainly long lines whenever you invoke a script, there are several options.

You can add the path to the Tcl interpreter to your DOS path.

PATH C:\Tcl\bin;C:\Windows;\C:Windows System32

You can create a .bat file wrapper to invoke tclsh. This is similar to typing out the entire path in some respect, but allows you to put a single small .bat file in C:\WINDOWS, while leaving the Tcl interpreter and libraries in separate directories.

C:\Tcl\bin\tclsh86 %1 %2 %3 %4 %5 %6 %7 %8 %9

You can write your Tcl programs as .bat files and evaluate them as filename.bat with the following wrapper around the Tcl code.

::catch {};#\

@echo off

::catch {};#\

@"C:\Tcl\bin\tclsh.exe" %0 %1 %2

::catch {};#\

@goto eof

#your code here

#\

:eof

This is similar to the startup described for UNIX Tcl files. The lines with leading double colons are viewed as labels by the .bat file interpreter, whereas the Tcl interpreter evaluates them as commands in the global namespace.

These lines end with a comment followed by a backslash. The backslash is ignored by the .bat file interpreter, which then executes the next line. The Tcl interpreter treats the next line as a continuation of the previous comment and ignores it. The catch command is discussed in Chapter 5, and namespaces are discussed in Chapter 6.

If you prefer to run your scripts by single word (i.e., filename instead of filename.bat), you can change the line @"C:\tcl\bin\tclsh.exe@" %0 %1 %2 to @@"C:\tcl\bin\tclsh.exe@" %0.bat %1 %2.The problem with the .bat file techniques is that .bat files support a limited number of command line arguments. On the other hand, if you need more than nine command line arguments, you might consider using a configuration file.

Read full chapter
URL: https://www.sciencedirect.com/science/article/pii/B9780123847171000026