1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

virsh: add vshCommandParser abstraction

add vshCommandParser and make vshCommandParse() accept different
parsers.

the current code for parse command string is integrated as
vshCommandStringParse().

Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
This commit is contained in:
Lai Jiangshan 2010-10-12 15:13:50 +08:00 committed by Eric Blake
parent 4417f08de4
commit a93f514f5f

@ -10325,30 +10325,40 @@ vshCommandRun(vshControl *ctl, const vshCmd *cmd)
* Command string parsing * 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 ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) typedef enum {
vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res) VSH_TK_ERROR, /* Failed to parse a token */
VSH_TK_ARG, /* Arbitrary argument, might be option or empty */
VSH_TK_SUBCMD_END, /* Separation between commands */
VSH_TK_END /* No more commands */
} vshCommandToken;
typedef struct __vshCommandParser {
vshCommandToken (*getNextArg)(vshControl *, struct __vshCommandParser *,
char **);
char *pos;
} vshCommandParser;
static int vshCommandParse(vshControl *ctl, vshCommandParser *parser);
static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res)
{ {
bool double_quote = false; bool double_quote = false;
int sz = 0; int sz = 0;
char *p = str; char *p = parser->pos;
char *q = vshStrdup(ctl, str); char *q = vshStrdup(ctl, p);
*end = NULL;
*res = q; *res = q;
while (p && *p && (*p == ' ' || *p == '\t')) while (*p && (*p == ' ' || *p == '\t'))
p++; p++;
if (p == NULL || *p == '\0') if (*p == '\0')
return VSH_TK_END; return VSH_TK_END;
if (*p == ';') { if (*p == ';') {
*end = ++p; /* = \0 or begin of next command */ parser->pos = ++p; /* = \0 or begin of next command */
return VSH_TK_END; return VSH_TK_SUBCMD_END;
} }
while (*p) { while (*p) {
@ -10371,14 +10381,25 @@ vshCommandGetToken(vshControl *ctl, char *str, char **end, char **res)
} }
*q = '\0'; *q = '\0';
*end = p; parser->pos = p;
return VSH_TK_DATA; 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 static int
vshCommandParse(vshControl *ctl, char *cmdstr) vshCommandParse(vshControl *ctl, vshCommandParser *parser)
{ {
char *str;
char *tkdata = NULL; char *tkdata = NULL;
vshCmd *clast = NULL; vshCmd *clast = NULL;
vshCmdOpt *first = NULL; vshCmdOpt *first = NULL;
@ -10388,44 +10409,27 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
ctl->cmd = NULL; ctl->cmd = NULL;
} }
if (cmdstr == NULL || *cmdstr == '\0') while (1) {
return FALSE;
str = cmdstr;
while (str && *str) {
vshCmdOpt *last = NULL; vshCmdOpt *last = NULL;
const vshCmdDef *cmd = NULL; const vshCmdDef *cmd = NULL;
int tk = VSH_TK_NONE; vshCommandToken tk;
int data_ct = 0; int data_ct = 0;
first = NULL; first = NULL;
while (tk != VSH_TK_END) { while (1) {
char *end = NULL;
const vshCmdOptDef *opt = NULL; const vshCmdOptDef *opt = NULL;
tkdata = 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) if (tk == VSH_TK_ERROR)
goto syntaxError; goto syntaxError;
if (tk != VSH_TK_ARG)
break;
if (cmd == NULL) { if (cmd == NULL) {
/* first token must be command name */ /* 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))) { if (!(cmd = vshCmddefSearch(tkdata))) {
vshError(ctl, _("unknown command: '%s'"), tkdata); vshError(ctl, _("unknown command: '%s'"), tkdata);
goto syntaxError; /* ... or ignore this command only? */ goto syntaxError; /* ... or ignore this command only? */
@ -10452,11 +10456,10 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
if (optstr) if (optstr)
tkdata = optstr; tkdata = optstr;
else else
tk = vshCommandGetToken(ctl, str, &end, &tkdata); tk = parser->getNextArg(ctl, parser, &tkdata);
str = end;
if (tk == VSH_TK_ERROR) if (tk == VSH_TK_ERROR)
goto syntaxError; goto syntaxError;
if (tk != VSH_TK_DATA) { if (tk != VSH_TK_ARG) {
vshError(ctl, vshError(ctl,
_("expected syntax: --%s <%s>"), _("expected syntax: --%s <%s>"),
opt->name, opt->name,
@ -10473,7 +10476,7 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
goto syntaxError; goto syntaxError;
} }
} }
} else if (tk == VSH_TK_DATA) { } else {
if (!(opt = vshCmddefGetData(cmd, data_ct++))) { if (!(opt = vshCmddefGetData(cmd, data_ct++))) {
vshError(ctl, _("unexpected data '%s'"), tkdata); vshError(ctl, _("unexpected data '%s'"), tkdata);
goto syntaxError; goto syntaxError;
@ -10500,8 +10503,6 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"), opt->type != VSH_OT_BOOL ? _("optdata") : _("bool"),
opt->type != VSH_OT_BOOL ? arg->data : _("(none)")); opt->type != VSH_OT_BOOL ? arg->data : _("(none)"));
} }
if (!str)
break;
} }
/* command parsed -- allocate new struct for the command */ /* command parsed -- allocate new struct for the command */
@ -10523,6 +10524,9 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
clast->next = c; clast->next = c;
clast = c; clast = c;
} }
if (tk == VSH_TK_END)
break;
} }
return TRUE; return TRUE;
@ -10538,7 +10542,6 @@ vshCommandParse(vshControl *ctl, char *cmdstr)
return FALSE; return FALSE;
} }
/* --------------- /* ---------------
* Misc utils * Misc utils
* --------------- * ---------------
@ -11188,7 +11191,7 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
strncat(cmdstr, " ", sz--); strncat(cmdstr, " ", sz--);
} }
vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr); vshDebug(ctl, 2, "command: \"%s\"\n", cmdstr);
ret = vshCommandParse(ctl, cmdstr); ret = vshCommandStringParse(ctl, cmdstr);
VIR_FREE(cmdstr); VIR_FREE(cmdstr);
return ret; return ret;
@ -11267,7 +11270,7 @@ main(int argc, char **argv)
#if USE_READLINE #if USE_READLINE
add_history(ctl->cmdstr); add_history(ctl->cmdstr);
#endif #endif
if (vshCommandParse(ctl, ctl->cmdstr)) if (vshCommandStringParse(ctl, ctl->cmdstr))
vshCommandRun(ctl, ctl->cmd); vshCommandRun(ctl, ctl->cmd);
} }
VIR_FREE(ctl->cmdstr); VIR_FREE(ctl->cmdstr);