[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] runtest: Allow multi-word arguments
From: |
Jacob Bachmeyer |
Subject: |
Re: [PATCH] runtest: Allow multi-word arguments |
Date: |
Thu, 20 Apr 2023 21:48:34 -0500 |
User-agent: |
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1.22) Gecko/20090807 MultiZilla/1.8.3.4e SeaMonkey/1.1.17 Mnenhy/0.7.6.0 |
Christoph Muellner wrote:
From: Christoph Müllner <christoph.muellner@vrull.eu>
A recent change (5fafcd43) introduced a command line argument cache,
that ensures that command line arguments have a higher priority
than configuration files.
That cache uses the following code to save and restore:
save_cmd_var:
upvar 1 $name target_var
restore_cmd_vars"
uplevel 1 set $name $value
This works well unless $value becomes a multi-word string
(i.e. a string that contains spaces), because in this case
the command becomes:
uplevel 1 set $name arg-word0 arg-word1 ...
Obviously this will trigger the following error:
wrong # args: should be "set varName ?newValue?"
Quoting "$value" does not help, because the quotes are evaluated before
executing set.
I believe that a bit more explanation is needed, because this
description evidences a fundamental misunderstanding of Tcl's evaluation
rules. The command actually becomes:
uplevel 1 {set} {NAME} {ARG-WORD0 ARG-WORD1 ...}
... because Tcl, unlike the shell, does *not* perform word-splitting
after substituting variables. The problem is that uplevel performs an
implicit eval on its arguments, which has the effect of stripping one
layer of grouping, so the command actually executed in the caller's
context becomes:
set NAME ARG-WORD0 ARG-WORD1 ...
... which, as you correctly note, fails with a Tcl error. The solution
is to wrap the command passed to uplevel in one extra layer of grouping
using the Tcl list command, as documented in the eval(n) manpage: "Note
that the list command quotes sequences of words in such a way that they
are not further expanded by the eval command." Now the command becomes:
uplevel 1 {{set} {NAME} {ARG-WORD0 ARG-WORD1 ...}}
... which, when evaluated in the caller's context becomes:
set NAME {ARG-WORD0 ARG-WORD1 ...}
... which is correct and restores the list value for variable NAME.
This issue has been assigned bug number 62982 and is fixed in commit
c298959ef991b389b64a825f70094738c6a48780, which is now available in Git
master on Savannah and will be included in the next release. The
DejaGnu testsuite has been improved to now detect both the issue itself
and the error introduced in the original patch offered.
-- Jacob