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:
		
							parent
							
								
									19f2db5c84
								
							
						
					
					
						commit
						ae50212ff7
					
				
							
								
								
									
										98
									
								
								monitor.c
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								monitor.c
									
									
									
									
									
								
							@ -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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user