Home | History | Annotate | Download | only in qemu
      1 /*
      2  * Commandline option parsing functions
      3  *
      4  * Copyright (c) 2003-2008 Fabrice Bellard
      5  * Copyright (c) 2009 Kevin Wolf <kwolf (at) redhat.com>
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a copy
      8  * of this software and associated documentation files (the "Software"), to deal
      9  * in the Software without restriction, including without limitation the rights
     10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     11  * copies of the Software, and to permit persons to whom the Software is
     12  * furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included in
     15  * all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     23  * THE SOFTWARE.
     24  */
     25 
     26 #include <stdio.h>
     27 #include <string.h>
     28 
     29 #include "qemu-common.h"
     30 #include "qemu-error.h"
     31 #include "qemu-objects.h"
     32 #include "qemu-option.h"
     33 #include "qerror.h"
     34 
     35 /*
     36  * Extracts the name of an option from the parameter string (p points at the
     37  * first byte of the option name)
     38  *
     39  * The option name is delimited by delim (usually , or =) or the string end
     40  * and is copied into buf. If the option name is longer than buf_size, it is
     41  * truncated. buf is always zero terminated.
     42  *
     43  * The return value is the position of the delimiter/zero byte after the option
     44  * name in p.
     45  */
     46 const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
     47 {
     48     char *q;
     49 
     50     q = buf;
     51     while (*p != '\0' && *p != delim) {
     52         if (q && (q - buf) < buf_size - 1)
     53             *q++ = *p;
     54         p++;
     55     }
     56     if (q)
     57         *q = '\0';
     58 
     59     return p;
     60 }
     61 
     62 /*
     63  * Extracts the value of an option from the parameter string p (p points at the
     64  * first byte of the option value)
     65  *
     66  * This function is comparable to get_opt_name with the difference that the
     67  * delimiter is fixed to be comma which starts a new option. To specify an
     68  * option value that contains commas, double each comma.
     69  */
     70 const char *get_opt_value(char *buf, int buf_size, const char *p)
     71 {
     72     char *q;
     73 
     74     q = buf;
     75     while (*p != '\0') {
     76         if (*p == ',') {
     77             if (*(p + 1) != ',')
     78                 break;
     79             p++;
     80         }
     81         if (q && (q - buf) < buf_size - 1)
     82             *q++ = *p;
     83         p++;
     84     }
     85     if (q)
     86         *q = '\0';
     87 
     88     return p;
     89 }
     90 
     91 int get_next_param_value(char *buf, int buf_size,
     92                          const char *tag, const char **pstr)
     93 {
     94     const char *p;
     95     char option[128];
     96 
     97     p = *pstr;
     98     for(;;) {
     99         p = get_opt_name(option, sizeof(option), p, '=');
    100         if (*p != '=')
    101             break;
    102         p++;
    103         if (!strcmp(tag, option)) {
    104             *pstr = get_opt_value(buf, buf_size, p);
    105             if (**pstr == ',') {
    106                 (*pstr)++;
    107             }
    108             return strlen(buf);
    109         } else {
    110             p = get_opt_value(NULL, 0, p);
    111         }
    112         if (*p != ',')
    113             break;
    114         p++;
    115     }
    116     return 0;
    117 }
    118 
    119 int get_param_value(char *buf, int buf_size,
    120                     const char *tag, const char *str)
    121 {
    122     return get_next_param_value(buf, buf_size, tag, &str);
    123 }
    124 
    125 int check_params(char *buf, int buf_size,
    126                  const char * const *params, const char *str)
    127 {
    128     const char *p;
    129     int i;
    130 
    131     p = str;
    132     while (*p != '\0') {
    133         p = get_opt_name(buf, buf_size, p, '=');
    134         if (*p != '=') {
    135             return -1;
    136         }
    137         p++;
    138         for (i = 0; params[i] != NULL; i++) {
    139             if (!strcmp(params[i], buf)) {
    140                 break;
    141             }
    142         }
    143         if (params[i] == NULL) {
    144             return -1;
    145         }
    146         p = get_opt_value(NULL, 0, p);
    147         if (*p != ',') {
    148             break;
    149         }
    150         p++;
    151     }
    152     return 0;
    153 }
    154 
    155 /*
    156  * Searches an option list for an option with the given name
    157  */
    158 QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
    159     const char *name)
    160 {
    161     while (list && list->name) {
    162         if (!strcmp(list->name, name)) {
    163             return list;
    164         }
    165         list++;
    166     }
    167 
    168     return NULL;
    169 }
    170 
    171 static int parse_option_bool(const char *name, const char *value, int *ret)
    172 {
    173     if (value != NULL) {
    174         if (!strcmp(value, "on")) {
    175             *ret = 1;
    176         } else if (!strcmp(value, "off")) {
    177             *ret = 0;
    178         } else {
    179             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
    180             return -1;
    181         }
    182     } else {
    183         *ret = 1;
    184     }
    185     return 0;
    186 }
    187 
    188 static int parse_option_number(const char *name, const char *value, uint64_t *ret)
    189 {
    190     char *postfix;
    191     uint64_t number;
    192 
    193     if (value != NULL) {
    194         number = strtoull(value, &postfix, 0);
    195         if (*postfix != '\0') {
    196             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
    197             return -1;
    198         }
    199         *ret = number;
    200     } else {
    201         qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
    202         return -1;
    203     }
    204     return 0;
    205 }
    206 
    207 static int parse_option_size(const char *name, const char *value, uint64_t *ret)
    208 {
    209     char *postfix;
    210     double sizef;
    211 
    212     if (value != NULL) {
    213         sizef = strtod(value, &postfix);
    214         switch (*postfix) {
    215         case 'T':
    216             sizef *= 1024;
    217         case 'G':
    218             sizef *= 1024;
    219         case 'M':
    220             sizef *= 1024;
    221         case 'K':
    222         case 'k':
    223             sizef *= 1024;
    224         case 'b':
    225         case '\0':
    226             *ret = (uint64_t) sizef;
    227             break;
    228         default:
    229             qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
    230             error_printf_unless_qmp("You may use k, M, G or T suffixes for "
    231                     "kilobytes, megabytes, gigabytes and terabytes.\n");
    232             return -1;
    233         }
    234     } else {
    235         qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
    236         return -1;
    237     }
    238     return 0;
    239 }
    240 
    241 /*
    242  * Sets the value of a parameter in a given option list. The parsing of the
    243  * value depends on the type of option:
    244  *
    245  * OPT_FLAG (uses value.n):
    246  *      If no value is given, the flag is set to 1.
    247  *      Otherwise the value must be "on" (set to 1) or "off" (set to 0)
    248  *
    249  * OPT_STRING (uses value.s):
    250  *      value is strdup()ed and assigned as option value
    251  *
    252  * OPT_SIZE (uses value.n):
    253  *      The value is converted to an integer. Suffixes for kilobytes etc. are
    254  *      allowed (powers of 1024).
    255  *
    256  * Returns 0 on succes, -1 in error cases
    257  */
    258 int set_option_parameter(QEMUOptionParameter *list, const char *name,
    259     const char *value)
    260 {
    261     int flag;
    262 
    263     // Find a matching parameter
    264     list = get_option_parameter(list, name);
    265     if (list == NULL) {
    266         fprintf(stderr, "Unknown option '%s'\n", name);
    267         return -1;
    268     }
    269 
    270     // Process parameter
    271     switch (list->type) {
    272     case OPT_FLAG:
    273         if (parse_option_bool(name, value, &flag) == -1)
    274             return -1;
    275         list->value.n = flag;
    276         break;
    277 
    278     case OPT_STRING:
    279         if (value != NULL) {
    280             list->value.s = qemu_strdup(value);
    281         } else {
    282             fprintf(stderr, "Option '%s' needs a parameter\n", name);
    283             return -1;
    284         }
    285         break;
    286 
    287     case OPT_SIZE:
    288         if (parse_option_size(name, value, &list->value.n) == -1)
    289             return -1;
    290         break;
    291 
    292     default:
    293         fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name);
    294         return -1;
    295     }
    296 
    297     return 0;
    298 }
    299 
    300 /*
    301  * Sets the given parameter to an integer instead of a string.
    302  * This function cannot be used to set string options.
    303  *
    304  * Returns 0 on success, -1 in error cases
    305  */
    306 int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
    307     uint64_t value)
    308 {
    309     // Find a matching parameter
    310     list = get_option_parameter(list, name);
    311     if (list == NULL) {
    312         fprintf(stderr, "Unknown option '%s'\n", name);
    313         return -1;
    314     }
    315 
    316     // Process parameter
    317     switch (list->type) {
    318     case OPT_FLAG:
    319     case OPT_NUMBER:
    320     case OPT_SIZE:
    321         list->value.n = value;
    322         break;
    323 
    324     default:
    325         return -1;
    326     }
    327 
    328     return 0;
    329 }
    330 
    331 /*
    332  * Frees a option list. If it contains strings, the strings are freed as well.
    333  */
    334 void free_option_parameters(QEMUOptionParameter *list)
    335 {
    336     QEMUOptionParameter *cur = list;
    337 
    338     while (cur && cur->name) {
    339         if (cur->type == OPT_STRING) {
    340             qemu_free(cur->value.s);
    341         }
    342         cur++;
    343     }
    344 
    345     qemu_free(list);
    346 }
    347 
    348 /*
    349  * Count valid options in list
    350  */
    351 static size_t count_option_parameters(QEMUOptionParameter *list)
    352 {
    353     size_t num_options = 0;
    354 
    355     while (list && list->name) {
    356         num_options++;
    357         list++;
    358     }
    359 
    360     return num_options;
    361 }
    362 
    363 /*
    364  * Append an option list (list) to an option list (dest).
    365  *
    366  * If dest is NULL, a new copy of list is created.
    367  *
    368  * Returns a pointer to the first element of dest (or the newly allocated copy)
    369  */
    370 QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
    371     QEMUOptionParameter *list)
    372 {
    373     size_t num_options, num_dest_options;
    374 
    375     num_options = count_option_parameters(dest);
    376     num_dest_options = num_options;
    377 
    378     num_options += count_option_parameters(list);
    379 
    380     dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
    381     dest[num_dest_options].name = NULL;
    382 
    383     while (list && list->name) {
    384         if (get_option_parameter(dest, list->name) == NULL) {
    385             dest[num_dest_options++] = *list;
    386             dest[num_dest_options].name = NULL;
    387         }
    388         list++;
    389     }
    390 
    391     return dest;
    392 }
    393 
    394 /*
    395  * Parses a parameter string (param) into an option list (dest).
    396  *
    397  * list is the template option list. If dest is NULL, a new copy of list is
    398  * created. If list is NULL, this function fails.
    399  *
    400  * A parameter string consists of one or more parameters, separated by commas.
    401  * Each parameter consists of its name and possibly of a value. In the latter
    402  * case, the value is delimited by an = character. To specify a value which
    403  * contains commas, double each comma so it won't be recognized as the end of
    404  * the parameter.
    405  *
    406  * For more details of the parsing see above.
    407  *
    408  * Returns a pointer to the first element of dest (or the newly allocated copy)
    409  * or NULL in error cases
    410  */
    411 QEMUOptionParameter *parse_option_parameters(const char *param,
    412     QEMUOptionParameter *list, QEMUOptionParameter *dest)
    413 {
    414     QEMUOptionParameter *allocated = NULL;
    415     char name[256];
    416     char value[256];
    417     char *param_delim, *value_delim;
    418     char next_delim;
    419 
    420     if (list == NULL) {
    421         return NULL;
    422     }
    423 
    424     if (dest == NULL) {
    425         dest = allocated = append_option_parameters(NULL, list);
    426     }
    427 
    428     while (*param) {
    429 
    430         // Find parameter name and value in the string
    431         param_delim = strchr(param, ',');
    432         value_delim = strchr(param, '=');
    433 
    434         if (value_delim && (value_delim < param_delim || !param_delim)) {
    435             next_delim = '=';
    436         } else {
    437             next_delim = ',';
    438             value_delim = NULL;
    439         }
    440 
    441         param = get_opt_name(name, sizeof(name), param, next_delim);
    442         if (value_delim) {
    443             param = get_opt_value(value, sizeof(value), param + 1);
    444         }
    445         if (*param != '\0') {
    446             param++;
    447         }
    448 
    449         // Set the parameter
    450         if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
    451             goto fail;
    452         }
    453     }
    454 
    455     return dest;
    456 
    457 fail:
    458     // Only free the list if it was newly allocated
    459     free_option_parameters(allocated);
    460     return NULL;
    461 }
    462 
    463 /*
    464  * Prints all options of a list that have a value to stdout
    465  */
    466 void print_option_parameters(QEMUOptionParameter *list)
    467 {
    468     while (list && list->name) {
    469         switch (list->type) {
    470             case OPT_STRING:
    471                  if (list->value.s != NULL) {
    472                      printf("%s='%s' ", list->name, list->value.s);
    473                  }
    474                 break;
    475             case OPT_FLAG:
    476                 printf("%s=%s ", list->name, list->value.n ? "on" : "off");
    477                 break;
    478             case OPT_SIZE:
    479             case OPT_NUMBER:
    480                 printf("%s=%" PRId64 " ", list->name, list->value.n);
    481                 break;
    482             default:
    483                 printf("%s=(unkown type) ", list->name);
    484                 break;
    485         }
    486         list++;
    487     }
    488 }
    489 
    490 /*
    491  * Prints an overview of all available options
    492  */
    493 void print_option_help(QEMUOptionParameter *list)
    494 {
    495     printf("Supported options:\n");
    496     while (list && list->name) {
    497         printf("%-16s %s\n", list->name,
    498             list->help ? list->help : "No description available");
    499         list++;
    500     }
    501 }
    502 
    503 /* ------------------------------------------------------------------ */
    504 
    505 struct QemuOpt {
    506     const char   *name;
    507     const char   *str;
    508 
    509     const QemuOptDesc *desc;
    510     union {
    511         int      boolean;
    512         uint64_t uint;
    513     } value;
    514 
    515     QemuOpts     *opts;
    516     QTAILQ_ENTRY(QemuOpt) next;
    517 };
    518 
    519 struct QemuOpts {
    520     char *id;
    521     QemuOptsList *list;
    522     Location loc;
    523     QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
    524     QTAILQ_ENTRY(QemuOpts) next;
    525 };
    526 
    527 static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
    528 {
    529     QemuOpt *opt;
    530 
    531     QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
    532         if (strcmp(opt->name, name) != 0)
    533             continue;
    534         return opt;
    535     }
    536     return NULL;
    537 }
    538 
    539 const char *qemu_opt_get(QemuOpts *opts, const char *name)
    540 {
    541     QemuOpt *opt = qemu_opt_find(opts, name);
    542     return opt ? opt->str : NULL;
    543 }
    544 
    545 int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
    546 {
    547     QemuOpt *opt = qemu_opt_find(opts, name);
    548 
    549     if (opt == NULL)
    550         return defval;
    551     assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
    552     return opt->value.boolean;
    553 }
    554 
    555 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
    556 {
    557     QemuOpt *opt = qemu_opt_find(opts, name);
    558 
    559     if (opt == NULL)
    560         return defval;
    561     assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
    562     return opt->value.uint;
    563 }
    564 
    565 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
    566 {
    567     QemuOpt *opt = qemu_opt_find(opts, name);
    568 
    569     if (opt == NULL)
    570         return defval;
    571     assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
    572     return opt->value.uint;
    573 }
    574 
    575 static int qemu_opt_parse(QemuOpt *opt)
    576 {
    577     if (opt->desc == NULL)
    578         return 0;
    579     switch (opt->desc->type) {
    580     case QEMU_OPT_STRING:
    581         /* nothing */
    582         return 0;
    583     case QEMU_OPT_BOOL:
    584         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
    585     case QEMU_OPT_NUMBER:
    586         return parse_option_number(opt->name, opt->str, &opt->value.uint);
    587     case QEMU_OPT_SIZE:
    588         return parse_option_size(opt->name, opt->str, &opt->value.uint);
    589     default:
    590         abort();
    591     }
    592 }
    593 
    594 static void qemu_opt_del(QemuOpt *opt)
    595 {
    596     QTAILQ_REMOVE(&opt->opts->head, opt, next);
    597     qemu_free((/* !const */ char*)opt->name);
    598     qemu_free((/* !const */ char*)opt->str);
    599     qemu_free(opt);
    600 }
    601 
    602 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
    603 {
    604     QemuOpt *opt;
    605     const QemuOptDesc *desc = opts->list->desc;
    606     int i;
    607 
    608     for (i = 0; desc[i].name != NULL; i++) {
    609         if (strcmp(desc[i].name, name) == 0) {
    610             break;
    611         }
    612     }
    613     if (desc[i].name == NULL) {
    614         if (i == 0) {
    615             /* empty list -> allow any */;
    616         } else {
    617             qerror_report(QERR_INVALID_PARAMETER, name);
    618             return -1;
    619         }
    620     }
    621 
    622     opt = qemu_mallocz(sizeof(*opt));
    623     opt->name = qemu_strdup(name);
    624     opt->opts = opts;
    625     QTAILQ_INSERT_TAIL(&opts->head, opt, next);
    626     if (desc[i].name != NULL) {
    627         opt->desc = desc+i;
    628     }
    629     if (value) {
    630         opt->str = qemu_strdup(value);
    631     }
    632     if (qemu_opt_parse(opt) < 0) {
    633         qemu_opt_del(opt);
    634         return -1;
    635     }
    636     return 0;
    637 }
    638 
    639 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
    640                      int abort_on_failure)
    641 {
    642     QemuOpt *opt;
    643     int rc = 0;
    644 
    645     QTAILQ_FOREACH(opt, &opts->head, next) {
    646         rc = func(opt->name, opt->str, opaque);
    647         if (abort_on_failure  &&  rc != 0)
    648             break;
    649     }
    650     return rc;
    651 }
    652 
    653 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
    654 {
    655     QemuOpts *opts;
    656 
    657     QTAILQ_FOREACH(opts, &list->head, next) {
    658         if (!opts->id) {
    659             continue;
    660         }
    661         if (strcmp(opts->id, id) != 0) {
    662             continue;
    663         }
    664         return opts;
    665     }
    666     return NULL;
    667 }
    668 
    669 static int id_wellformed(const char *id)
    670 {
    671     int i;
    672 
    673     if (!qemu_isalpha(id[0])) {
    674         return 0;
    675     }
    676     for (i = 1; id[i]; i++) {
    677         if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
    678             return 0;
    679         }
    680     }
    681     return 1;
    682 }
    683 
    684 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
    685 {
    686     QemuOpts *opts = NULL;
    687 
    688     if (id) {
    689         if (!id_wellformed(id)) {
    690             qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
    691             error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
    692             return NULL;
    693         }
    694         opts = qemu_opts_find(list, id);
    695         if (opts != NULL) {
    696             if (fail_if_exists) {
    697                 qerror_report(QERR_DUPLICATE_ID, id, list->name);
    698                 return NULL;
    699             } else {
    700                 return opts;
    701             }
    702         }
    703     }
    704     opts = qemu_mallocz(sizeof(*opts));
    705     if (id) {
    706         opts->id = qemu_strdup(id);
    707     }
    708     opts->list = list;
    709     loc_save(&opts->loc);
    710     QTAILQ_INIT(&opts->head);
    711     QTAILQ_INSERT_TAIL(&list->head, opts, next);
    712     return opts;
    713 }
    714 
    715 void qemu_opts_reset(QemuOptsList *list)
    716 {
    717     QemuOpts *opts, *next_opts;
    718 
    719     QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
    720         qemu_opts_del(opts);
    721     }
    722 }
    723 
    724 void qemu_opts_loc_restore(QemuOpts *opts)
    725 {
    726     loc_restore(&opts->loc);
    727 }
    728 
    729 int qemu_opts_set(QemuOptsList *list, const char *id,
    730                   const char *name, const char *value)
    731 {
    732     QemuOpts *opts;
    733 
    734     opts = qemu_opts_create(list, id, 1);
    735     if (opts == NULL) {
    736         return -1;
    737     }
    738     return qemu_opt_set(opts, name, value);
    739 }
    740 
    741 const char *qemu_opts_id(QemuOpts *opts)
    742 {
    743     return opts->id;
    744 }
    745 
    746 void qemu_opts_del(QemuOpts *opts)
    747 {
    748     QemuOpt *opt;
    749 
    750     for (;;) {
    751         opt = QTAILQ_FIRST(&opts->head);
    752         if (opt == NULL)
    753             break;
    754         qemu_opt_del(opt);
    755     }
    756     QTAILQ_REMOVE(&opts->list->head, opts, next);
    757     qemu_free(opts->id);
    758     qemu_free(opts);
    759 }
    760 
    761 int qemu_opts_print(QemuOpts *opts, void *dummy)
    762 {
    763     QemuOpt *opt;
    764 
    765     fprintf(stderr, "%s: %s:", opts->list->name,
    766             opts->id ? opts->id : "<noid>");
    767     QTAILQ_FOREACH(opt, &opts->head, next) {
    768         fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
    769     }
    770     fprintf(stderr, "\n");
    771     return 0;
    772 }
    773 
    774 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
    775 {
    776     char option[128], value[1024];
    777     const char *p,*pe,*pc;
    778 
    779     for (p = params; *p != '\0'; p++) {
    780         pe = strchr(p, '=');
    781         pc = strchr(p, ',');
    782         if (!pe || (pc && pc < pe)) {
    783             /* found "foo,more" */
    784             if (p == params && firstname) {
    785                 /* implicitly named first option */
    786                 pstrcpy(option, sizeof(option), firstname);
    787                 p = get_opt_value(value, sizeof(value), p);
    788             } else {
    789                 /* option without value, probably a flag */
    790                 p = get_opt_name(option, sizeof(option), p, ',');
    791                 if (strncmp(option, "no", 2) == 0) {
    792                     memmove(option, option+2, strlen(option+2)+1);
    793                     pstrcpy(value, sizeof(value), "off");
    794                 } else {
    795                     pstrcpy(value, sizeof(value), "on");
    796                 }
    797             }
    798         } else {
    799             /* found "foo=bar,more" */
    800             p = get_opt_name(option, sizeof(option), p, '=');
    801             if (*p != '=') {
    802                 break;
    803             }
    804             p++;
    805             p = get_opt_value(value, sizeof(value), p);
    806         }
    807         if (strcmp(option, "id") != 0) {
    808             /* store and parse */
    809             if (qemu_opt_set(opts, option, value) == -1) {
    810                 return -1;
    811             }
    812         }
    813         if (*p != ',') {
    814             break;
    815         }
    816     }
    817     return 0;
    818 }
    819 
    820 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
    821                           int permit_abbrev)
    822 {
    823     const char *firstname;
    824     char value[1024], *id = NULL;
    825     const char *p;
    826     QemuOpts *opts;
    827 
    828     assert(!permit_abbrev || list->implied_opt_name);
    829     firstname = permit_abbrev ? list->implied_opt_name : NULL;
    830 
    831     if (strncmp(params, "id=", 3) == 0) {
    832         get_opt_value(value, sizeof(value), params+3);
    833         id = value;
    834     } else if ((p = strstr(params, ",id=")) != NULL) {
    835         get_opt_value(value, sizeof(value), p+4);
    836         id = value;
    837     }
    838     opts = qemu_opts_create(list, id, 1);
    839     if (opts == NULL)
    840         return NULL;
    841 
    842     if (qemu_opts_do_parse(opts, params, firstname) != 0) {
    843         qemu_opts_del(opts);
    844         return NULL;
    845     }
    846 
    847     return opts;
    848 }
    849 
    850 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
    851 {
    852     char buf[32];
    853     const char *value;
    854     int n;
    855 
    856     if (!strcmp(key, "id")) {
    857         return;
    858     }
    859 
    860     switch (qobject_type(obj)) {
    861     case QTYPE_QSTRING:
    862         value = qstring_get_str(qobject_to_qstring(obj));
    863         break;
    864     case QTYPE_QINT:
    865         n = snprintf(buf, sizeof(buf), "%" PRId64,
    866                      qint_get_int(qobject_to_qint(obj)));
    867         assert(n < sizeof(buf));
    868         value = buf;
    869         break;
    870     case QTYPE_QFLOAT:
    871         n = snprintf(buf, sizeof(buf), "%.17g",
    872                      qfloat_get_double(qobject_to_qfloat(obj)));
    873         assert(n < sizeof(buf));
    874         value = buf;
    875         break;
    876     case QTYPE_QBOOL:
    877         pstrcpy(buf, sizeof(buf),
    878                 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
    879         value = buf;
    880         break;
    881     default:
    882         return;
    883     }
    884     qemu_opt_set(opaque, key, value);
    885 }
    886 
    887 /*
    888  * Create QemuOpts from a QDict.
    889  * Use value of key "id" as ID if it exists and is a QString.
    890  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
    891  * other types are silently ignored.
    892  */
    893 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
    894 {
    895     QemuOpts *opts;
    896 
    897     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
    898     if (opts == NULL)
    899         return NULL;
    900 
    901     qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
    902     return opts;
    903 }
    904 
    905 /*
    906  * Convert from QemuOpts to QDict.
    907  * The QDict values are of type QString.
    908  * TODO We'll want to use types appropriate for opt->desc->type, but
    909  * this is enough for now.
    910  */
    911 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
    912 {
    913     QemuOpt *opt;
    914     QObject *val;
    915 
    916     if (!qdict) {
    917         qdict = qdict_new();
    918     }
    919     if (opts->id) {
    920         qdict_put(qdict, "id", qstring_from_str(opts->id));
    921     }
    922     QTAILQ_FOREACH(opt, &opts->head, next) {
    923         val = QOBJECT(qstring_from_str(opt->str));
    924         qdict_put_obj(qdict, opt->name, val);
    925     }
    926     return qdict;
    927 }
    928 
    929 /* Validate parsed opts against descriptions where no
    930  * descriptions were provided in the QemuOptsList.
    931  */
    932 int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
    933 {
    934     QemuOpt *opt;
    935 
    936     assert(opts->list->desc[0].name == NULL);
    937 
    938     QTAILQ_FOREACH(opt, &opts->head, next) {
    939         int i;
    940 
    941         for (i = 0; desc[i].name != NULL; i++) {
    942             if (strcmp(desc[i].name, opt->name) == 0) {
    943                 break;
    944             }
    945         }
    946         if (desc[i].name == NULL) {
    947             qerror_report(QERR_INVALID_PARAMETER, opt->name);
    948             return -1;
    949         }
    950 
    951         opt->desc = &desc[i];
    952 
    953         if (qemu_opt_parse(opt) < 0) {
    954             return -1;
    955         }
    956     }
    957 
    958     return 0;
    959 }
    960 
    961 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
    962                       int abort_on_failure)
    963 {
    964     Location loc;
    965     QemuOpts *opts;
    966     int rc = 0;
    967 
    968     loc_push_none(&loc);
    969     QTAILQ_FOREACH(opts, &list->head, next) {
    970         loc_restore(&opts->loc);
    971         rc |= func(opts, opaque);
    972         if (abort_on_failure  &&  rc != 0)
    973             break;
    974     }
    975     loc_pop(&loc);
    976     return rc;
    977 }
    978