home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-11 | 49.2 KB | 1,452 lines |
- Posted-By: auto-faq 3.1.1.2
- Archive-name: tcl-faq/usage
- Posting-Frequency: monthly
-
-
- TCL LANGUAGE USAGE QUESTIONS AND ANSWERS
-
- INTRODUCTION
-
- This FAQ file is intended to address some of the most commonly asked
- questions regarding the Tcl programming language. It is hoped that by
- addressing these here in this document, that the postings to
- comp.lang.tcl will be of a less repetitive and more informative
- nature. It is also hoped that via this and other available resources,
- more and more people will be able to utilize Tcl and Tcl based
- applications.
-
- This FAQ is maintained by Joe Moss (joe@morton.rain.com) and is posted
- monthly to comp.lang.tcl and news.answers and can also be obtained
- from the Tcl archive at ftp.aud.alcatel.com (198.64.191.10) in the
- /tcl/docs directory or via the World Wide Web as
- http://route.psg.com/tcl.html.
-
- Note that this FAQ deals with Tcl, not with Tk. For Tk Toolkit Q&As
- see the FAQ posting by Thomas J. Accardo (tja@cpu.com) (see the
- question below, entitled "Where can I get further info about Tcl" for
- pointers to other Tcl FAQs). However, there is some inevitable
- overlap. Some of the most commonly asked questions about usage of the
- Tk widgets are due to mis-understandings of how the Tcl interpreter
- works. These issues may still be addressed here. Also, some examples
- of Tcl usage may involve the use of the Tk widgets.
-
- Questions and Answers about the use of non-Tk related extensions (such
- as Extended Tcl and Expect, but not TkX, expectk, BLT, etc.) are also
- appropriate here.
-
- The source of this document is now maintained in HTML. It is then run
- through a couple of scripts (written in Tcl, of course) to
- automagically add question numbers, generate the Index of Questions,
- and add the From and Subject lines to the text version. The version
- available via the WWW will be updated whenever there are changes,
- while the ASCII text version will be generated and posted only once a
- month.
-
- Last modified: Wed Mar 01 00:53:48 PST 1995
- _________________________________________________________________
-
- Index of Questions:
-
- GENERAL INFORMATION:
- * Q1- Where can I get further info about Tcl?
- * Q2- Where can I find help getting Tcl to work on my machine?
- * Q3- How can I combine Tcl and C?
- * Q4- How do I combine several extensions to provide all the
- features I want?
- * Q5- What about dynamic loading?
- * Q6- How do I create a stand alone program in case Tcl isn't
- installed?
- * Q7- How do I make my script executable regardless of the location
- of tclsh?
- * Q8- Why isn't <some extension> part of the standard distribution?
-
- PROGRAMMING RELATED QUESTIONS AND ANSWERS:
- * Q9- How can I create/use association lists or property lists?
- * Q10- How can I generate a random number in Tcl?
- * Q11- How can I call one proc with the multi parameter value
- returned by another proc?
- * Q12- How can I pass an array into a proc?
- * Q13- How can I run an external command and read its output via a
- pipe?
- * Q14- How can I delete a procedure from within a script?
- * Q15- How can I get more than 7 digits of double precision?
- * Q16- How can I grab the command line when a non-built-in call is
- made?
- * Q17- How can I get or set an environment variable?
- * Q18- How can I use numbers with leading zeroes?
- * Q19- How can I find the command line arguments to my application?
- * Q20- How can I put comments in my script, e.g. in a case
- statement?
- * Q21- How can I input and output binary data?
- * Q22- How can I trap signals, and perform other more Unix specific
- functions?
- * Q23- How can I do a double indirect? - Why doesn't $$var work?
- * Q24- How can I get quoted strings to work the way I want?
- * Q25- How can I share procedures between multiple tcl applications?
- * Q26- How can I get items inserted into a list?
- * Q27- How can I perform a non-blocking read on a file identifier?
- * Q28- How can I read and write from a pipe without locking up?
- * Q29- How can I find what version I am running?
- * Q30- How can I use variables to hold array names?
-
- PLATFORM SPECIFIC AND PORTABILITY RELATED QUESTIONS:
- * Q31- How can I create shared Tcl/Tk libraries on AIX
- * Q32- Has anyone gotten Tcl to compile under HP-UX?
- * Q33- Has anyone gotten Tcl to compile under VMS?
- * Q34- What does it take to get Tcl to compile under SCO Unix?
- * Q35- Why do I get format and scan errors when I run tclTest?
- * Q36- Why do I get lots of errors under Irix 4.0.1 when I run
- tclTest?
- * Q37- Does anyone else have problems with Tcl on a Cray?
- * Q38- How do I install Tcl 7.1/Tk 3.4 on NeXTSTEP 3.1?
- * Q39- Installing TCL7.1 on NeXT
- * Q40- Installing TK3.4 on NEXTSTEP 3.1
- * Q41- Why can't I print the draft of the Tcl/Tk book?
- * Q42- Why am I getting errors on my SGI Indigo workstation?
- * Q43- How do I build expect on Solaris 2.3?
- * Q44- How do I port Tcl and Tk to a Sequent?
- * Q45- How do I get around the symbol table full msg in AU/X 3.0?
- * Q46- How do I compile Tcl on MS-DOS, MacOS, or other non-UNIX
- system?
- * Q47- How do I get Tcl to compile on my QNX system?
- * Q48- Why do I get the error message "Command not found" when I try
- to run a Tcl script?
-
- _________________________________________________________________
-
- GENERAL INFORMATION:
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q1- Where can I get further info about Tcl?
-
- The newsgroup comp.lang.tcl is for discussion of the Tcl language and
- packages based on it. There are several FAQ documents related to Tcl
- available from ftp.aud.alcatel.com in the /tcl/docs directory that
- provide further information and pointers to yet more reading material,
- both on-line and in print. They can also be accessed via the World
- Wide Web:
- http://www.cis.ohio-state.edu/hypertext/faq/usenet/tcl-faq/top.html
-
- Two other good starting points, if you are surfing the Web for
- information, are: http://www.sco.com/IXI/of_interest/tcl/Tcl.html and
- http://web.cs.ualberta.ca/%7Ewade/HyperTcl/.
-
- Of course, the source distribution itself includes a great deal of
- documentation. The latest version is 7.3, with the 7.4b2 beta release
- also available. Both can be obtained from:
- ftp://ftp.cs.berkeley.edu/ucb/tcl/.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q2- Where can I find help getting Tcl to work on my machine?
-
- Look in the Tcl distribution for the file called porting.notes. This
- will contain a collection of notes that various people have provided
- about porting Tcl to various machines and operating systems. There is
- also a file called README which should be read FIRST - before doing
- anything else with the code (this should always be one's first step
- with any package).
-
- There are also several questions and answers related to building the
- interpreter on various platforms at the end of this document.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q3- How can I combine Tcl and C?
-
- Tcl was intended to be used along with C code. Because of this, there
- are several ways to combine the two. Here is a list of some of them
- (with man page references for further info):
- * Adding Commands to Tcl (Tcl_CreateCommand)
- * Command Traces (Tcl_CreateTrace)
- * Variable Traces (Tcl_TraceVar)
- * Getting/Setting Variables (Tcl_GetVar/Tcl_SetVar)
- * Linking Variables (Tcl_LinkVar)
- * Asynchronous Event Handlers (Tcl_AsyncCreate)
- * Adding Functions to expr Command (Tcl_CreateMathFunc)
- * Custom tclAppInit Routine (Tcl_AppInit)
- * Custom main Routine (Tcl_Main)
- * Via Pipes (open)
- * exec Command (exec)
-
- The last two do not provide nearly the same level of integration as
- those near the top of the list, but they are necessary if you do not
- have access to the source code.
-
- There is plenty of documentation available that explains this in
- further detail. See the TclCommandWriting man page, included with
- Extended Tcl or available via the WWW at
- http://psg.com/~joem/CmdWrite.html
-
- See also part two of Larry's Tcl FAQ and the Tcl Bibliography for
- other references.
-
- In addition to all the ways possible with standard Tcl, several
- extensions add others, notably via pseudo-ttys with expect, and via X
- event, file event, timer, and idle callback handlers with Tk. Also
- check out Embedded Tk, available from
- ftp://ftp.std.com/pub/drh/et1_0.tar.gz
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q4- How do I combine several extensions to provide all the
- features I want?
-
- The simple answer is to create a custom Tcl_AppInit function to call
- the Init procedures for each of the desired extensions. This can be
- done by copying the tclAppInit.c (tkAppInit.c for Tk apps) file from
- Tcl source distribution, modifying it, and then linking your
- Tcl_AppInit function with the Tcl library. For example, the standard
- Tcl_AppInit looks like this:
-
- int
- Tcl_AppInit(interp)
- Tcl_Interp *interp; /* Interpreter for application. */
- {
- /* ... */
-
- if (Tcl_Init(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- /* ... */
- }
-
- In order to add the foo extension, you would add a call to the foo
- init function, like this:
-
- int
- Tcl_AppInit(interp)
- Tcl_Interp *interp; /* Interpreter for application. */
- {
- /* ... */
-
- if (Tcl_Init(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- if (Foo_Init(interp) == TCL_ERROR) {
- return TCL_ERROR;
- }
-
- /* ... */
- }
-
- For more information, see the Tcl_AppInit man page and the
- tclAppInit.c file.
-
- The more complete answer is that the simple answer doesn't always
- work. Many extensions require more extensive modifications and the way
- to combine them depends on the specific extensions involved.
-
- If you wish to include Extended Tcl, you should start with the
- Tcl_AppInit function that comes with it. Also make sure when you link
- the program that you include the Extended Tcl library before the
- standard Tcl library, for example:
-
- cc -o mytclsh mytclXAppInit.c -ltclx -ltcl ...
-
- or for an interpreter including the Tk extensions:
-
- cc -o mywish mytkXAppInit.c -ltkx -ltk -ltclx -ltcl ...
-
- On the positive side, there are also several packages available that
- can aid in combining extensions, such as Make-A-Wish, or extensions
- that include configuration files for combining them with other popular
- extensions. For example, several extensions written by Sven Delmas
- allow you to specify options to configure to generate a Makefile that
- will build an interpreter containing the specified extensions. See
- part four of Larry Virden's FAQ for the location of these and other
- packages.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q5- What about dynamic loading?
-
- The issue of dynamic loading appears fairly often in comp.lang.tcl and
- yes, the ideal method of combining extensions would be to use dynamic
- loading, but the standard Tcl distribution does not currently support
- it.
-
- The syntax of the load command has pretty much already been worked
- out. It is just a matter of implementing it on a large number of
- platforms (this is something that is definately platform dependent).
-
- Here is an excerpt from a message, dated 14 Jul 1993, written by John
- Ousterhout on the subject:
-
- At the [1993 Tcl] workshop we decided to standardize on a simple Tcl
- command interface for dynamic loading. The command syntax will be as
- follows:
-
- load <file>
-
- where <file> is the name of a dynamically-loadable object file such
- as libtcl.so. The syntax of these names may vary from system to
- system according to local custom, but part of the name should be the
- package prefix for the package, such as tcl in the above example.
-
- The load command must load the given object file, pick the package
- prefix out of the file name, then invoke the procedure
- <prefix>_Init, where <prefix> is the package prefix with the first
- letter capitalized, e.g. Tcl_Init or Dp_Init or Tclx_Init. Each
- loadable package must contain an initialization procedure that takes
- a single argument that is a (Tcl_Interp *):
-
- int Dp_Init(Tcl_Interp *interp);
-
- The init procedure adds all of that package's Tcl commands into the
- interpreter, plus performs any other package-specific
- initialization. It returns a standard Tcl completion code and leaves
- an error message or result value in the interpreter, which is
- returned as the result of the load command.
-
- Implementations for certain platforms are already available, check the
- software catalog (parts four and five of Larry Virden's FAQ) for
- details (e.g. the Shells package) and also see the paper by Kevin
- Kenny from the 1994 Tcl workshop proceedings available from
- http://crdis1.ge.com/papers/gecrd/mtl/mdip/tcl94/00header.html.
- Hopefully soon this will become part of the standard distribution.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q6- How do I create a stand alone program in case Tcl isn't
- installed?
-
- Earle Lowe (lowee@cpsc.ucalgary.ca) has replied that:
-
- If you want to create a stand-alone program that will run anywhere
- regardless of the presence/absence of TCL/Tk, than you need to go
- through some more work.
-
- Basically, this involves converting the TCL init files to C strings,
- and then rather than calling Tcl_Init() and Tk_Init(), you call
- Tcl_Eval() with the converted C strings as arguments.
-
- I suggest getting the wish_compiler package by Alexei Rodriguez
- (alexei@cis.ufl.edu) from
- ftp://ftp.aud.alcatel.com/tcl/code/wish_compiler.shar.gz
-
- This package contains a tcl2c converter, and instructions as to its
- use.
-
- With some Makefile magic, you can use using TCL/Tk as intended (as
- an interpreted language using some version of wish) and when the
- code works, you can create a stand-alone compiled program.
-
- Another option that is now available is "Embedded Tk". You can get it
- from ftp://ftp.std.com/pub/drh/et1_0.tar.gz
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q7- How do I make my script executable regardless of the location
- of tclsh?
-
- Or how can I automatically pass my script through tclsh without
- specifying a fixed path?
-
- There are several tricks you can use, but the most common is to make
- use of the fact that, in Tcl, the backslash character works as a line
- continuation indicator, even within comments. So instead of:
-
- #! /usr/local/bin/tclsh
-
- puts "Hello World"
-
- You could use:
-
- #! /bin/sh
- # The next line is executed by /bin/sh, but not Tcl \
- exec tclsh $0 ${1+"$@"}
-
- puts "Hello World"
-
- and the script will run regardless of where tclsh is located (as long
- as it is in one of the directories in the user's PATH).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q8- Why isn't <some extension> part of the standard distribution?
-
- Often people ask why some language extension that they use often (in
- fact, they may find it indispensible) isn't merged into the core
- language.
-
- It must be remembered that a lot of people use Tcl on widely differing
- systems and in vastly different ways. Also, Tcl was originally
- intended as an embedded language that would provide the minimal
- programming constructs and framework upon which a programmer could
- base the scripting language for their application.
-
- Having said that, the core Tcl language has grown over the years. Some
- of the added features have come from extensions written by others.
- When the capabilities provided by extensions are deemed to be of
- sufficient value to all users of Tcl, John has added them to the base
- language. Some examples are associative arrays, the file I/O commands
- (and file handles), and the unknown procedure, all of which appeared
- in Extended Tcl before becoming part of standard Tcl. Tk 4.0 will
- contain (and Tk4.0b2 does now contain) the equivalent functionality of
- the addinput and photo widget extensions that were written by others
- for Tcl 7.x/Tk 3.x.
- _________________________________________________________________
-
- PROGRAMMING RELATED QUESTIONS AND ANSWERS:
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q9- How can I create/use association lists or property lists?
-
- Use arrays or Extended Tcl keyed lists.
-
- For example, if you did a:
-
- keylset ttyFields ttyName tty1a
- keylset ttyFields baudRate 57600
- keylset ttyFields parity strip
-
- And then an echo $ttyFields, you'd get:
-
- {ttyName tty1a} {baudRate 57600} {parity strip}
-
- Or using arrays:
-
- set ttyFields(ttyName) tty1a
- set ttyFields(baudRate) 57600
- set ttyFields(parity) strip
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q10- How can I generate a random number in Tcl?
-
- Extended Tcl includes a command named random to do this. For example,
- to generate a random number between 0 and 9 inclusive:
-
- set random_number [random 10]
-
- It also has a srandom command to seed the random number generator.
-
- Several pseudo-random number generator functions, written in straight
- Tcl, have been posted to comp.lang.tcl, see Larry's tcl-faq/part4 for
- a list.
-
- To get a value you can use as a seed, you might try one (or a
- combination) of these:
-
- [pid]
- [file atime /dev/kmem]
- [getclock] (Extended Tcl only)
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q11- How can I call one proc with the multi parameter value
- returned by another proc?
-
- Assuming y requires multiple args and x returns multiple words, use
- Tcl's eval command:
-
- eval y [x]
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q12- How can I pass an array into a proc?
-
- Use upvar rather than try to use global variables when possible. If
- the function is event driven, you are forced to use global variables.
-
- # print elements of an array
- proc show_array arrayName {
- upvar $arrayName myArray
-
- foreach element [array names myArray] {
- puts stdout "${arrayName}($element) = $myArray($element)"
- }
- }
-
- set arval(0) zero
- set arval(1) one
- show_array arval
-
- To return an array from a procedures, just take the array name in as
- an argument, as above. Any changes you make in the array will be made
- in the parent's array as well.
-
- Extended Tcl introduces a concept called keyed lists which are arrays
- made out of lists of key-value pairs and can be passed by value to
- routines, over networks, etc.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q13- How can I run an external command and read its output via a
- pipe?
-
- For example, to grep a pattern out of a range of files, one might do:
-
- Karl Lehenbauer (karl@NeoSoft.com) writes:
-
- set files [glob /home/cole/stats/*]
-
- proc parseInfo { site } {
- global files
-
- #
- # site is chosen from a listbox earlier
- #
- set in [open [concat "|/usr/bin/grep $site $files"] r]
-
- while {[gets $in line]>-1} {
- puts stderr $line
- }
- catch {close $in}
- }
-
- One thing: the matching strings are not returned in directory order.
-
- But what if I want to check the return code AND use the output of the
- command? Kevin B. Kenny (kennykb@dssv01.crd.ge.com) writes:
-
- if [catch {exec ls} data] {
- # The exec got an error, and $errorCode has its termination status
- } else {
- # The exec succeeded
- }
- # In any case, `data' contains all the output from the child process.
-
- Note that Karl Lehenbauer (karl@NeoSoft.com) adds that errorCode will
- be a list containing three elements, the string "CHILDSTATUS", the
- process ID of the child, and the exit status of the child.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q14- How can I delete a procedure from within a script?
-
- Rename the procedure to have no name, for example:
-
- rename procedureName ""
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q15- How can I get more than 7 digits of double precision?
-
- In Tcl 7.x, set the global variable tcl_precision to a value in the
- range 1-17. For example:
-
- % expr 4*atan(1)
- 3.14159
- % set tcl_precision 0
- can't set "tcl_precision": improper value for precision
- % set tcl_precision 3
- 3
- % expr 4*atan(1)
- 3.14
- % set tcl_precision 16
- 16
- % expr 4*atan(1)
- 3.141592653589793
- % set tcl_precision 18
- can't set "tcl_precision": improper value for precision
-
- In Tcl 6.x, you must modify the tclExpr.c module to use %lf instead of
- %g.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q16- How can I grab the command line when a non-built-in call is
- made?
-
- The procedure unknown is called automatically with arguments
- containing the command and its arguments for any command that couldn't
- be found. In fact, Tcl and Extended Tcl use this feature to provide
- demand loaded commands, and even entire libraries. Also, when using
- the "tclsh" or "tcl" shells interactively, the unknown procedure
- enables the shell to run external programs (i.e. without typing "exec"
- first).
-
- So by modifying the unknown procedure you can provide your own
- extended functionality, or even remove the demand loading capability
- if you so desire.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q17- How can I get or set an environment variable?
-
- By using something like the following.
-
- set olddisplay $env(DISPLAY)
- set env(DISPLAY) unix:0
-
- Thanks to Joel Fine (joel@cs.berkeley.edu) for the answer.
-
- You can also check if an environment variable exists, like this:
-
- if [info exists env(VARNAME)] {
- # okay, it's there use it
- set value $env(VARNAME)
- } else {
- # the environment var isn't set, use a default
- set value "the default value"
- }
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q18- How can I use numbers with leading zeroes?
-
- Dave Morriss was having problems because he was trying to do something
- like:
-
- set index [expr [exec date +%W]%[llength $pop_server_list]]
-
- but during the 8th and 9th week of the year, he got errors, since 08
- and 09 are not valid octal numbers. Actually, Tcl first tries to
- interpret numbers starting with a zero as an octal number, but if that
- fails (i.e. because of invalid octal digits like 8 and 9), the value
- is then interpreted as a floating point value; the % (modulo) function
- only operates on integer values.
-
- Some of the solutions provided were:
-
- From George A. Howlett (george.howlett@att.com), we got:
-
- set wknum [format "%g" [exec date +%W]]
- set index [expr [exec $wknum%[llength $pop_server_list]]
-
- From Fred Feirtag (feirtag@wave.nrl.navy.mil):
-
- set index [expr (1[exec date +%W]-100)%[llength $pop_server_list]]
-
- From Dan R. Schenck (schendr@Texaco.com):
-
- set index [expr [string trimleft [exec date +%W] 0]%[llength \
- $pop_server_list]]
-
- Jay Goldberg (jayg@accessware.com) points out that while all of the
- above work in this case (dealing with a date) they don't work in the
- general case.
-
- Instead you can use the statement:
-
- regsub 0+(.+) orig_string \\1 new_string
-
- to strip off leading zeros. So, applying this to the example above:
-
- regsub 0+(.+) [exec date +%W] \\1 weeknum
- set index [expr $weeknum%[llength $pop_server_list]]
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q19- How can I find the command line arguments to my application?
-
- The program name is assigned to the global variable argv0 and any
- arguments to it are placed in the global variable argv as a list. The
- variable argc is set to the number of elements in the list argv. As an
- example:
-
- #! /usr/local/bin/tclsh
-
- if { $argc != 2 } {
- puts stderr "$argv0: Usage: $argv0 <infile> <outfile>"
- exit 1
- }
-
- set infile [lindex $argv 0]
- set outfile [lindex $argv 1]
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q20- How can I put comments in my script, e.g. in a case
- statement?
-
- You can't have comments where you have them. Move the comments inside
- of the { for the case that you want. Your code should read:
-
- case 1 {
- -1 {
- #
- # Cannot find information sought
- #
- exit 2
- }
- 0 {
- #
- # Error in arguments
- #
- exit 1
- }
- default {
- #
- # Desired information found
- #
- exit 0
- }
- }
-
- Thanks to Gerald W. Lester (gwlester@cpu.com).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q21- How can I input and output binary data?
-
- With Extended Tcl you can safely do stuff like:
-
- set infp [open "|compress -dc $fileName"]
- set outfp [open "|gzip -c $newFileName" w]
-
- copyfile $infp $outfp
-
- Thanks to Karl Lehenbauer (karl@NeoSoft.com) for the code example.
-
- A method of handling binary data one character at a time using
- standard Tcl can be found in:
- ftp.aud.alcatel.com:/tcl/code/binary-io-hack.shar.gz
-
- There are also two different extensions available that enable the
- handling of binary data: tclbin and BinarIO. The former is better for
- handling structured data, while the latter works better for binary
- data streams.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q22- How can I trap signals, and perform other more Unix specific
- functions?
-
- Extended Tcl offers many of these types of functions. For instance,
- extended Tcl has the signal command:
-
- signal action siglist [command]
-
- where action is one of "default", "ignore", "error", "trap", "get",
- plus the POSIX "block" and "unblock" actions (available only on
- POSIX systems, of course). Siglist is a list of either the symbolic
- or numeric Unix signal (the SIG prefix is optional). Command is your
- error handler (or a simple {puts stdout "Don't press *that* key!"}
- :-)
-
- trap does what you expect, and I find error and get to be extremely
- useful in interactive programs which demand keyboard traversal.
-
- Extended Tcl also has things like fork, etc.
-
- Answer by Brad Morrison (brad@NeoSoft.com).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q23- How can I do a double indirect? - Why doesn't $$var work?
-
- There is one and only one level of substitution possible with every
- pass through the interpreter. Also, when doing variable substitution,
- the interpreter finds the dollar sign and then takes everything
- following it up until the next invalid character (where invalid is
- defined as anything other than a letter, digit, or underscore) as the
- name of the variable - well, that is, unless it finds array notation
- or the ${varname} form.
-
- In the case of $$var, the character after the first dollar sign is an
- invalid character (another dollar sign), so there is no variable name
- and variable substitution is not performed (the dollar sign is left as
- is) and scanning starts again for any dollar signs and a following
- variable name. It is immediately found at that second dollar sign, the
- substitution is performed, and scanning for dollar signs resumes with
- whatever was after the variable name. Since there isn't anything else,
- substition is done for this pass through the interpreter (remember
- it's only done once).
-
- The eval command runs it's arguments through the interpreter, so you
- could use eval to cause a second pass through the interpreter, and
- thus, have $$var work:
-
- % set a 5
- 5
- % set var a
- a
- % puts $$var # This doesn't work
- $a
- % eval puts $$var # This does - but it's dangerous
- 5
-
- However, if the contents of var contain any special characters (e.g.
- whitespace, semicolon) you'll run into problems.
-
- A better method is to take advantage of the behaviour of the set
- command when given only one argument, and combine command substitution
- with variable substitution:
-
- % puts [set $var] # This works safely
- 5
-
- or, in fact, you could use just command substitution (which is
- performed once for each [ ] pair):
-
- % puts [set [set var]] # as does this
- 5
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q24- How can I get quoted strings to work the way I want?
-
- A long article dealing with the issues can be found at
- ftp://ftp.aud.alcatel.com/tcl/docs/README.programmer.gz
-
- Here are some short answers:
-
- Q. I'm trying to build up a command for later execution but am having
- trouble with variable values that include whitespace or special
- characters.
-
- A. The safest way to build up commands is to use the list command so
- that you can keep track of the list structure. Avoid using double
- quotes because you can end up with an extra trip through the
- evaluator. We'll illustrate this with a command to create a button
- that prints out the label on the button when you click it.
-
- Wrong answer #1:
-
- button $myname -text $label -command "puts stdout $label"
-
- Why? because if $label has whitespace then the puts command will be
- passed the wrong number of arguments. If $label has $ or [ ]
- characters, they will be interpreted instead of printed.
- Good answer #2:
-
- button $myname -text $label -command [list puts stdout $label]
-
- Why? because list will properly quote the value of $label
-
- Q. I'm trying to build up a command for later execution but am having
- trouble getting some variables to evaluate now, and some to evaluate
- later when the command is run.
-
- A. The cleanest way to do this is to define a procedure that hides the
- use of the variables at run time, and then build up a call to that
- procedure using the list command as described previously. (You can
- even define the procedure on the fly. It will have global scope even
- it if is created within another procedure.)
-
- Wrong answer #1:
-
- button $myname -text $label -command \
- [list puts stdout $ArrayOfDynamicStuff($label)]
-
- Why? The array value will be substituted when the button is created,
- not later on when the button is clicked. Also, note that the command
- is executed at the global scope, so it is not necessary to include a
- "global ArrayOfDynamicStuff" in the command.
- Wrong answer #2 (backquotes and list):
-
- button $myname -text $label -command \
- [list puts stdout \$ArrayOfDynamicStuff($label)]
-
- Why? Here the list command and the backquote of $ are fighting with
- each other. The command ends up being something like:
-
- puts stdout {$ArrayOfDynamicStuff(foo)}
-
- which prevents the substitution of the value of the array element.
- Dubious answer #3 (backquotes and double-quotes):
-
- button $myname -text $label -command \
- "puts stdout \$ArrayOfDynamicStuff($label)"
-
- Why? This only works if the value of $label has no special
- characters or whitespace.
- Clean answer #4 (proc):
-
- proc doit { i } {
- global ArrayOfDynamicStuff
- puts stdout $ArrayOfDynamicStuff($i)
- }
- button $myname -text $label -command [list doit $label]
-
- Why? Using little TCL procs for your button commands is a good habit
- because it eliminates most needs for fancy quoting, and it makes it
- easier to tweak the button command later on.
-
- Q. I'm trying to pass along a variable number of args to another
- procedure but I'm having trouble getting the $args to expand right.
-
- A. Avoid using eval and double quotes because that results in an extra
- trip through the interpreter. The eval command will do a concat of its
- arguments if there are more than one, so that pretty much eliminates
- the need to group things with double quotes. Let's extend the button
- example:
-
- Wrong answer #1:
-
- proc mybutton { myname label args } {
- button $myname -text $label -command [list puts stdout $label] $args
- }
-
- Why? All the extra arguments to mybutton are grouped into one list
- element that is but into the value of $args. However, the button
- command expects to see individual arguments, not a sub-list.
- Wrong answer #2:
-
- proc mybutton { myname label args } {
- eval "button $myname -text $label -command [list puts stdout $label] $a
- rgs"
- }
-
- Why? The double quotes allow expansion of $label as well as $args,
- so if $label has any whitespace, the button command will be
- malformed
- Good answer #3:
-
- proc mybutton { myname label args } {
- set cmd {button $myname -text $label -command [list puts stdout $label]
- }
- eval $cmd $args
- }
-
- Why? Eval will first concatenate its two arguments and then run the
- result through the interpreter. Think of this as stripping off the
- outer curly braces from $cmd and $arg and making a single list with
- all the elements of both. $label will be evaluated exactly once, so
- the puts command will remain good, and whatever went into args will
- also be processed exactly one time.
-
- Q. Why do I get a syntax error in an if/while/for statement?
-
- A. You may have written something like
-
- wish: set foo bar
- wish: if {$foo == bar} {puts stdout bar}
- syntax error in expression "$foo == bar"
-
- in which bar is interpreted as neither a string nor a variable, since
- strings as operands in expressions MUST be surrounded by double quotes
- or braces.
-
- Change to
-
- wish: if {$foo == "bar"} {puts stdout bar}
-
- or
-
- wish: if {$foo == {bar}} {puts stdout bar}
-
- always in expressions, depending on if you want expansion performed or
- not.
-
- Contributed by Jesper Blommaskog (d9jesper@dtek.chalmers.se).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q25- How can I share procedures between multiple tcl
- applications?
-
- Rather than sourcing the files explicitly, build a tcl library:
-
- Step 1. Put the files in a common directory
-
- Step 2. Build the tclIndex for the "library". I use a Makefile with a
- convention like:
-
- install.index:
- (cd ${DESTDIR}/tclscripts/lib; \
- echo 'source /usr/local/lib/tcl/init.tcl;\
- auto_mkindex . *.tk' | tcl ; exit 0)
-
- Step 3. Modify your tcl scripts to reference the library:
-
- e.g.:
-
- # local additions
- lappend auto_path /usr/local/lib/tcl_local $env(RDS_TCL_SCRIPTS)/lib
-
- Now, as soon as your script tried to reference a procedure in the
- library, the "unknown" command autoloads the procedure for you.
-
- Contributed by Joe VanAndel (vanandel@ncar.ucar.edu).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q26- How can I get items inserted into a list?
-
- A user asked why
-
- linsert $list 0 ..
-
- did not result in .. being inserted into list.
-
- Jesper Blommaskog (d9jesper@dtek.chalmers.se) replied:
-
- When doing list operations other than lappend, you must save the
- returned value. This applies to list, lindex, lrange, and lreplace at
- least.
-
- In this example, you would perhaps want to do something like:
-
- set list [ linsert $list 0 .. ]
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q27- How can I perform a non-blocking read on a file identifier?
-
- From Frank Smith (frank@arraysystems.nstn.ns.ca) we are told that if
- you have Extended Tcl, you can
-
- read $fileId [fstat $fileId size]
-
- This will read only the number of bytes currently available on fileId
- and consequently will not block.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q28- How can I read and write from a pipe without locking up?
-
- The stdio package has an optimization for speed that buffers
- characters so that you can avoid un-necessary system calls. This isn't
- very good for interactive use so stdio changes it's behaviour if the
- file is a terminal. When you write to a pipe you are not writing to a
- terminal and so your output is buffered, similarly when the program at
- the other end of the pipe writes its response it is also buffered. The
- end result is the programs at both end of the pipe stall waiting for
- input. It is possible to force the buffers to be written using flush
- in Tcl and fflush() in C, often though, you don't have control over
- the program at the other end of the pipeline and in that case your
- only solution is to use a pseudo-teletype (pty). Unfortunately this
- isn't all that easy.
-
- While this isn't directly supported in Tcl, the spawn command in
- expect opens a pty and starts a command.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q29- How can I find what version I am running?
-
- Well, there is no one answer to this. Tcl itself will tell you it's
- version if you type:
-
- info tclversion
-
- On the other hand, to get the Tk version, you must use:
-
- puts $tk_version
-
- Other extensions use other means (for example, Extended Tcl uses
- "infox version" to return it's version number).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q30- How can I use variables to hold array names?
-
- Eric Bleeker (ericbl@paramount.nikhefk.nikhef.nl) has written:
-
- You may have written something like:
-
- % set foo "bar baz"
- bar baz
- % foreach aap $foo {
- set $aap(1) "something"
- }
- can't read "aap(1)": variable isn't array
-
- This means Tcl tries to substitute the array element aap(1) which
- doesn't exist. To fix this use:
-
- % foreach aap $foo {
- set [set aap](1) "something"
- }
-
- In this case two arrays bar and baz are created.
-
- An alternative format is:
-
- % foreach aap $foo {
- set ${aap}(1) "something"
- }
-
- _________________________________________________________________
-
- PLATFORM SPECIFIC AND PORTABILITY RELATED QUESTIONS:
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q31- How can I create shared Tcl/Tk libraries on AIX
-
- Dov Grobgeld (dov@menora.weizmann.ac.il) provided info on creating Tcl
- and Tk shared libraries under AIX 3.1.5:
-
- For Tcl:
-
- cc -o tkshar.o *.o -bE:tclshar.exp -bM:SRE -berok -lX11 -lm
- ar r libtclshr tclshar.o
-
- For Tk:
-
- cc -o tkshar.o *.o -bE:tkshar.exp -bM:SRE -berok -Ltcl -lX11 -lm -ltclshr
- ar r libtkshr tkshar.o
-
- where tckshar.exp and tkshar.exp had lists of the external
- functions.
-
- There are also problems with fonts on AIX and the IBM. A patch is
- needed from IBM to fix the X server so that fonts are working
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q32- Has anyone gotten Tcl to compile under HP-UX?
-
- See the porting notes. Also, be aware that there have been some
- reports of Configure assuming that you should use the compatibility
- version of opendir() and that you have no dirent.h . This causes
- glob-ing to fail, as well as TclX's readdir, etc.
-
- Changing tcl7.3 to remove the opendir compatibility file and removing
- the -DNO_DIRENT, -DUSE_DIRENT2 fixed it all up.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q33- Has anyone gotten Tcl to compile under VMS?
-
- Information from John Kimball (jkimball@src.honeywell.com) on May 4,
- 1993 was that he had gotten Tcl 6.7 and Tk 3.2 ported to VMS 5.5. See
- the catalog for the file information.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q34- What does it take to get Tcl to compile under SCO Unix?
-
- Add a "#undef select" to tkEvent.c, and remove the reference to
- TK_EXCEPTION around line 460 of main.c.
-
- Tk uses its own scheme for allocating the border colors for its 3D
- widgets, which causes problems when running TK on a system with
- "PseudoColor" display class, and a 16-cell colormap.
-
- If you can't go to eight bitplanes, you can instead start the server
- with a "-static" (Xsco) or "-analog" (Xsight) option, making the
- display class become "StaticColor". This makes the entire colormap
- read-only, and it will return the color that most closely maps to the
- desired color as possible.
-
- This information is from Keith Amann (Keith_Amann@stortek.com).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q35- Why do I get format and scan errors when I run tclTest?
-
- That's a problem (scanf/printf) many systems seem to have. Don't worry
- too much about it - just don't use these 'advanced' features. If
- you're hacking C, you'll have the same problems.
-
- For instance, printf("%Ng", double_value) and strtod("+",&terminal)
- produce incorrect results.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q36- Why do I get lots of errors under Irix 4.0.1 when I run
- tclTest?
-
- There's a bug in the 4.0.1 optimizer that's fixed in 4.0.2. Compile
- tclVar.c using -O0 (no optimization).
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q37- Does anyone else have problems with Tcl on a Cray?
-
- See the porting notes for a set of changes mentioned. Also, Booker C.
- Bense (benseb@grumpy.sdsc.edu) reports that version 3.0.1.6 has some
- real problems with char pointers, causing Tcl to crash. Using version
- 3.0.2.1, things are much better, except for a minor formatting problem
- and serious problems with scan.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q38- How do I install Tcl 7.1/Tk 3.4 on NeXTSTEP 3.1?
-
- I have indicated in the past that this particular question seems to
- generate controversy - I have replaced previous explanations with the
- latest msg from someone who sounds authoritative...
-
- From: Robert Nicholson (robert@steffi.demon.co.uk)
-
- This is for TCL7.1 and TK3.4
-
- This is a variation on Thomas Funke's entry.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q39- Installing TCL7.1 on NeXT
-
- To install tcl7.1 on NeXTSTEP 3.1 you must:
- * run configure with predefined CPP:
- type "sh" to run a Bourne shell. then type
-
- CPP='cc -E' ./configure
- * edit Makefile:
- add tmpnam.o to COMPAT_OBJS:
-
- COMPAT_OBJS = getcwd.o waitpid.o strtod.o tmpnam.o
-
- At this point you probably want to rename the all calls to strtod
- and tmpnam to something else in order to distinguish them from those
- that are supplied in the NeXT libraries libsys_a.a. You can do this
- by adding the following line to AC_FLAGS
-
- -Dstrtod=newstrtod -Dtmpnam=newtmpnam
-
- and renaming the names of the definitions in the appropriate
- compat/*.c files.
-
- To check everything is working correctly open a tclsh
-
- % expr {"0" == "+"}
- 0
-
- Using the wrong strtod function will cause this test to return 1
- which is a serious error. Ignore the precision errors.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q40- Installing TK3.4 on NEXTSTEP 3.1
-
- There is a call to strtod in TK3.4 so you should link against
- ../tcl-7.1/compat/strtod.o and apply the -Dstrtod=newstrtod to
- AC_FLAGS in Tk also.
-
- Note:Tk's raise test will fail when running the tvtwm window
- manager. Changing to either twm or even better fvwm ensures that
- this test will succeed.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q41- Why can't I print the draft of the Tcl/Tk book?
-
- From John Ousterhout (John.Ousterhout@Eng.Sun.COM):
-
- Here's my form letter that seems to explain most of the problems
- people have had printing parts of the book:
-
- Some old versions of the Transcript spooler software cannot properly
- handle encapsulated Postscript files within another Postscript file
- when they do page reversal. They tend to garble the page structure of
- the file, causing an error at the point of the first EPS file. Part II
- of the Tcl book has lots of EPS files embedded in it, one for each
- screen dump. If your printer cannot print this file I suggest checking
- to see if page reversal is enabled for your printer. If so, try asking
- your local system wizard to disable it for you; this should allow the
- file to print. Or, find some other way to dump the Postscript file
- directly to the printer without going through the spooling software
- (e.g. perhaps you can simply cat it to the printer's serial port).
-
- Others have suggested:
-
- The embedded pictures have CR as the line separator instead of LF and
- this may be causing the problem. Try translating them to LFs ...
-
- tr '\015' '\012' <book.p2.ps >fixedbook.p2.ps
-
- and:
-
- This is not the original poster's problem but in countries using A4
- paper and on a particular printer, the Dataproducts LZR1260E, the
- frame size causes the printing to be stretched vertically. This
- happens with other Framemaker generated documents by the way. A PS
- interpreter bug no doubt. The fix is to edit the dimensions for A4
- paper. This shell script does both fixes.
-
- #!/bin/sh
- cat $1 | tr '\015' '\012' | sed '/FMDOCUMENT$/s/612 792/595 842/'
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q42- Why am I getting errors on my SGI Indigo workstation?
-
- From Gordon Lack (gml4410@ggr.co.uk) we are told that the SGI c
- compiler has some bugs with variable arguments.
-
- tclVar.c must be compiled with -O0 at IRIX C 4.0.1 because of a
- compiler bug with varargs.
-
- Done by placing specific rule into Makefile.
-
- # GGR SG needs -O0 for varargs at 4.0.1
-
- CC_SWITCHES0 = -O0 -I. -I${SRC_DIR} ${AC_FLAGS} ${MATH_FLAGS} \
- ${GENERIC_FLAGS} ${PROTO_FLAGS} ${MEM_DEBUG_FLAGS} \
- -DTCL_LIBRARY=\"${TCL_LIBRARY}\"
-
- tclVar.o: tclVar.c
- $(CC) -c $(CC_SWITCHES0) $<
-
- Peter Neelin (neelin@pet.mni.mcgill.ca) also noted that:
-
- I get tclX 7.3a to compile on an SGI (irix 4.0.5) with the following
- changes to the Config.mk file:
-
- 71c71
- < CFLAGS=-cckr -D__GNU_LIBRARY__
- ---
- > #CFLAGS=
- 106,107c106,107
- < TCL_PLUS_BUILD=TCL_PLUS
- < CCPLUS=g++
- ---
- > #TCL_PLUS_BUILD=TCL_PLUS
- > CCPLUS=CC
- 191,193c191
- < MAN_DIR_SEPARATOR=
- <
- < LIBOBJS=strftime.o
- ---
- > #MAN_DIR_SEPARATOR=.
-
- The -D__GNU_LIBRARY solves the srandom problem and I think that the
- -cckr gets around the prototype error with waitpid (it's crude, but it
- works). I've forgotten why I needed the strftime.
-
- If you want the version of Config.mk that worked for me, send me mail.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q43- How do I build expect on Solaris 2.3?
-
- From Jeff Abramson (jra@hrcms.jazz.att.com) we are told that,
-
- using either SunPro cc 2.0.1 or gcc 2.5.8 with no problems. For
- SunPro I do:
-
- CC=cc ./configure --prefix=directory_of_your_choice
- make CC=cc
-
- For gcc I do:
-
- CC="gcc -fwritable-strings" ./configure \
- --prefix=directory_of_your_choice
- make CC="gcc -fwritable-strings"
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q44- How do I port Tcl and Tk to a Sequent?
-
- From Andrew Swan (aswan@soda.berkeley.edu) we find:
-
- For both Tcl and Tk, I used gcc rather than the Sequent cc which is
- not ansi.
-
- For Tcl, there were a couple of problems with the math library.
- First, the Sequent math library doesn't include the 'fmod' function.
- I got the source for fmod from ftp.uu.net, put it in the compat
- subdirectory, and added it to the Makefile. fmod also wanted
- functions 'isnan' and 'finite' but I just commented those out since
- I don't believe tcl supports infinity and nan.
-
- The other problem with the math library was that it has two copies
- of the 'tanh' function in it. This is easy to fix by using "ar" to
- separate the library in to object files and then reconstruct it,
- leaving one of the copies of tanh out.
-
- With those changes, Tcl compiled cleanly and passed all the tests
- except the scanning tests. Apparently, the *scanf functions are
- broken in Dynix. The problem is with recognizing the end of octal
- numbers, and I just let this problem go. Fixing it would probably
- involve finding source to the *scanf functions and including it.
-
- To compile Tk, I had to make a new version of stddef.h including
- things like wchar_t. I just copied it in to another include
- directory and put that directory first and then tweaked the copy. Tk
- also had the math library problem (tanh). Other than those, however,
- everything compiled cleanly and passed all the tests.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q45- How do I get around the symbol table full msg in AU/X 3.0?
-
- After getting things compiled on AU/X, you have to be sure to do the
- links with the -A {factor} arguments which expand the default table
- allocations. {factor} is the amount by which the compiler multiplies
- the default allocation. Try -A 2. Contact Walter B. Kulecz, PhD.
- (wkulecz@medics.jsc.nasa.gov) for more details of his port.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q46- How do I compile Tcl on MS-DOS, MacOS, or other non-UNIX
- system?
-
- Refer to Larry Virden's FAQ (see tcl-faq/part1) or (see tcl-faq/part4)
- for details concerning tools, finished ports, or mailing lists
- relating to this topic.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q47- How do I get Tcl to compile on my QNX system?
-
- Steve Furr (furr@qnx.com) indicates:
-
- For the record, to get TCL to work under QNX, I had to:
- * Make the _POSIX_SOURCE change indicated for pathname lengths
- * Change a definition of VARARGS, so the Watcom ANSI C compiler
- would accept varargs functions used.
- * Resolve a conflict with error codes defined by QNX.
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q48- Why do I get the error message "Command not found" when I
- try to run a Tcl script?
-
- The script probably starts with a #! that is followed by a path to the
- Tcl interpreter that is too long for your system. Many Unix systems
- are limited 32 characters in this regard. So, something like this will
- fail:
-
- #! /usr/home/homedir/very/long/path/tclsh
-
- # rest of script
-
- You can either shorten the path by moving the tclsh executable to a
- different directory or by using symbolic links. Another option is to
- not specify the path at all. See the question "How do I make my script
- executable regardless of the location of tclsh?" for an example of
- how to do this.
- _________________________________________________________________
-
- End of FAQ
-