add vrshCommandParser and make vshCommandParse() accepts different
parsers.
the current code for parse command string is integrated as
vshCommandStringParse().
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
virsh.c | 91 +++++++++++++++++++++++++++++++---------------------------------
1 file changed, 45 insertions(+), 46 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index f97ee42..27321a5 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -10158,23 +10158,29 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
return ret;
}
+#define VSH_TK_ERROR -1
+#define VSH_TK_ARG 0
+#define VSH_TK_SUBCMD_END 1
+#define VSH_TK_END 2
+
+typedef struct __vshCommandParser {
+ int (*getNextArg)(vshControl *, struct __vshCommandParser *, char **);
+ char *pos;
+} vshCommandParser;
+
+static int vshCommandParse(vshControl *ctl, vshCommandParser *parser);
+
/* ---------------
* Command string parsing
* ---------------
*/
-#define VSH_TK_ERROR -1
-#define VSH_TK_NONE 0
-#define VSH_TK_DATA 1
-#define VSH_TK_END 2
static int
-vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
+vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
{
bool double_quote = false;
int sz = 0;
- char *p = str, *q;
-
- *end = NULL;
+ char *p = parser->pos, *q;
while (p && *p && (*p == ' ' || *p == '\t'))
p++;
@@ -10182,8 +10188,8 @@ vshCommandGetToken(vshControl *ctl, char *str, char **end, char
**res)
if (p == NULL || *p == '\0')
return VSH_TK_END;
if (*p == ';') {
- *end = ++p; /* = \0 or begin of next command */
- return VSH_TK_END;
+ parser->pos = ++p; /* = \0 or begin of next command */
+ return VSH_TK_SUBCMD_END;
}
q = p;
@@ -10218,14 +10224,25 @@ copy:
}
*(*res + sz) = '\0';
- *end = p;
- return VSH_TK_DATA;
+ parser->pos = p;
+ return VSH_TK_ARG;
+}
+
+static int vshCommandStringParse(vshControl *ctl, char *cmdstr)
+{
+ vshCommandParser parser;
+
+ if (cmdstr == NULL || *cmdstr == '\0')
+ return FALSE;
+
+ parser.pos = cmdstr;
+ parser.getNextArg = vshCommandStringGetArg;
+ return vshCommandParse(ctl, &parser);
}
static int
-vshCommandParse(vshControl *ctl, char *cmdstr)
+vshCommandParse(vshControl *ctl, vshCommandParser *parser)
{
- char *str;
char *tkdata = NULL;
vshCmd *clast = NULL;
vshCmdOpt *first = NULL;
@@ -10235,44 +10252,27 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
ctl->cmd = NULL;
}
- if (cmdstr == NULL || *cmdstr == '\0')
- return FALSE;
-
- str = cmdstr;
- while (str && *str) {
+ for (;;) {
vshCmdOpt *last = NULL;
const vshCmdDef *cmd = NULL;
- int tk = VSH_TK_NONE;
+ int tk;
int data_ct = 0;
first = NULL;
- while (tk != VSH_TK_END) {
- char *end = NULL;
+ for (;;) {
const vshCmdOptDef *opt = NULL;
tkdata = NULL;
+ tk = parser->getNextArg(ctl, parser, &tkdata);
- /* get token */
- tk = vshCommandGetToken(ctl, str, &end, &tkdata);
-
- str = end;
-
- if (tk == VSH_TK_END) {
- VIR_FREE(tkdata);
- break;
- }
if (tk == VSH_TK_ERROR)
goto syntaxError;
+ if (tk != VSH_TK_ARG)
+ break;
if (cmd == NULL) {
/* first token must be command name */
- if (tk != VSH_TK_DATA) {
- vshError(ctl,
- _("unexpected token (command name):
'%s'"),
- tkdata);
- goto syntaxError;
- }
if (!(cmd = vshCmddefSearch(tkdata))) {
vshError(ctl, _("unknown command: '%s'"), tkdata);
goto syntaxError; /* ... or ignore this command only? */
@@ -10299,11 +10299,10 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
if (optstr)
tkdata = optstr;
else
- tk = vshCommandGetToken(ctl, str, &end, &tkdata);
- str = end;
+ tk = parser->getNextArg(ctl, parser, &tkdata);
if (tk == VSH_TK_ERROR)
goto syntaxError;
- if (tk != VSH_TK_DATA) {
+ if (tk != VSH_TK_ARG) {
vshError(ctl,
_("expected syntax: --%s <%s>"),
opt->name,
@@ -10320,7 +10319,7 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
goto syntaxError;
}
}
- } else if (tk == VSH_TK_DATA) {
+ } else {
if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
vshError(ctl, _("unexpected data '%s'"), tkdata);
goto syntaxError;
@@ -10347,8 +10346,6 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
opt->type != VSH_OT_BOOL ? _("optdata") :
_("bool"),
opt->type != VSH_OT_BOOL ? arg->data :
_("(none)"));
}
- if (!str)
- break;
}
/* command parsed -- allocate new struct for the command */
@@ -10370,6 +10367,9 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
clast->next = c;
clast = c;
}
+
+ if (tk == VSH_TK_END)
+ break;
}
return TRUE;
@@ -10385,7 +10385,6 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
return FALSE;
}
-
/* ---------------
* Misc utils
* ---------------
@@ -11086,7 +11085,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
strncat(cmdstr, " ", sz--);
}
vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr);
- ret = vshCommandParse(ctl, cmdstr);
+ ret = vshCommandStringParse(ctl, cmdstr);
VIR_FREE(cmdstr);
return ret;
@@ -11165,7 +11164,7 @@ main(int argc, char **argv)
#if USE_READLINE
add_history(ctl->cmdstr);
#endif
- if (vshCommandParse(ctl, ctl->cmdstr))
+ if (vshCommandStringParse(ctl, ctl->cmdstr))
vshCommandRun(ctl, ctl->cmd);
}
VIR_FREE(ctl->cmdstr);