JasonBourne
JasonBourne

Reputation: 185

How to add a variable amount of arguments to exec in tcl?

I've been working with TCL for some time now, and I have spent a long time trying to do the following (it seems easy and I think it should be, but I can't get it right):

I need to execute an external program by means of a tcl script. For that, I use the exec command. For using this external program, I need to input a variable amount of files. If I called this program straight from a cmd window, it would be something like:

C:\>myprogram -i file1 -i file2 -i file3 (etc., etc.)

However, when trying to implement this in a dynamic/variable way through tcl I get into trouble. The way I do it is by storing in some variable myvar all the "-i filex" I need (done in a loop), and then pass that as a parameter to the exec command. It would look something like:

exec myprogram $myvar

Doing that apparently creates some issues, because this myprogram fails to "see" myvar. I'm guessing that there is some sort of hidden terminator or some clash of different types of arguments that makes that in the end the exec command "sees" only myprogram.

So, my question is, does anyone know how to insert variable arguments into a call to exec?

Upvotes: 9

Views: 5141

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137557

Specializing for your case:

Tcl 8.5 (and later):

exec myprogram {*}$myvar

Tcl 8.4 (and before):

eval [list exec myprogram] [lrange $myvar 0 end]
# Or...
eval [linsert $myvar 0 exec myprogram]

That's right, the old version is ugly (or non-obvious, or both). Because of that, people tended to write this instead:

eval exec myprogram $myvar

but that was slower than expected (OK, not so relevant when running an external program!) and has hazards when $myvar isn't a canonically-formatted list due to the way that eval works. It used to catch out even experienced Tcl programmers, and that's why we introduced new syntax in 8.5, which is specified to be surprise-free and is pretty short too.

Upvotes: 7

TrojanName
TrojanName

Reputation: 5355

You can use {*} or eval. See this question for example.

Upvotes: 10

Related Questions