www.gibmonks.com

  Previous section   Next section

Practical Programming in Tcl & Tk, Third Edition
By Brent B. Welch

Table of Contents
Chapter 40.  Send


The Sender Script

The following example is a general-purpose script that reads input and then sends it to another application. You can put this at the end of a pipeline to get a loopback effect to the main application, although you can also use fileevent for similar effects. One advantage of send over fileevent is that the sender and receiver can be more independent. A logging application, for example, can come and go independently of the applications that log error messages:

Example 40-1 The sender application.
#!/usr/local/bin/wish
# sender takes up to four arguments:
# 1) the name of the application to send to.
# 2) a command prefix.
# 3) the name of another application to notify
#    after the end of the data.
# 4) the command to use in the notification.

# Hide the unneeded window
wm withdraw .
# Process command line arguments
if {$argc == 0} {
   puts stderr "Usage: send name ?cmd? ?uiName? ?uiCmd?"
   exit 1
} else {
   set app [lindex $argv 0]
}
if {$argc > 1} {
   set cmd [lindex $argv 1]
} else {
   set cmd Send_Insert
}
if {$argc > 2} {
   set ui [lindex $argv 2]
   set uiCmd Send_Done
}
if {$argc > 3} {
   set uiCmd [lindex $argv 3]
}
# Read input and send it to the logger
while {[gets stdin input] >= 0} {
   # Ignore errors with the logger
   catch {send $app [concat $cmd [list $input\n]]}
}
# Notify the controller, if any
if [info exists ui] {
   if [catch {send $ui $uiCmd}msg] {
      puts stderr "send.tcl could not notify $ui\n$msg"
   }
}
# This is necessary to force wish to exit.
exit

The sender application supports communication with two processes. It sends all its input to a primary "logging" application. When the input finishes, it can send a notification message to another "controller" application. The logger and the controller could be the same application.

graphics/tip_icon.gif

Use list to quote arguments to send.


Consider the send command used in the example:

send $app [concat $cmd [list $input\n]]

The combination of concat and list is tricky. The list command quotes the value of the input line. This quoted value is then appended to the command, so it appears as a single extra argument. Without the quoting by list, the value of the input line will affect the way the remote interpreter parses the command. Consider these alternatives:

send $app [list $cmd $input]

This form is safe, except that it limits $cmd to a single word. If cmd contains a value like the ones given below, the remote interpreter will not parse it correctly. It will treat the whole multiword value as the name of a command:

.log insert end
.log see end ; .log insert end

This is the most common wrong answer:

send $app $cmd $input

The send command concatenates $cmd and $input together, and the result will be parsed again by the remote interpreter. The success or failure of the remote command depends on the value of the input data. If the input included Tcl syntax like $ or [ ], errors or other unexpected behavior would result.


      Previous section   Next section
    Top