On 10/12/2010 01:13 AM, Lai Jiangshan wrote:
In origin code, double quote is only allowed at the begin or end
"complicated argument"
--some_opt="complicated string" (we split this argument into 2 parts,
option and data, the data is "complicated string").
This patch makes it allow double quote at any position of
an argument:
complicated" argument"
complicated" "argument
--"some opt=complicated string"
This patch is also needed for the following patches,
the following patches will not split option argument into 2 parts,
so we have to allow double quote at any position of an argument.
Signed-off-by: Lai Jiangshan<laijs(a)cn.fujitsu.com>
I had to add your name to AUTHORS to make syntax-check happy.
---
diff --git a/tools/virsh.c b/tools/virsh.c
index 57ea618..7b6f2b6 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -10172,9 +10172,9 @@ static int
vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
{
int tk = VSH_TK_NONE;
- int quote = FALSE;
+ bool double_quote = false;
int sz = 0;
- char *p = str;
+ char *p = str, *q;
Maybe it's just me, but I tend to declare multiple pointers on separate
lines. But no big deal.
- } else if (quote&& *p == '"') {
- quote = FALSE;
+ }
+
+ if (*p == '"') {
'make syntax-check' would have caught this TAB.
+ double_quote = !double_quote;
p++;
- break; /* end of "..." token */
+ continue;
}
+
+ if (*res)
+ (*res)[sz] = *p;
That's a lot of indirection, for every byte of the loop. Wouldn't it be
better to have a local temporary, and only assign to *res at the end?
p++;
sz++;
}
- if (quote) {
+ if (double_quote) {
vshError(ctl, "%s", _("missing \""));
return VSH_TK_ERROR;
}
@@ -10231,8 +10234,12 @@ vshCommandGetToken(vshControl *ctl, char *str, char **end, char
**res)
if (sz == 0)
return VSH_TK_END;
- *res = vshMalloc(ctl, sz + 1);
- memcpy(*res, tkstr, sz);
+ if (!*res) {
+ *res = vshMalloc(ctl, sz + 1);
+ sz = 0;
+ p = q;
+ goto copy;
+ }
Hmm, a backwards jump, which means we parse every string twice - once to
figure out how long it is, and again to strip quotes. Yes, that avoids
over-allocating, but are we really that tight on memory? I find it
quicker to just strdup() up front, then edit in-place on a single pass.
Hmm, one thing you _don't_ recognize is:
-"-"option
as an option. In the shell, quotes are stripped before arguments are
recognized as a particular token. I think that's pretty easy to support
- delay VSH_TK_OPTION checking until after we've stripped quotes, but
I'll show it as a separate patch.
Hmm, I also noticed that we're inconsistent on strdup/vshStrdup in this
file; separate cleanup patch for that coming up soon.
But, with those nits fixed, ACK. Here's what I'm squashing in to my
local tree; I'll push it once I complete my review of your other 7
patches, as well as getting approval to my promised followup patches.
diff --git i/AUTHORS w/AUTHORS
index 09169f2..a8f96df 100644
--- i/AUTHORS
+++ w/AUTHORS
@@ -129,6 +129,7 @@ Patches have also been contributed by:
diff --git i/tools/virsh.c w/tools/virsh.c
index 0a28c99..4f70724 100644
--- i/tools/virsh.c
+++ w/tools/virsh.c
@@ -10124,16 +10124,18 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
#define VSH_TK_DATA 2
#define VSH_TK_END 3
-static int
+static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
{
int tk = VSH_TK_NONE;
bool double_quote = false;
int sz = 0;
- char *p = str, *q;
+ char *p = str;
+ char *q = vshStrdup(ctl, str);
char *tkstr = NULL;
*end = NULL;
+ *res = q;
while (p && *p && (*p == ' ' || *p == '\t'))
p++;
@@ -10145,9 +10147,6 @@ vshCommandGetToken(vshControl *ctl, char *str,
char **end, char **res)
return VSH_TK_END;
}
- q = p;
- *res = NULL;
-copy:
while (*p) {
/* end of token is blank space or ';' */
if (!double_quote && (*p == ' ' || *p == '\t' || *p ==
';'))
@@ -10170,34 +10169,23 @@ copy:
tkstr = p; /* begin of token */
}
- if (*p == '"') {
+ if (*p == '"') {
double_quote = !double_quote;
p++;
continue;
}
- if (*res)
- (*res)[sz] = *p;
- p++;
+ *q++ = *p++;
sz++;
}
if (double_quote) {
vshError(ctl, "%s", _("missing \""));
return VSH_TK_ERROR;
}
- if (tkstr == NULL || *tkstr == '\0' || p == NULL)
- return VSH_TK_END;
- if (sz == 0)
+ if (tkstr == NULL || *tkstr == '\0' || sz == 0)
return VSH_TK_END;
- if (!*res) {
- *res = vshMalloc(ctl, sz + 1);
- sz = 0;
- p = q;
- goto copy;
- }
- *(*res + sz) = '\0';
-
+ *q = '\0';
*end = p;
return tk;
}
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library
http://libvirt.org