[libvirt] [PATCH 4/8] virsh: add vrshCommandParser abstraction

Lai Jiangshan laijs at cn.fujitsu.com
Tue Oct 12 07:13:50 UTC 2010


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 at 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);




More information about the libvir-list mailing list