home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-03 | 47.0 KB | 1,400 lines |
- Newsgroups: comp.lang.tcl,comp.answers,news.answers
- Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!paperboy.osf.org!bone.think.com!blanket.mitre.org!agate!howland.reston.ans.net!newsfeed.internetmci.com!sgigate.sgi.com!sdd.hp.com!hp-pcd!hp-cv!reuter.cse.ogi.edu!gasco!qiclab.scn.rain.com!morton!joe
- From: joe@morton.rain.com (Joe Moss)
- Subject: FAQ: comp.lang.tcl Tcl Language Usage Questions And Answers
- Message-ID: <tcl-faq/usage-1-833672178@morton.rain.com>
- Followup-To: comp.lang.tcl
- Summary: Answers to common questions regarding the use of the
- Tcl language and building the Tcl interpreter
- Keywords: FAQ Tcl TclX
- Sender: joe@morton.rain.com (Joe Moss)
- Supersedes: <tcl-faq/usage-1-830936969@morton.rain.com>
- Reply-To: tcl-faq@morton.rain.com (Tcl Q&A FAQ Maintainer)
- Organization: Morton & Associates
- Date: Sat, 1 Jun 1996 23:36:21 GMT
- Approved: news-answers-request@MIT.EDU
- Expires: Sat, 6 Jul 1996 23:36:18 GMT
- Lines: 1380
- Xref: senator-bedfellow.mit.edu comp.lang.tcl:48787 comp.answers:19082 news.answers:73445
-
- 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.neosoft.com/languages/tcl (198.64.191.10) in the
- /languages/tcl/alcatel/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
- misunderstandings 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 maintained in HTML. It is then run
- through a script (written in Tcl, of course) to automagically generate
- the Index of Questions, number the questions, generate the URL list, 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 once a month.
-
- Last modified: Sat Jun 01 16:34:01 PDT 1996
- ---------------------------------------------------------------------------
-
- INDEX OF QUESTIONS:
-
- SECTION A - GENERAL INFORMATION:
- * Q.A1- Where can I get further info about Tcl?
- * Q.A2- Where can I find help getting Tcl to work on my machine?
- * Q.A3- How can I combine Tcl and C?
- * Q.A4- How do I combine several extensions to provide all the
- features I want?
- * Q.A5- What about dynamic loading?
- * Q.A6- How do I create a stand alone program in case Tcl isn't
- installed?
- * Q.A7- How do I make my script executable regardless of the location
- of tclsh?
- * Q.A8- Why isn't <some extension> part of the standard distribution?
-
- SECTION B - PROGRAMMING RELATED QUESTIONS AND ANSWERS:
- * Q.B1- How can I create/use association lists or property lists?
- * Q.B2- How can I generate a random number in Tcl?
- * Q.B3- How can I call one proc with the multi parameter value
- returned by another proc?
- * Q.B4- How can I pass an array into a proc?
- * Q.B5- How can I run an external command and read its output via a
- pipe?
- * Q.B6- How can I delete a procedure from within a script?
- * Q.B7- How can I get more than 7 digits of double precision?
- * Q.B8- How can I grab the command line when a non-built-in call is
- made?
- * Q.B9- How can I get or set an environment variable?
- * Q.B10- How can I use numbers with leading zeroes?
- * Q.B11- How can I find the command line arguments to my application?
- * Q.B12- I found a bug in the handling of comments!
- * Q.B13- How can I input and output binary data?
- * Q.B14- How can I trap signals, and perform other more Unix specific
- functions?
- * Q.B15- How can I do a double indirect? - Why doesn't $$var work?
- * Q.B16- How can I get quoted strings to work the way I want?
- * Q.B17- How can I share procedures between multiple tcl applications?
- * Q.B18- How can I get items inserted into a list?
- * Q.B19- How can I perform a non-blocking read on a file identifier?
- * Q.B20- How can I read and write from a pipe without locking up?
- * Q.B21- How can I find what version I am running?
- * Q.B22- How can I use variables to hold array names?
- * Q.B23- How can I make variables static, like in C?
- * Q.B24- How can I convert between a character and its ASCII value?
-
- SECTION C - EXPLANATION OF ERROR MESSAGES:
- * Q.C1- "not found" or "Command not found"
- * Q.C2- invalid command name "}"
- * Q.C3- missing close-brace
- * Q.C4- X server insecure (must use xauth-style authorization)
- * Q.C5- expected integer but got ...
- * Q.C6- "Undefined symbol: main" or similar
-
- SECTION D - COMPILING AND OTHER PLATFORM SPECIFIC QUESTIONS:
- * Q.D1- Why does "glob" cut off the first two characters of each
- filename?
- * Q.D2- How do I get Tcl working on MS Windows (3.1, 95, or NT)?
- * Q.D3- How can I build the Tcl library as a shared libary?
- ---------------------------------------------------------------------------
-
- GENERAL INFORMATION:
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A1- 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.neosoft.com in the /languages/tcl/alcatel/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.teraform.com/~lvirden/tcl-faq/
-
- Three other good starting points, if you are surfing the Web for
- information, are:
- http://www.sco.com/Technology/tcl/Tcl.html
- http://web.cs.ualberta.ca/~wade/HyperTcl/
- http://www.sunlabs.com/research/tcl/
-
- Of course, the source distribution itself includes a great deal of
- documentation. The latest version is 7.5. It can be obtained from:
- ftp://ftp.smli.com/pub/tcl/
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A2- 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).
-
- You should also check the on-line database of porting information
- available via the Sun Tcl/Tk Web pages.
-
- There are also some questions and answers related to building the
- interpreter on various platforms at the end of this document.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A3- 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.vnet.net/pub/users/drh/
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A4- 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 Tcl-my-fancy, 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 five
- of Larry Virden's FAQ for the location of these and other packages.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A5- What about dynamic loading?
-
- The current version of Tcl supports dynamic loading on many platforms.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A6- How do I create a stand alone program in case Tcl isn't
- installed?
-
- The "Plus" patches from Jan Nijtmans (nijtmans@nici.kun.nl) include a
- make target for building a standalone interpreter. See
- http://www.nici.kun.nl/tkpvm/pluspatch.html
-
- Additionally, 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.neosoft.com/languages/tcl/alcatel/code/wish_compiler.shar.g
- z
-
- 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 available is "Embedded Tk". You can get it from
- ftp://ftp.vnet.net/pub/users/drh/
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.A7- How do I make my script executable regardless of the
- location of tclsh?
-
- 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: Q.A8- 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 and later contain the
- equivalent functionality of the addinput and photo widget extensions
- that were written by others for Tcl 7.3/Tk 3.6.
- ---------------------------------------------------------------------------
-
- PROGRAMMING RELATED QUESTIONS AND ANSWERS:
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B1- 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: Q.B2- How can I generate a random number in Tcl?
-
- Extended Tcl includes a command named "random" that is an interface to
- the random number generator in the system's standard C library.
-
- For example, to generate a random number between 0 and 9 inclusive:
-
- set random_number [random 10]
-
- It also allows you to specify a seed value.
-
- To get a value you can use as a seed, you might try one or a combination
- of these (on Unix-like systems):
-
- [pid]
- [file atime /dev/kmem]
- [getclock] (Extended Tcl only)
-
- 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.
-
- Here is one that is syntax compatible with the one in Extended Tcl, but
- implemented in standard Tcl. The constants are from Don Libes. Be aware
- that there is little checking for valid arguments.
-
- proc random {args} {
- global RNG_seed
-
- set max 259200
- set argcnt [llength $args]
- if { $argcnt < 1 || $argcnt > 2 } {
- error "wrong # args: random limit | seed ?seedval?"
- }
- if ![string compare [lindex $args 0] seed] {
- if { $argcnt == 2 } {
- set RNG_seed [lindex $args 1]
- } else {
- set RNG_seed [expr \
- ([pid]+[file atime /dev/kmem])%$max]
- }
- return
- }
- if ![info exists RNG_seed] {
- set RNG_seed [expr ([pid]+[file atime /dev/kmem])%$max]
- }
- set RNG_seed [expr ($RNG_seed*7141+54773) % $max]
- return [expr int(double($RNG_seed)*[lindex $args 0]/$max)]
- }
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B3- 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: Q.B4- 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: Q.B5- 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: Q.B6- 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: Q.B7- 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: Q.B8- 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: Q.B9- 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: Q.B10- How can I use numbers with leading zeroes?
-
- In Tcl, numbers that start with a zero are interpreted as octal values
- (or hexadecimal, if the zero is immediately followed by an 'x'). Often,
- this is a useful feature, but there are some problems:
- * What if the number has invalid octal (hexadecimal) digits?
-
- Prior to Tcl 7.4b3, the interpreter would try to interpret a number
- such as 08 as a floating point value. Starting with 7.4b3, the
- interpreter generates an error message when presented with such a
- value.
- * What if you want the value interpreted as a decimal number (as if
- the leading zeros weren't there)?
-
- You have to strip off the zeros. Here are two possible
- implementations of a function "stripzeros":
-
- proc stripzeros {value} {
- regsub ^0+(.+) $value \\1 retval
- return $retval
- }
-
- or
-
- proc stripzeros {value} {
- set retval [string trimleft $value 0]
- if { ![string length $retval] } {
- return 0
- }
- return $retval
- }
-
- Then, whenever you are passing a value to a command that requires an
- integer value, and there is the possibility that the value has a
- leading zero, just pass it through this function first, i.e. instead
- of:
-
- set dayofweek [expr $days%7]
-
- use:
-
- set dayofweek [expr [stripzeros $days]%7]
-
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B11- 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: Q.B12- I found a bug in the handling of comments!
-
- Sometimes people find that Tcl behaves differently than they expect
- (often because of the way some other language acts in a similar
- situation). They then think this unexpected behavior is a bug. Probably
- the most common occurance of this is in regard to comments.
-
- In Tcl, everything passed to the parser must have proper list structure,
- even comments (and yes comments are passed to the parser, unlike in some
- languages where they are stripped at an earlier stage). Generally, this
- means you need to make sure your braces are evenly matched, even though
- they may be on a line that is commented out.
-
- So, for example, you have an "if" statement that tests a certain
- condition, but you want to try testing a different condition. You
- comment out the old condition and type a new "if" statement. This code
- will cause an error that there is a missing close-brace:
-
- ## WRONG
- if { $newflag } {
- # if { $oldflag } {
- puts hello
- }
-
- In this case, you have to balance the braces, for example:
-
- ## CORRECT
- if { $newflag } {
- # if { $oldflag } {
- puts hello
- # }
- }
-
- Another interesting point about comments in Tcl is that the line
- continuation mechanism still applies, so:
-
- # This is a comment line that ends with a backslash \
- and this line is still part of the comment
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B13- How can I input and output binary data?
-
- Internally, the Tcl interpreter stores nearly everything in
- null-terminated strings. This procludes the possibility of directly
- storing binary data (or more specifically, anything with embedded
- nulls).
-
- However, certain operations can be performed without the data being
- stored in Tcl variables. For example, file handles can be attached
- directly to external programs, like this:
-
- set infp [open "|compress -dc $fileName"]
-
- exec gzip -c $newFileName <@ $infp
-
- or in Extended Tcl:
-
- set infp [open "|compress -dc $fileName"]
- set outfp [open "|gzip -c $newFileName" w]
-
- copyfile $infp $outfp
-
- In Tcl 7.5, you can copy binary data between open channels using the
- command "unsupported0". However, as is indicated by the name, it is not
- a method which should be relied on - it will disappear in a future
- release, although proper support for handling binary data should be
- added at that time.
-
- Alternatively, you can in some way convert the data to a form that is
- usable from Tcl:
- * Reading from or writing to a pipe that is connected to an external
- filter, such as atob/btoa, uuencode/uudecode, or even od.
- * A method of handling binary data one character at a time using
- standard Tcl can be found in:
- ftp.neosoft.com:/languages/tcl/alcatel/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.
-
- Thanks to Wayne Throop throop@aur.alcatel.com for his contribution to
- this section.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B14- 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: Q.B15- 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 its 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
-
- Similarly, to print the values of `var1', `var2', and `var3':
-
- set var1 3.14159
- set var2 hello
- set var3 13
- foreach num {1 2 3} {
- puts "var$num = [set var$num]"
- }
-
- will output:
-
- var1 = 3.14159
- var2 = hello
- var3 = 13
-
- The "upvar" command can also be used to derefence variables.
-
- In addition, starting with version 7.4, the interpreter includes the
- command "subst" which can be used to perform substitutions.
-
- Note that all of the above applies to array variables also.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B16- 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.neosoft.com/languages/tcl/alcatel/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] $args"
- }
-
- 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: Q.B17- 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: Q.B18- 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: Q.B19- 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: Q.B20- 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 its 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: Q.B21- How can I find what version I am running?
-
- Well, there is no one answer to this. Tcl itself, will tell you its
- version, if you type:
-
- info tclversion
-
- or with recent versions:
-
- puts $tcl_version
-
- 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 its version number).
-
- Starting with the 7.4 version, the tclsh executable is, by default,
- installed with the version number appended - making it rather obvious
- which version you are running. However, if it is not installed like that
- on your system, you can find out the version from the shell prompt with
- something like:
-
- echo 'puts $tcl_version;exit 0' | tclsh
-
- (the ";exit 0" part is only needed for wish and its derivatives, but
- doesn't hurt anything when it isn't needed)
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B22- 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"
- }
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B23- How can I make variables static, like in C?
-
- The "static" keyword in C is used for different purposes. One of the
- most common is when you wish to have a variable that retains its value
- across invocations of the same function (but without making the variable
- globally available). Karl Lehenbauer (karl@NeoSoft.com) wrote the
- following procedure to emulate this behaviour:
-
- proc static {args} {
- set procName [lindex [info level -1] 0]
- foreach varName $args {
- uplevel 1 "upvar #0 staticvars($procName:$varName) $varName"
- }
- }
-
- Another common use, is when you want a global variable that is only
- visible to functions within that particular source file. This is best
- handled by a namespace facility. Tcl does not yet have a built-in
- namespace facility, but several extensions are available the provide
- one. See the software catalog in Larry's FAQ for more info.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.B24- How can I convert between a character and its ASCII value?
-
- To get the ASCII value of a character:
-
- proc toASCII { char } {
- scan $char %c value
- return $value
- }
-
- puts "The ASCII value of 'A' is [toASCII A]"
-
- To convert from an ASCII value to a character:
-
- proc toChar { value } {
- return [format %c $value]
- }
-
- puts "The ASCII value 65 corresponds to the character '[toChar 65]'"
-
- ---------------------------------------------------------------------------
-
- EXPLANATION OF ERROR MESSAGES:
-
- This section lists some error messages and some possible (and
- non-obvious) reasons why you may be getting them.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.C1- "not found" or "Command not found"
-
- This error message comes from your shell, not Tcl. 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 to 32
- characters (including the "#!") 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.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.C2- invalid command name "}"
-
- You have probably commented out a line that ends with an open curly
- brace. See Question B12 for more info.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.C3- missing close-brace
-
- Your braces aren't balanced. Again, one likely, though perhaps
- non-obvious, reason is improperly commented lines. See Question B12.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.C4- X server insecure (must use xauth-style authorization)
-
- Tk requires you to have a secure X server before you can use the send
- command. See the question 2.A.7 "How can I get Tk 3.3 to even start - I
- get security error messages." in Thomas Accardo's Tk Toolkit Usage FAQ
- as well as http://ce-toolkit.crd.ge.com/tkxauth/ for instructions on how
- to make your server secure.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.C5- expected integer but got ...
-
- This error occurs when trying to perform some mathematical operation
- that requires an integer value, but given a non-integer value. While
- this is pretty obvious when the value supplied is a floating point value
- or an alphabetic string, this error can be confusing when the value is
- something that may look like a valid integer. Specifically numbers that
- have leading zeros. See the question How can I use numbers with leading
- zeros? for an explanation.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.C6- "Undefined symbol: main" or similar
-
- If when linking an application you get an error saying that the "main"
- function was not found, it is probably because the application was
- written for a version of Tcl prior to Tcl 7.4 and you are linking it
- with version 7.4 (or later).
-
- Older versions of Tcl included a "main" function in the library
- ("libtcl.a"). This caused various problems, in particular with C++
- programs, and it was removed starting with version 7.4b1. The
- application being linked with the Tcl library must now provide the
- "main" routine itself.
- ---------------------------------------------------------------------------
-
- COMPILING AND OTHER PLATFORM SPECIFIC QUESTIONS:
-
- This section contains some hints on compiling the Tcl distribution on
- various platforms and other notes regarding platform specific problems.
-
- For building Tcl 7.4 and newer releases, there is now an on-line
- database, maintained by Sun, for people to query, if they have problems
- building the standard distribution. If the software did not build
- automatically for you, check at http://www.sunlabs.com/research/tcl/ for
- an entry regarding your platform. And please share your experience, if
- there is no current entry and you were able to get the distribution to
- build somehow.
-
- Notes that were previously listed here, but which apply primarily to
- older releases are now available in a separate document at:
- http://psg.com/~joem/tcl/PlatformNotes.html
-
- See also Question A2
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.D1- Why does "glob" cut off the first two characters of each
- filename?
-
- This problem can occur on SVR4, Solaris 2.x, and similar systems that
- have both System V and BSD libraries. It happens when the interpreter is
- compiled with include files that don't match the libraries to which it
- is linked (specifically, readdir returns a different structure than is
- expected). You need to modify the Makefile to make sure the include
- files correspond to the libraries.
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.D2- How do I get Tcl working on MS Windows (3.1, 95, or NT)?
-
- For Microsoft specific information see the FAQ maintained by Eric
- Johnson (ejohnson@camax.com). It is available at:
- http://ourworld.compuserve.com:80/homepages/efjohnson/tclwin.htm
-
-
- ------------------
-
- From: Tcl Q&A
- Subject: Q.D3- How can I build the Tcl library as a shared libary?
-
- This is now supported for some platforms in the standard distribution.
-
- You can also get the "Plus" patches, which include support for
- additional platforms. For more information, see
- http://www.nici.kun.nl/tkpvm/pluspatch.html
-
- Additionally, Extended Tcl includes instructions for building shared
- libraries on many Unix systems. You may be able to use this information,
- if your platform is not supported by the plus patches.
- ---------------------------------------------------------------------------
- End of FAQ
- ---
- set Email "joe@morton.rain.com (Joe Moss)";set URL http://psg.com/~joem/
- ======================================================================
- "Folk, if you are not checking the Frequently Asked Questions documents
- before you ask questions, you are taking longer to resolve problems,
- and annoying more folk, than necessary." -- Larry W. Virden
-