monitor: New format for handlers argument types

Current handlers argument types, as defined in qemu-monitor.hx file,
are a sequence of chars where each one represents one argument type
of the command handler. The number of chars is also used to know how
many arguments a given handler accepts.

This commit defines a new format, which makes mandatory the use of
a name for each argument.

For example, do_eject() command handler is currently defined as:

{ "eject", "-fB", do_eject, ... }

With the new format it becomes:

{ "eject", "force:-f,filename:B", do_eject, ... }

This way the Monitor will be capable of setting up a dictionary, using
each argument's name as the key and the argument itself as the value.

This commit also adds two new functions: key_get_info() and
next_arg_type(), both are used to parse the new format.

Currently key_get_info() consumes the 'key' part of the new format and
discards it, this way the current parsing code is not affected by this
change.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/monitor.c b/monitor.c
index 105a49a..88390ff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2508,6 +2508,33 @@
     return p;
 }
 
+/**
+ * Read key of 'type' into 'key' and return the current
+ * 'type' pointer.
+ */
+static char *key_get_info(const char *type, char **key)
+{
+    size_t len;
+    char *p, *str;
+
+    if (*type == ',')
+        type++;
+
+    p = strchr(type, ':');
+    if (!p) {
+        *key = NULL;
+        return NULL;
+    }
+    len = p - type;
+
+    str = qemu_malloc(len + 1);
+    memcpy(str, type, len);
+    str[len] = '\0';
+
+    *key = str;
+    return ++p;
+}
+
 static int default_fmt_format = 'x';
 static int default_fmt_size = 4;
 
@@ -2520,6 +2547,7 @@
     const mon_cmd_t *cmd;
     char cmdname[256];
     char buf[1024];
+    char *key;
     void *str_allocated[MAX_ARGS];
     void *args[MAX_ARGS];
     void (*handler_0)(Monitor *mon);
@@ -2571,9 +2599,10 @@
     typestr = cmd->args_type;
     nb_args = 0;
     for(;;) {
-        c = *typestr;
-        if (c == '\0')
+        typestr = key_get_info(typestr, &key);
+        if (!typestr)
             break;
+        c = *typestr;
         typestr++;
         switch(c) {
         case 'F':
@@ -2787,6 +2816,8 @@
             monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);
             goto fail;
         }
+        qemu_free(key);
+        key = NULL;
     }
     /* check that all arguments were parsed */
     while (qemu_isspace(*p))
@@ -2854,6 +2885,7 @@
     qemu_errors_to_previous();
 
  fail:
+    qemu_free(key);
     for(i = 0; i < MAX_ARGS; i++)
         qemu_free(str_allocated[i]);
 }
@@ -2972,6 +3004,12 @@
     *pnb_args = nb_args;
 }
 
+static const char *next_arg_type(const char *typestr)
+{
+    const char *p = strchr(typestr, ':');
+    return (p != NULL ? ++p : typestr);
+}
+
 static void monitor_find_completion(const char *cmdline)
 {
     const char *cmdname;
@@ -3014,12 +3052,12 @@
         }
         return;
     found:
-        ptype = cmd->args_type;
+        ptype = next_arg_type(cmd->args_type);
         for(i = 0; i < nb_args - 2; i++) {
             if (*ptype != '\0') {
-                ptype++;
+                ptype = next_arg_type(ptype);
                 while (*ptype == '?')
-                    ptype++;
+                    ptype = next_arg_type(ptype);
             }
         }
         str = args[nb_args - 1];