+static int get_str(char *buf, int buf_size, const char **pp)
+{
+ const char *p;
+ char *q;
+ int c;
+
+ q = buf;
+ p = *pp;
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ if (*p == '\0') {
+ fail:
+ *q = '\0';
+ *pp = p;
+ return -1;
+ }
+ if (*p == '\"') {
+ p++;
+ while (*p != '\0' && *p != '\"') {
+ if (*p == '\\') {
+ p++;
+ c = *p++;
+ switch (c) {
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case '\\':
+ case '\'':
+ case '\"':
+ break;
+ default:
+ qemu_printf("unsupported escape code: '\\%c'\n", c);
+ goto fail;
+ }
+ if ((q - buf) < buf_size - 1) {
+ *q++ = c;
+ }
+ } else {
+ if ((q - buf) < buf_size - 1) {
+ *q++ = *p;
+ }
+ p++;
+ }
+ }
+ if (*p != '\"') {
+ qemu_printf("unterminated string\n");
+ goto fail;
+ }
+ p++;
+ } else {
+ while (*p != '\0' && !qemu_isspace(*p)) {
+ if ((q - buf) < buf_size - 1) {
+ *q++ = *p;
+ }
+ p++;
+ }
+ }
+ *q = '\0';
+ *pp = p;
+ return 0;
+}
+
+#define MAX_ARGS 16
+
+static void free_cmdline_args(char **args, int nb_args)
+{
+ int i;
+
+ assert(nb_args <= MAX_ARGS);
+
+ for (i = 0; i < nb_args; i++) {
+ g_free(args[i]);
+ }
+
+}
+
+/*
+ * Parse the command line to get valid args.
+ * @cmdline: command line to be parsed.
+ * @pnb_args: location to store the number of args, must NOT be NULL.
+ * @args: location to store the args, which should be freed by caller, must
+ * NOT be NULL.
+ *
+ * Returns 0 on success, negative on failure.
+ *
+ * NOTE: this parser is an approximate form of the real command parser. Number
+ * of args have a limit of MAX_ARGS. If cmdline contains more, it will
+ * return with failure.
+ */
+static int parse_cmdline(const char *cmdline,
+ int *pnb_args, char **args)
+{
+ const char *p;
+ int nb_args, ret;
+ char buf[1024];
+
+ p = cmdline;
+ nb_args = 0;
+ for (;;) {
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ if (*p == '\0') {
+ break;
+ }
+ if (nb_args >= MAX_ARGS) {
+ goto fail;
+ }
+ ret = get_str(buf, sizeof(buf), &p);
+ if (ret < 0) {
+ goto fail;
+ }
+ args[nb_args] = g_strdup(buf);
+ nb_args++;
+ }
+ *pnb_args = nb_args;
+ return 0;
+
+ fail:
+ free_cmdline_args(args, nb_args);
+ return -1;
+}
+
+static void help_cmd_dump_one(Monitor *mon,
+ const mon_cmd_t *cmd,
+ char **prefix_args,
+ int prefix_args_nb)
+{
+ int i;
+
+ for (i = 0; i < prefix_args_nb; i++) {
+ monitor_printf(mon, "%s ", prefix_args[i]);
+ }
+ monitor_printf(mon, "%s %s -- %s\n", cmd->name, cmd->params, cmd->help);
+}
+
+/* @args[@arg_index] is the valid command need to find in @cmds */