monitor: cleanup parsing of cmd name and cmd arguments

There's too much going on in monitor_parse_command().
Split up the arguments parsing bits into a separate function
monitor_parse_arguments(). Let the original function check for
command validity and sub-commands if any and return data (*cmd)
that the newly introduced function can process and return a
QDict. Also, pass a pointer to the cmdline to track current
parser location.

Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Bandan Das <bsd@redhat.com>
Acked-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
Bandan Das 2015-06-03 18:38:08 -04:00 committed by Markus Armbruster
parent 19f2db5c84
commit ae50212ff7
1 changed files with 57 additions and 41 deletions

View File

@ -3634,39 +3634,32 @@ static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
} }
/* /*
* Parse @cmdline according to command table @table. * Parse command name from @cmdp according to command table @table.
* If @cmdline is blank, return NULL. * If blank, return NULL.
* If it can't be parsed, report to @mon, and return NULL. * Else, if no valid command can be found, report to @mon, and return
* Else, insert command arguments into @qdict, and return the command. * NULL.
* If a sub-command table exists, and if @cmdline contains an additional string * Else, change @cmdp to point right behind the name, and return its
* for a sub-command, this function will try to search the sub-command table. * command table entry.
* If no additional string for a sub-command is present, this function will * Do not assume the return value points into @table! It doesn't when
* return the command found in @table. * the command is found in a sub-command table.
* Do not assume the returned command points into @table! It doesn't
* when the command is a sub-command.
*/ */
static const mon_cmd_t *monitor_parse_command(Monitor *mon, static const mon_cmd_t *monitor_parse_command(Monitor *mon,
const char *cmdline, const char **cmdp,
int start, mon_cmd_t *table)
mon_cmd_t *table,
QDict *qdict)
{ {
const char *p, *typestr; const char *p;
int c;
const mon_cmd_t *cmd; const mon_cmd_t *cmd;
char cmdname[256]; char cmdname[256];
char buf[1024];
char *key;
/* extract the command name */ /* extract the command name */
p = get_command_name(cmdline + start, cmdname, sizeof(cmdname)); p = get_command_name(*cmdp, cmdname, sizeof(cmdname));
if (!p) if (!p)
return NULL; return NULL;
cmd = search_dispatch_table(table, cmdname); cmd = search_dispatch_table(table, cmdname);
if (!cmd) { if (!cmd) {
monitor_printf(mon, "unknown command: '%.*s'\n", monitor_printf(mon, "unknown command: '%.*s'\n",
(int)(p - cmdline), cmdline); (int)(p - *cmdp), *cmdp);
return NULL; return NULL;
} }
@ -3674,15 +3667,33 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
while (qemu_isspace(*p)) { while (qemu_isspace(*p)) {
p++; p++;
} }
*cmdp = p;
/* search sub command */ /* search sub command */
if (cmd->sub_table != NULL) { if (cmd->sub_table != NULL && *p != '\0') {
/* check if user set additional command */ return monitor_parse_command(mon, cmdp, cmd->sub_table);
if (*p == '\0') { }
return cmd; return cmd;
} }
return monitor_parse_command(mon, cmdline, p - cmdline,
cmd->sub_table, qdict); /*
} * Parse arguments for @cmd.
* If it can't be parsed, report to @mon, and return NULL.
* Else, insert command arguments into a QDict, and return it.
* Note: On success, caller has to free the QDict structure.
*/
static QDict *monitor_parse_arguments(Monitor *mon,
const char **endp,
const mon_cmd_t *cmd)
{
const char *typestr;
char *key;
int c;
const char *p = *endp;
char buf[1024];
QDict *qdict = qdict_new();
/* parse the parameters */ /* parse the parameters */
typestr = cmd->args_type; typestr = cmd->args_type;
@ -3713,14 +3724,14 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
switch(c) { switch(c) {
case 'F': case 'F':
monitor_printf(mon, "%s: filename expected\n", monitor_printf(mon, "%s: filename expected\n",
cmdname); cmd->name);
break; break;
case 'B': case 'B':
monitor_printf(mon, "%s: block device name expected\n", monitor_printf(mon, "%s: block device name expected\n",
cmdname); cmd->name);
break; break;
default: default:
monitor_printf(mon, "%s: string expected\n", cmdname); monitor_printf(mon, "%s: string expected\n", cmd->name);
break; break;
} }
goto fail; goto fail;
@ -3862,7 +3873,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
goto fail; goto fail;
/* Check if 'i' is greater than 32-bit */ /* Check if 'i' is greater than 32-bit */
if ((c == 'i') && ((val >> 32) & 0xffffffff)) { if ((c == 'i') && ((val >> 32) & 0xffffffff)) {
monitor_printf(mon, "\'%s\' has failed: ", cmdname); monitor_printf(mon, "\'%s\' has failed: ", cmd->name);
monitor_printf(mon, "integer is for 32-bit values\n"); monitor_printf(mon, "integer is for 32-bit values\n");
goto fail; goto fail;
} else if (c == 'M') { } else if (c == 'M') {
@ -3970,7 +3981,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
if(!is_valid_option(p, typestr)) { if(!is_valid_option(p, typestr)) {
monitor_printf(mon, "%s: unsupported option -%c\n", monitor_printf(mon, "%s: unsupported option -%c\n",
cmdname, *p); cmd->name, *p);
goto fail; goto fail;
} else { } else {
skip_key = 1; skip_key = 1;
@ -4004,7 +4015,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
len = strlen(p); len = strlen(p);
if (len <= 0) { if (len <= 0) {
monitor_printf(mon, "%s: string expected\n", monitor_printf(mon, "%s: string expected\n",
cmdname); cmd->name);
break; break;
} }
qdict_put(qdict, key, qstring_from_str(p)); qdict_put(qdict, key, qstring_from_str(p));
@ -4013,7 +4024,7 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
break; break;
default: default:
bad_type: bad_type:
monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c); monitor_printf(mon, "%s: unknown type '%c'\n", cmd->name, c);
goto fail; goto fail;
} }
g_free(key); g_free(key);
@ -4024,13 +4035,14 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon,
p++; p++;
if (*p != '\0') { if (*p != '\0') {
monitor_printf(mon, "%s: extraneous characters at the end of line\n", monitor_printf(mon, "%s: extraneous characters at the end of line\n",
cmdname); cmd->name);
goto fail; goto fail;
} }
return cmd; return qdict;
fail: fail:
QDECREF(qdict);
g_free(key); g_free(key);
return NULL; return NULL;
} }
@ -4050,13 +4062,17 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline)
QDict *qdict; QDict *qdict;
const mon_cmd_t *cmd; const mon_cmd_t *cmd;
qdict = qdict_new(); cmd = monitor_parse_command(mon, &cmdline, mon->cmd_table);
if (!cmd) {
cmd = monitor_parse_command(mon, cmdline, 0, mon->cmd_table, qdict); return;
if (cmd) {
cmd->mhandler.cmd(mon, qdict);
} }
qdict = monitor_parse_arguments(mon, &cmdline, cmd);
if (!qdict) {
return;
}
cmd->mhandler.cmd(mon, qdict);
QDECREF(qdict); QDECREF(qdict);
} }