From bloom-picayune.mit.edu!mintaka.lcs.mit.edu!olivea!uunet!spool.mu.edu!agate!sprite.Berkeley.EDU!ouster Wed Feb 19 15:06:22 EST 1992
Article: 297 of comp.lang.tcl
Path: bloom-picayune.mit.edu!mintaka.lcs.mit.edu!olivea!uunet!spool.mu.edu!agate!sprite.Berkeley.EDU!ouster
From: ouster@sprite.Berkeley.EDU (John Ousterhout)
Newsgroups: comp.lang.tcl
Subject: Re: tcl string delimiters & tk listbox
Message-ID: <kq550aINN8e8@agate.berkeley.edu>
Date: 19 Feb 92 17:29:46 GMT
References: <1992Feb18.211911.24904@rock.concert.net>
Organization: U.C. Berkeley Sprite Project
Lines: 73
NNTP-Posting-Host: tyranny.berkeley.edu

In article <1992Feb18.211911.24904@rock.concert.net>, whaley@jazz.concert.net (Jonathan Whaley) writes:
|> I have a tcl string evaluation problem I need help in working around.
|> 
|> I'm writing an array of strings from a shared memory segment into a
|> tk scrolling listbox widget.
|> 
|> The output in the widget should look like...
|> 
|> 43292244 C ) " D
|> 
|> that is a long plus the ascii characters that represent each part of the long.
|> 
|> Currently my code fragment looks like this...
|> 
|> /* painfully plug in each string into the listbox widget */
|> 
|> for ( i=0; ( i < p_dataptr->num_items); i++) {
|>         result = Tcl_VarEval(interp, ".Captured_Packet.frame.list insert end \""
|> , p_dataptr->captured_strings[i],"\"",(char *) NULL);
|>         if (result != TCL_OK) {
|>             fprintf(stderr, "%s\n", Tcl_GetVar(interp, "errorInfo", 1));
|>             exit(1);
|>         }
|> }
|> 
|> The problem is that I get the error:
|> unmatched quote: '=> "', while executing
|> """
|> 
|> whenever I encounter a quote inside the string I'm trying to put in the
|> listbox. The same thing of course happens if I try to change the group
|> delimiters to [] or { } instead of "".
|> 
|> Basically any one of the tcl delimiters may appear in the string I wish
|> to place into the listbox. Anyone have a way to solve this problem or
|> a better way to approach putting items in the listbox?
|> 
|> thanks...
|> Jonathan Whaley
|> whaley@concert.net
|> 

This is a common problem that people run into when generating Tcl commands.
The solution is to ensure that the command has proper "list" structure so
that when it's parsed by Tcl it will divide up into words in the way you'd
originally intended.  Fortunately, there are Tcl procedures to help with this.
In particular, the procedure Tcl_Merge should fix the above problem.  Try
the following code:

char *argv[4];
char *command;

argv[0] = ".Captured_Packet.frame.list";
argv[1] = "insert";
argv[2] = "end";
argv[3] = p_dataptr->captured_strings[i];
command = Tcl_Merge(4, argv);
result = Tcl_Eval(interp, command, 0, (char **) NULL);
free(command);

Tcl_Merge generates a string that is a valid list whose four elements
are the things in the argv array.  If the argv[3] includes special
characters like " or [, then Tcl_Merge adds backslashes or braces so
that the result will parse back to the original.  In contrast, Tcl_VarEval
just concatenates its arguments together.

Similar problems can occur when you're generating commands in Tcl scripts
instead of C programs.  In this case, use the "list" command to put together
a proper list instead of just concatenating strings.

The key thing to realize here is that commands are similar in structure to
lists so you can use the list-related commands in both C and Tcl code to
put together commands that will parse correctly.


