modern Tcl and correct quoting

Poor Yorick org.macosforge.lists.macports-dev at pooryorick.com
Thu Jun 13 06:42:31 PDT 2013


On Thu, Jun 13, 2013 at 08:43:07PM +1000, Joshua Root wrote:
> On 2013-6-13 14:07 , Poor Yorick wrote:
> > Here's another example from the patch.  The original version looks like this:
> > 
> > 	if {[catch {eval curl fetch $verboseflag {$source} {$tarpath}} error]} {
> > 		...
> > 	}
> > 
> > Taking a look at just the [eval] part:
> > 
> > 	eval curl fetch $verboseflag {$source} {$tarpath}
> > 
> > The curly brackets around {$source} and {$tarpath} are there to escape
> > substitution as Tcl prepares to invoke [eval], and this is not necessarily
> > incorrect, but there are some caveats. $verboseflag is resolved prior to the
> > invocation of [eval], but $source and $tarpath are passed as literal strings.
> > If $verboseflag is "yes", [eval] will get exactly five values as arguments:
> > 
> > 	curl
> > 
> > 	fetch
> > 
> > 	yes
> > 
> > 	$source
> > 
> > 	$tarpath
> > 
> > It will then concatenate these arguments into a script which it will then pass to the interpreter:
> > 
> > 	curl fetch yes $source $tarpath
> > 
> > $source and $tarpath have not been resolved yet.  As it prepares to execute
> > [curl], the the interpreter will resolve them, and [curl] will receive exactly
> > 4 arguments.
> 
> $verboseflag is actually either empty or "-v". The intent of the
> existing code is that curl will get only 3 arguments when $verboseflag
> is empty. If it weren't for this, the eval could be omitted entirely, right?
> 
> So actually using list will change the behaviour by passing the empty
> string as an arg.
> 

In that case, the original code is correctly employing double substitution,
exactly as you describe.  It could also be written like this:

    eval curl fetch $verboseflag {$source $tarpath}

Or, some microseconds could be shaved by avoiding eval:

    if {$verboseflag eq {}} {
        curl fetch $source $tarpath
    } else {
        curl fetch $berboseflag $source $tarpath
    }

If we weren't writing to Tcl 8.4, we could do this:

    curl {*}$verboseflag $source $tarpath

-- 
Yorick


More information about the macports-dev mailing list