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@xxxxxxxxxxxxxx> --- 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); -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list