tags:

views:

119

answers:

1

Is there a way to (ab)use the tcl C-API to 'parse' a string, doing all the replacement (including sub commands in square brackets), but stopping before actually evaluating the resulting command line?

What I'm trying to do is create a command (in C, but I'll consider doing a tcl-wrapper, if there's an elegant way to do it there) which takes a block as a parameter (i.e. curly-braces-quoted-string). I'd like to take that block, split it up and perform substitutions in the same way as if it was to be executed, but stop there and interpret the resulting lines instead.

I've considered creating a namespace, where all valid first-words are defined as commands, however this list is so vast (and pretty much dynamic) so it quickly becomes too cumbersome. I also tried this approach but with the unknown command to intercept the different commands. However, unknown is used for a bunch of stuff, and cannot be bound to a namespace, so I'd have to define it whenever I execute the block, and set it back to whatever it was before when I'm done, which feels pretty shaky. On top of that I'd run the risk (fairly low risk, but not zero) of colliding with an actual command, so I'd very much prefer to not use the unknown command.

The closest I can get is Tcl_ParseCommand (and the rest of the family), which produces a parse tree, which I could manually evaluate. I guess I'll resort to doing it this way if there's no better solution, but I would of course prefer it, if there was an 'official' way..

Am I missing something?

+2  A: 

Take a look at Tcl_SubstObj. It's the C equivalent of the [subst] command, which appears to be what you're looking for.

As you indicated in your comment, subst doesn't quite do what you're looking to do. If it helps, the following Tcl code may be what you're looking for:

> set mydata {mylist item $listitem group item {$group item}}
> set listitem {1 2 3}
> subst $mydata      ;# error: can't read "group": no such variable
> proc groupsubst {data} {
    return [uplevel 1 list $data]
}
> groupsubst $mydata ;# mylist item {1 2 3} group item {$group item}
RHSeeger
Good suggestion, the only problem with it is that it'll disregard curly-braces, I'll see if I can make some use of it...
roe
that's one creative use of uplevel.. :) It's equivalent to eval [concat list $mydata], good idea though, thanks!
roe
The code inside the proc is equivalent. The proc itself uses uplevel specifically to make sure that code/variable substitution happens at the stack level it was called from. You couldn't use [eval [concat ...]] inside my proc and get the same results.
RHSeeger