[libvirt] [PATCH 4/8] virsh: add vrshCommandParser abstraction
add vrshCommandParser and make vshCommandParse() accepts different parsers. the current code for parse command string is integrated as vshCommandStringParse(). Signed-off-by: Lai Jiangshan la...@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_NONE0 -#define VSH_TK_DATA1 -#define VSH_TK_END2 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,
Re: [libvirt] [PATCH 4/8] virsh: add vrshCommandParser abstraction
On 10/12/2010 01:13 AM, Lai Jiangshan wrote: add vrshCommandParser and make vshCommandParse() accepts different s/vrsh/vsh/; s/accepts/accept/ parsers. the current code for parse command string is integrated as vshCommandStringParse(). Signed-off-by: Lai Jiangshanla...@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 Hmm, in addition to floating this earlier, you also lost _NONE and added _SUBCMD_END. The enum I suggested in patch 3 is sounding more appealing, so I'll squash it in now. + +typedef struct __vshCommandParser { +int (*getNextArg)(vshControl *, struct __vshCommandParser *, char **); +char *pos; +} vshCommandParser; + +static int vshCommandParse(vshControl *ctl, vshCommandParser *parser); I'm a fan of avoiding forward static declarations if the file can be rearranged topologically. + /* --- * Command string parsing * --- */ This logically belongs before enums related to command parsing. -#define VSH_TK_ERROR-1 -#define VSH_TK_NONE0 -#define VSH_TK_DATA1 -#define VSH_TK_END2 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; Rebasing this on top of my edits to patch 1 is getting interesting. while (p *p (*p == ' ' || *p == '\t')) You no longer need to check if p is NULL, +static int vshCommandStringParse(vshControl *ctl, char *cmdstr) +{ +vshCommandParser parser; + +if (cmdstr == NULL || *cmdstr == '\0') +return FALSE; + +parser.pos = cmdstr; ...since this guarantees it is non-NULL. +for (;;) { $ git grep 'for.*;;' | wc -l 14 $ git grep 'while.*true' | wc -l 6 $ git grep 'while.*1' | wc -l 70 Guess which one I'm changing this to, for consistency :) ACK, with those nits fixed. Here's what I squashed in: diff --git i/tools/virsh.c w/tools/virsh.c index 56985a4..d9f72f3 100644 --- i/tools/virsh.c +++ w/tools/virsh.c @@ -10174,38 +10174,40 @@ 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 +/* --- + * Command string parsing + * --- + */ + +typedef enum { +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 { -int (*getNextArg)(vshControl *, struct __vshCommandParser *, char **); +vshCommandToken (*getNextArg)(vshControl *, struct __vshCommandParser *, + char **); char *pos; } vshCommandParser; static int vshCommandParse(vshControl *ctl, vshCommandParser *parser); -/* --- - * Command string parsing - * --- - */ - -static int ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) +static vshCommandToken ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) vshCommandStringGetArg(vshControl *ctl, vshCommandParser *parser, char **res) { bool double_quote = false; int sz = 0; char *p = parser-pos; -char *q = vshStrdup(ctl, str); +char *q = vshStrdup(ctl, p); -*end = NULL; *res = q; -while (p *p (*p == ' ' || *p == '\t')) +while (*p (*p == ' ' || *p == '\t')) p++; -if (p == NULL || *p == '\0') +if (*p == '\0') return VSH_TK_END; if (*p == ';') { parser-pos = ++p; /* = \0 or begin of next command */ @@ -10261,15 +10262,15 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser) ctl-cmd = NULL; } -for (;;) { +while (1) { vshCmdOpt *last = NULL; const vshCmdDef *cmd = NULL; -int tk; +vshCommandToken tk; int data_ct = 0; first = NULL; -for (;;) { +while (1) { const vshCmdOptDef *opt = NULL; tkdata = NULL; -- Eric Blake ebl...@redhat.com+1-801-349-2682 Libvirt virtualization library http://libvirt.org -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list