Version 27 of escargo

Updated 2005-09-26 23:55:35

The often used screen name for David S. Cargo ([email protected] and [email protected]). My home IP address is often 199.86.45.178 (from home) or 207.250.72.2 (from work), and will appear when looking at Recent Changes.

Updated slightly on 05/05/05 since it's such a funny date.

Initials? Why would I prefer to use initials with a handle like this?

I have been coding in tcl, tk, and expect since 1996.

For a few years I was a Multics [L1 ] user, and have also used (in ancient times) CP/M-80, MS-DOS, VAX VMS, TOPS-10, old Honeywell minicomputer systems, ModComp Systems.

More recently I have used CrayOS, Solaris, Microsoft Windows (starting at 3.1), and Linux.

I did manage to attend the Tcl 2002 conference in Vancouver. Very nice.


I have started a few pages, including one with an application:

and others more philosophical


For $25/yr you can be [email protected].

(That's the yearly membership for slug.org) PSE


For not much more than that I can get my own domain name. I'm not sure a snail should be consorting with slugs. They are fellow mollusks, but still....


Pet Peeves

I may wind up doing some minor editorial (copyediting) changes to wiki pages that I see that have the following problems.

  • The use of "it's" instead of "its" (where the possessive is intended)
  • The use of "its" instead of "it's" (where the contraction is intended)
  • The use of "lets" instead of "let's" (where the contraction is appropriate)
  • The use of "which" instead of "that" (nonrestrictive versus restrictive)
  • Misspellings ("alot")

I won't mark these changes since I don't think they will change the meaning.

EKB I support you in this effort, but mention that the rules for "which" vs. "that" are different in the UK and the US.

escargo I know that, so I like to check to see which kind of quotations might be used (single versus double quotation marks) to guess which kind of localization needs to be done.

My tendencies toward punctuation correction have led two different people to each give me a copy of Eats, Shoots & Leaves: The Zero Tolerance Approach to Punctuation, by Lynne Truss.


My Current Puzzle

May the source be with you...

I'm trying to develop an application that can, among other functions, read and process Tcl commands from a file. I want to log operations (using the tcllib logger package). Ideally, legal Tcl would be processed in a way equivalent to the source command. However, I'm seeing interesting differences.

First, some legal operations (to be stored in a file named test.tcl):


 proc requireOperation {service operation} {
     if {[string trim $operation] eq ""} {
         puts "blank operation"
     }
     return 1
 }

 set ops [list operation1 operation2 operation3 operation4]

 set service someService
 foreach op $ops {
     requireOperation $service $op
 }
 # This should be the equivalent of the code above.
 set ops [list \
              operation1 \
              operation2 \
              operation3 \
              operation4]

 foreach op $ops {
     requireOperation $service $op
 }

To run this code, you must first do

 package require logger
 set log [logger::init test]

 source process_file.tcl
 process_file $log test.tcl

This is the code that has the problem somewhere:


 # process_file.tcl - This file contains procs for executing files or
 # lists of Tcl commands.  Errors are caught and reported.  Execution
 # is not terminated at this level.  If execution is terminated, it
 # will happen at the logging proc level.

 # logObj - a logger object to use for logging
 # fileName - the name of the file to execute commands from
 # This proc reads the entire file before processing starts.
 # It does not finely diagnose why a file cannot be read.
 proc process_file {logObj fileName} {
     ${logObj}::info "Opening $fileName"
     if {[catch {open $fileName} handle]} {
         ${logObj}::critical "Failure opening $fileName"
         set result 1
     } else {
         set result 0
         set contents [read $handle [file size $fileName]]
         close $handle
        # This was added to solve one problem but it might have created another.
         set contents [string map [list "\\\n" ""] $contents]
         set listOfLines [split $contents \n] 
         runCommands $logObj $listOfLines
     }
     return $result
 }

 # logObj - a logger object to use for logging
 # listOfLines - a list containing a sequence of lines to execute
 # The proc does not care where the lines came from.
 proc runCommands {logObj listOfLines} {
     set n [llength $listOfLines]
     ${logObj}::debug "runCommands passed $n lines."
     set command ""
     # Using for so that lines are counted.
     for {set i 0} {$i < $n} {incr i} {
         set line [lindex $listOfLines $i]
         ${logObj}::debug "Line $i: $line"
         append command $line
         # Allow manual exit of this loop without a real EOF signal.
         if {$command eq "EOF"} {
             break
         } elseif {[info complete $command]} {
             runOneCommand $logObj $command
             set command ""
         }
     }
 }

 # logObj - a logger object to use for logging
 # command - the command to execute
 # This proc is only supposed to be called when "info complete"
 # says that there is a complete command.  However, that is true
 # for the empty string and even a list of empty strings.
 # Don't bother to safeguard against those for now.
 proc runOneCommand {logObj command} {
     global errorInfo
     # Execute command at global level.
     ${logObj}::info "Executing $command."
     if {[catch {uplevel \#0 $command} result]} {
         puts [set errorInfo]
         ${logObj}::error "Error executing $command: [set errorInfo]"
     } else {
         puts $result
     }
 }

The problem seems to result in confused tokenization of the processed code. I get messages like:

 wrong # args:  extra words after "else" clause in "if" command

It seems like this ought to be simple, but it's not.

RJ I think I see what is happening. Here is what listOfLines ends up looking like when passed to the next proc:

  \ proc\ requireOperation\ \{service\ operation\}\ \{ \ \ \ \ \ if\ \{\[string\ trim\ \$operation\]\ ==\ \"\"\}\ \{ {    puts "blank operation"} \ \ \ \ \ \} {     return 1} \ \} {} { set ops [list operation1 operation2 operation3 operation4]} {} { set service someService} \ foreach\ op\ \$ops\ \{ {     requireOperation $service $op} \ \} {}

See if command page - if the if command appears on a single line and ends in a continuation "\" it expects the next line to start with 'else'.


Messages to escargo:

  • Zarutian 2005-07-25-15:34 meet me on the tclers' chat.
  • Zarutian 2005-07-25-16:07 well, I have to go off the chat for now but I will probably be on it again between 23:00 GMT and 00:00 GMT tonight.
  • Sorry; I don't chat, but feel free to send me e-mail at the addresses above.

Category Person