qemu/util/qemu-option.c
<<
>>
Prefs
   1/*
   2 * Commandline option parsing functions
   3 *
   4 * Copyright (c) 2003-2008 Fabrice Bellard
   5 * Copyright (c) 2009 Kevin Wolf <kwolf@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 "qemu/osdep.h"
  27
  28#include "qapi/error.h"
  29#include "qemu-common.h"
  30#include "qemu/error-report.h"
  31#include "qapi/qmp/types.h"
  32#include "qapi/qmp/qerror.h"
  33#include "qemu/option_int.h"
  34#include "qemu/cutils.h"
  35#include "qemu/id.h"
  36#include "qemu/help_option.h"
  37
  38/*
  39 * Extracts the name of an option from the parameter string (p points at the
  40 * first byte of the option name)
  41 *
  42 * The option name is delimited by delim (usually , or =) or the string end
  43 * and is copied into buf. If the option name is longer than buf_size, it is
  44 * truncated. buf is always zero terminated.
  45 *
  46 * The return value is the position of the delimiter/zero byte after the option
  47 * name in p.
  48 */
  49const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
  50{
  51    char *q;
  52
  53    q = buf;
  54    while (*p != '\0' && *p != delim) {
  55        if (q && (q - buf) < buf_size - 1)
  56            *q++ = *p;
  57        p++;
  58    }
  59    if (q)
  60        *q = '\0';
  61
  62    return p;
  63}
  64
  65/*
  66 * Extracts the value of an option from the parameter string p (p points at the
  67 * first byte of the option value)
  68 *
  69 * This function is comparable to get_opt_name with the difference that the
  70 * delimiter is fixed to be comma which starts a new option. To specify an
  71 * option value that contains commas, double each comma.
  72 */
  73const char *get_opt_value(char *buf, int buf_size, const char *p)
  74{
  75    char *q;
  76
  77    q = buf;
  78    while (*p != '\0') {
  79        if (*p == ',') {
  80            if (*(p + 1) != ',')
  81                break;
  82            p++;
  83        }
  84        if (q && (q - buf) < buf_size - 1)
  85            *q++ = *p;
  86        p++;
  87    }
  88    if (q)
  89        *q = '\0';
  90
  91    return p;
  92}
  93
  94int get_next_param_value(char *buf, int buf_size,
  95                         const char *tag, const char **pstr)
  96{
  97    const char *p;
  98    char option[128];
  99
 100    p = *pstr;
 101    for(;;) {
 102        p = get_opt_name(option, sizeof(option), p, '=');
 103        if (*p != '=')
 104            break;
 105        p++;
 106        if (!strcmp(tag, option)) {
 107            *pstr = get_opt_value(buf, buf_size, p);
 108            if (**pstr == ',') {
 109                (*pstr)++;
 110            }
 111            return strlen(buf);
 112        } else {
 113            p = get_opt_value(NULL, 0, p);
 114        }
 115        if (*p != ',')
 116            break;
 117        p++;
 118    }
 119    return 0;
 120}
 121
 122int get_param_value(char *buf, int buf_size,
 123                    const char *tag, const char *str)
 124{
 125    return get_next_param_value(buf, buf_size, tag, &str);
 126}
 127
 128static void parse_option_bool(const char *name, const char *value, bool *ret,
 129                              Error **errp)
 130{
 131    if (value != NULL) {
 132        if (!strcmp(value, "on")) {
 133            *ret = 1;
 134        } else if (!strcmp(value, "off")) {
 135            *ret = 0;
 136        } else {
 137            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
 138                       name, "'on' or 'off'");
 139        }
 140    } else {
 141        *ret = 1;
 142    }
 143}
 144
 145static void parse_option_number(const char *name, const char *value,
 146                                uint64_t *ret, Error **errp)
 147{
 148    char *postfix;
 149    uint64_t number;
 150
 151    if (value != NULL) {
 152        number = strtoull(value, &postfix, 0);
 153        if (*postfix != '\0') {
 154            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
 155            return;
 156        }
 157        *ret = number;
 158    } else {
 159        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
 160    }
 161}
 162
 163static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
 164                                            const char *name)
 165{
 166    int i;
 167
 168    for (i = 0; desc[i].name != NULL; i++) {
 169        if (strcmp(desc[i].name, name) == 0) {
 170            return &desc[i];
 171        }
 172    }
 173
 174    return NULL;
 175}
 176
 177void parse_option_size(const char *name, const char *value,
 178                       uint64_t *ret, Error **errp)
 179{
 180    char *postfix;
 181    double sizef;
 182
 183    if (value != NULL) {
 184        sizef = strtod(value, &postfix);
 185        if (sizef < 0 || sizef > UINT64_MAX) {
 186            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
 187                             "a non-negative number below 2^64");
 188            return;
 189        }
 190        switch (*postfix) {
 191        case 'T':
 192            sizef *= 1024;
 193            /* fall through */
 194        case 'G':
 195            sizef *= 1024;
 196            /* fall through */
 197        case 'M':
 198            sizef *= 1024;
 199            /* fall through */
 200        case 'K':
 201        case 'k':
 202            sizef *= 1024;
 203            /* fall through */
 204        case 'b':
 205        case '\0':
 206            *ret = (uint64_t) sizef;
 207            break;
 208        default:
 209            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
 210            error_append_hint(errp, "You may use k, M, G or T suffixes for "
 211                    "kilobytes, megabytes, gigabytes and terabytes.\n");
 212            return;
 213        }
 214    } else {
 215        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
 216    }
 217}
 218
 219bool has_help_option(const char *param)
 220{
 221    size_t buflen = strlen(param) + 1;
 222    char *buf = g_malloc(buflen);
 223    const char *p = param;
 224    bool result = false;
 225
 226    while (*p) {
 227        p = get_opt_value(buf, buflen, p);
 228        if (*p) {
 229            p++;
 230        }
 231
 232        if (is_help_option(buf)) {
 233            result = true;
 234            goto out;
 235        }
 236    }
 237
 238out:
 239    g_free(buf);
 240    return result;
 241}
 242
 243bool is_valid_option_list(const char *param)
 244{
 245    size_t buflen = strlen(param) + 1;
 246    char *buf = g_malloc(buflen);
 247    const char *p = param;
 248    bool result = true;
 249
 250    while (*p) {
 251        p = get_opt_value(buf, buflen, p);
 252        if (*p && !*++p) {
 253            result = false;
 254            goto out;
 255        }
 256
 257        if (!*buf || *buf == ',') {
 258            result = false;
 259            goto out;
 260        }
 261    }
 262
 263out:
 264    g_free(buf);
 265    return result;
 266}
 267
 268void qemu_opts_print_help(QemuOptsList *list)
 269{
 270    QemuOptDesc *desc;
 271
 272    assert(list);
 273    desc = list->desc;
 274    printf("Supported options:\n");
 275    while (desc && desc->name) {
 276        printf("%-16s %s\n", desc->name,
 277               desc->help ? desc->help : "No description available");
 278        desc++;
 279    }
 280}
 281/* ------------------------------------------------------------------ */
 282
 283QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
 284{
 285    QemuOpt *opt;
 286
 287    QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
 288        if (strcmp(opt->name, name) != 0)
 289            continue;
 290        return opt;
 291    }
 292    return NULL;
 293}
 294
 295static void qemu_opt_del(QemuOpt *opt)
 296{
 297    QTAILQ_REMOVE(&opt->opts->head, opt, next);
 298    g_free(opt->name);
 299    g_free(opt->str);
 300    g_free(opt);
 301}
 302
 303/* qemu_opt_set allows many settings for the same option.
 304 * This function deletes all settings for an option.
 305 */
 306static void qemu_opt_del_all(QemuOpts *opts, const char *name)
 307{
 308    QemuOpt *opt, *next_opt;
 309
 310    QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) {
 311        if (!strcmp(opt->name, name)) {
 312            qemu_opt_del(opt);
 313        }
 314    }
 315}
 316
 317const char *qemu_opt_get(QemuOpts *opts, const char *name)
 318{
 319    QemuOpt *opt;
 320
 321    if (opts == NULL) {
 322        return NULL;
 323    }
 324
 325    opt = qemu_opt_find(opts, name);
 326    if (!opt) {
 327        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
 328        if (desc && desc->def_value_str) {
 329            return desc->def_value_str;
 330        }
 331    }
 332    return opt ? opt->str : NULL;
 333}
 334
 335/* Get a known option (or its default) and remove it from the list
 336 * all in one action. Return a malloced string of the option value.
 337 * Result must be freed by caller with g_free().
 338 */
 339char *qemu_opt_get_del(QemuOpts *opts, const char *name)
 340{
 341    QemuOpt *opt;
 342    const QemuOptDesc *desc;
 343    char *str = NULL;
 344
 345    if (opts == NULL) {
 346        return NULL;
 347    }
 348
 349    opt = qemu_opt_find(opts, name);
 350    if (!opt) {
 351        desc = find_desc_by_name(opts->list->desc, name);
 352        if (desc && desc->def_value_str) {
 353            str = g_strdup(desc->def_value_str);
 354        }
 355        return str;
 356    }
 357    str = opt->str;
 358    opt->str = NULL;
 359    qemu_opt_del_all(opts, name);
 360    return str;
 361}
 362
 363bool qemu_opt_has_help_opt(QemuOpts *opts)
 364{
 365    QemuOpt *opt;
 366
 367    QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
 368        if (is_help_option(opt->name)) {
 369            return true;
 370        }
 371    }
 372    return false;
 373}
 374
 375static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
 376                                     bool defval, bool del)
 377{
 378    QemuOpt *opt;
 379    bool ret = defval;
 380
 381    if (opts == NULL) {
 382        return ret;
 383    }
 384
 385    opt = qemu_opt_find(opts, name);
 386    if (opt == NULL) {
 387        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
 388        if (desc && desc->def_value_str) {
 389            parse_option_bool(name, desc->def_value_str, &ret, &error_abort);
 390        }
 391        return ret;
 392    }
 393    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
 394    ret = opt->value.boolean;
 395    if (del) {
 396        qemu_opt_del_all(opts, name);
 397    }
 398    return ret;
 399}
 400
 401bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
 402{
 403    return qemu_opt_get_bool_helper(opts, name, defval, false);
 404}
 405
 406bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
 407{
 408    return qemu_opt_get_bool_helper(opts, name, defval, true);
 409}
 410
 411static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
 412                                           uint64_t defval, bool del)
 413{
 414    QemuOpt *opt;
 415    uint64_t ret = defval;
 416
 417    if (opts == NULL) {
 418        return ret;
 419    }
 420
 421    opt = qemu_opt_find(opts, name);
 422    if (opt == NULL) {
 423        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
 424        if (desc && desc->def_value_str) {
 425            parse_option_number(name, desc->def_value_str, &ret, &error_abort);
 426        }
 427        return ret;
 428    }
 429    assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
 430    ret = opt->value.uint;
 431    if (del) {
 432        qemu_opt_del_all(opts, name);
 433    }
 434    return ret;
 435}
 436
 437uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
 438{
 439    return qemu_opt_get_number_helper(opts, name, defval, false);
 440}
 441
 442uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
 443                                 uint64_t defval)
 444{
 445    return qemu_opt_get_number_helper(opts, name, defval, true);
 446}
 447
 448static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
 449                                         uint64_t defval, bool del)
 450{
 451    QemuOpt *opt;
 452    uint64_t ret = defval;
 453
 454    if (opts == NULL) {
 455        return ret;
 456    }
 457
 458    opt = qemu_opt_find(opts, name);
 459    if (opt == NULL) {
 460        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
 461        if (desc && desc->def_value_str) {
 462            parse_option_size(name, desc->def_value_str, &ret, &error_abort);
 463        }
 464        return ret;
 465    }
 466    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
 467    ret = opt->value.uint;
 468    if (del) {
 469        qemu_opt_del_all(opts, name);
 470    }
 471    return ret;
 472}
 473
 474uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
 475{
 476    return qemu_opt_get_size_helper(opts, name, defval, false);
 477}
 478
 479uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
 480                               uint64_t defval)
 481{
 482    return qemu_opt_get_size_helper(opts, name, defval, true);
 483}
 484
 485static void qemu_opt_parse(QemuOpt *opt, Error **errp)
 486{
 487    if (opt->desc == NULL)
 488        return;
 489
 490    switch (opt->desc->type) {
 491    case QEMU_OPT_STRING:
 492        /* nothing */
 493        return;
 494    case QEMU_OPT_BOOL:
 495        parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
 496        break;
 497    case QEMU_OPT_NUMBER:
 498        parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
 499        break;
 500    case QEMU_OPT_SIZE:
 501        parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
 502        break;
 503    default:
 504        abort();
 505    }
 506}
 507
 508static bool opts_accepts_any(const QemuOpts *opts)
 509{
 510    return opts->list->desc[0].name == NULL;
 511}
 512
 513int qemu_opt_unset(QemuOpts *opts, const char *name)
 514{
 515    QemuOpt *opt = qemu_opt_find(opts, name);
 516
 517    assert(opts_accepts_any(opts));
 518
 519    if (opt == NULL) {
 520        return -1;
 521    } else {
 522        qemu_opt_del(opt);
 523        return 0;
 524    }
 525}
 526
 527static void opt_set(QemuOpts *opts, const char *name, const char *value,
 528                    bool prepend, Error **errp)
 529{
 530    QemuOpt *opt;
 531    const QemuOptDesc *desc;
 532    Error *local_err = NULL;
 533
 534    desc = find_desc_by_name(opts->list->desc, name);
 535    if (!desc && !opts_accepts_any(opts)) {
 536        error_setg(errp, QERR_INVALID_PARAMETER, name);
 537        return;
 538    }
 539
 540    opt = g_malloc0(sizeof(*opt));
 541    opt->name = g_strdup(name);
 542    opt->opts = opts;
 543    if (prepend) {
 544        QTAILQ_INSERT_HEAD(&opts->head, opt, next);
 545    } else {
 546        QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 547    }
 548    opt->desc = desc;
 549    opt->str = g_strdup(value);
 550    qemu_opt_parse(opt, &local_err);
 551    if (local_err) {
 552        error_propagate(errp, local_err);
 553        qemu_opt_del(opt);
 554    }
 555}
 556
 557void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
 558                  Error **errp)
 559{
 560    opt_set(opts, name, value, false, errp);
 561}
 562
 563void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
 564                       Error **errp)
 565{
 566    QemuOpt *opt;
 567    const QemuOptDesc *desc = opts->list->desc;
 568
 569    opt = g_malloc0(sizeof(*opt));
 570    opt->desc = find_desc_by_name(desc, name);
 571    if (!opt->desc && !opts_accepts_any(opts)) {
 572        error_setg(errp, QERR_INVALID_PARAMETER, name);
 573        g_free(opt);
 574        return;
 575    }
 576
 577    opt->name = g_strdup(name);
 578    opt->opts = opts;
 579    opt->value.boolean = !!val;
 580    opt->str = g_strdup(val ? "on" : "off");
 581    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 582}
 583
 584void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
 585                         Error **errp)
 586{
 587    QemuOpt *opt;
 588    const QemuOptDesc *desc = opts->list->desc;
 589
 590    opt = g_malloc0(sizeof(*opt));
 591    opt->desc = find_desc_by_name(desc, name);
 592    if (!opt->desc && !opts_accepts_any(opts)) {
 593        error_setg(errp, QERR_INVALID_PARAMETER, name);
 594        g_free(opt);
 595        return;
 596    }
 597
 598    opt->name = g_strdup(name);
 599    opt->opts = opts;
 600    opt->value.uint = val;
 601    opt->str = g_strdup_printf("%" PRId64, val);
 602    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 603}
 604
 605/**
 606 * For each member of @opts, call @func(@opaque, name, value, @errp).
 607 * @func() may store an Error through @errp, but must return non-zero then.
 608 * When @func() returns non-zero, break the loop and return that value.
 609 * Return zero when the loop completes.
 610 */
 611int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
 612                     Error **errp)
 613{
 614    QemuOpt *opt;
 615    int rc;
 616
 617    QTAILQ_FOREACH(opt, &opts->head, next) {
 618        rc = func(opaque, opt->name, opt->str, errp);
 619        if (rc) {
 620            return rc;
 621        }
 622        assert(!errp || !*errp);
 623    }
 624    return 0;
 625}
 626
 627QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
 628{
 629    QemuOpts *opts;
 630
 631    QTAILQ_FOREACH(opts, &list->head, next) {
 632        if (!opts->id && !id) {
 633            return opts;
 634        }
 635        if (opts->id && id && !strcmp(opts->id, id)) {
 636            return opts;
 637        }
 638    }
 639    return NULL;
 640}
 641
 642QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
 643                           int fail_if_exists, Error **errp)
 644{
 645    QemuOpts *opts = NULL;
 646
 647    if (id) {
 648        if (!id_wellformed(id)) {
 649            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
 650                       "an identifier");
 651            error_append_hint(errp, "Identifiers consist of letters, digits, "
 652                              "'-', '.', '_', starting with a letter.\n");
 653            return NULL;
 654        }
 655        opts = qemu_opts_find(list, id);
 656        if (opts != NULL) {
 657            if (fail_if_exists && !list->merge_lists) {
 658                error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
 659                return NULL;
 660            } else {
 661                return opts;
 662            }
 663        }
 664    } else if (list->merge_lists) {
 665        opts = qemu_opts_find(list, NULL);
 666        if (opts) {
 667            return opts;
 668        }
 669    }
 670    opts = g_malloc0(sizeof(*opts));
 671    opts->id = g_strdup(id);
 672    opts->list = list;
 673    loc_save(&opts->loc);
 674    QTAILQ_INIT(&opts->head);
 675    QTAILQ_INSERT_TAIL(&list->head, opts, next);
 676    return opts;
 677}
 678
 679void qemu_opts_reset(QemuOptsList *list)
 680{
 681    QemuOpts *opts, *next_opts;
 682
 683    QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
 684        qemu_opts_del(opts);
 685    }
 686}
 687
 688void qemu_opts_loc_restore(QemuOpts *opts)
 689{
 690    loc_restore(&opts->loc);
 691}
 692
 693void qemu_opts_set(QemuOptsList *list, const char *id,
 694                   const char *name, const char *value, Error **errp)
 695{
 696    QemuOpts *opts;
 697    Error *local_err = NULL;
 698
 699    opts = qemu_opts_create(list, id, 1, &local_err);
 700    if (local_err) {
 701        error_propagate(errp, local_err);
 702        return;
 703    }
 704    qemu_opt_set(opts, name, value, errp);
 705}
 706
 707const char *qemu_opts_id(QemuOpts *opts)
 708{
 709    return opts->id;
 710}
 711
 712/* The id string will be g_free()d by qemu_opts_del */
 713void qemu_opts_set_id(QemuOpts *opts, char *id)
 714{
 715    opts->id = id;
 716}
 717
 718void qemu_opts_del(QemuOpts *opts)
 719{
 720    QemuOpt *opt;
 721
 722    if (opts == NULL) {
 723        return;
 724    }
 725
 726    for (;;) {
 727        opt = QTAILQ_FIRST(&opts->head);
 728        if (opt == NULL)
 729            break;
 730        qemu_opt_del(opt);
 731    }
 732    QTAILQ_REMOVE(&opts->list->head, opts, next);
 733    g_free(opts->id);
 734    g_free(opts);
 735}
 736
 737/* print value, escaping any commas in value */
 738static void escaped_print(const char *value)
 739{
 740    const char *ptr;
 741
 742    for (ptr = value; *ptr; ++ptr) {
 743        if (*ptr == ',') {
 744            putchar(',');
 745        }
 746        putchar(*ptr);
 747    }
 748}
 749
 750void qemu_opts_print(QemuOpts *opts, const char *separator)
 751{
 752    QemuOpt *opt;
 753    QemuOptDesc *desc = opts->list->desc;
 754    const char *sep = "";
 755
 756    if (opts->id) {
 757        printf("id=%s", opts->id); /* passed id_wellformed -> no commas */
 758        sep = separator;
 759    }
 760
 761    if (desc[0].name == NULL) {
 762        QTAILQ_FOREACH(opt, &opts->head, next) {
 763            printf("%s%s=", sep, opt->name);
 764            escaped_print(opt->str);
 765            sep = separator;
 766        }
 767        return;
 768    }
 769    for (; desc && desc->name; desc++) {
 770        const char *value;
 771        QemuOpt *opt = qemu_opt_find(opts, desc->name);
 772
 773        value = opt ? opt->str : desc->def_value_str;
 774        if (!value) {
 775            continue;
 776        }
 777        if (desc->type == QEMU_OPT_STRING) {
 778            printf("%s%s=", sep, desc->name);
 779            escaped_print(value);
 780        } else if ((desc->type == QEMU_OPT_SIZE ||
 781                    desc->type == QEMU_OPT_NUMBER) && opt) {
 782            printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint);
 783        } else {
 784            printf("%s%s=%s", sep, desc->name, value);
 785        }
 786        sep = separator;
 787    }
 788}
 789
 790static void opts_do_parse(QemuOpts *opts, const char *params,
 791                          const char *firstname, bool prepend, Error **errp)
 792{
 793    char option[128], value[1024];
 794    const char *p,*pe,*pc;
 795    Error *local_err = NULL;
 796
 797    for (p = params; *p != '\0'; p++) {
 798        pe = strchr(p, '=');
 799        pc = strchr(p, ',');
 800        if (!pe || (pc && pc < pe)) {
 801            /* found "foo,more" */
 802            if (p == params && firstname) {
 803                /* implicitly named first option */
 804                pstrcpy(option, sizeof(option), firstname);
 805                p = get_opt_value(value, sizeof(value), p);
 806            } else {
 807                /* option without value, probably a flag */
 808                p = get_opt_name(option, sizeof(option), p, ',');
 809                if (strncmp(option, "no", 2) == 0) {
 810                    memmove(option, option+2, strlen(option+2)+1);
 811                    pstrcpy(value, sizeof(value), "off");
 812                } else {
 813                    pstrcpy(value, sizeof(value), "on");
 814                }
 815            }
 816        } else {
 817            /* found "foo=bar,more" */
 818            p = get_opt_name(option, sizeof(option), p, '=');
 819            if (*p != '=') {
 820                break;
 821            }
 822            p++;
 823            p = get_opt_value(value, sizeof(value), p);
 824        }
 825        if (strcmp(option, "id") != 0) {
 826            /* store and parse */
 827            opt_set(opts, option, value, prepend, &local_err);
 828            if (local_err) {
 829                error_propagate(errp, local_err);
 830                return;
 831            }
 832        }
 833        if (*p != ',') {
 834            break;
 835        }
 836    }
 837}
 838
 839/**
 840 * Store options parsed from @params into @opts.
 841 * If @firstname is non-null, the first key=value in @params may omit
 842 * key=, and is treated as if key was @firstname.
 843 * On error, store an error object through @errp if non-null.
 844 */
 845void qemu_opts_do_parse(QemuOpts *opts, const char *params,
 846                       const char *firstname, Error **errp)
 847{
 848    opts_do_parse(opts, params, firstname, false, errp);
 849}
 850
 851static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
 852                            bool permit_abbrev, bool defaults, Error **errp)
 853{
 854    const char *firstname;
 855    char value[1024], *id = NULL;
 856    const char *p;
 857    QemuOpts *opts;
 858    Error *local_err = NULL;
 859
 860    assert(!permit_abbrev || list->implied_opt_name);
 861    firstname = permit_abbrev ? list->implied_opt_name : NULL;
 862
 863    if (strncmp(params, "id=", 3) == 0) {
 864        get_opt_value(value, sizeof(value), params+3);
 865        id = value;
 866    } else if ((p = strstr(params, ",id=")) != NULL) {
 867        get_opt_value(value, sizeof(value), p+4);
 868        id = value;
 869    }
 870
 871    /*
 872     * This code doesn't work for defaults && !list->merge_lists: when
 873     * params has no id=, and list has an element with !opts->id, it
 874     * appends a new element instead of returning the existing opts.
 875     * However, we got no use for this case.  Guard against possible
 876     * (if unlikely) future misuse:
 877     */
 878    assert(!defaults || list->merge_lists);
 879    opts = qemu_opts_create(list, id, !defaults, &local_err);
 880    if (opts == NULL) {
 881        error_propagate(errp, local_err);
 882        return NULL;
 883    }
 884
 885    opts_do_parse(opts, params, firstname, defaults, &local_err);
 886    if (local_err) {
 887        error_propagate(errp, local_err);
 888        qemu_opts_del(opts);
 889        return NULL;
 890    }
 891
 892    return opts;
 893}
 894
 895/**
 896 * Create a QemuOpts in @list and with options parsed from @params.
 897 * If @permit_abbrev, the first key=value in @params may omit key=,
 898 * and is treated as if key was @list->implied_opt_name.
 899 * On error, store an error object through @errp if non-null.
 900 * Return the new QemuOpts on success, null pointer on error.
 901 */
 902QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
 903                          bool permit_abbrev, Error **errp)
 904{
 905    return opts_parse(list, params, permit_abbrev, false, errp);
 906}
 907
 908/**
 909 * Create a QemuOpts in @list and with options parsed from @params.
 910 * If @permit_abbrev, the first key=value in @params may omit key=,
 911 * and is treated as if key was @list->implied_opt_name.
 912 * Report errors with error_report_err().  This is inappropriate in
 913 * QMP context.  Do not use this function there!
 914 * Return the new QemuOpts on success, null pointer on error.
 915 */
 916QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
 917                                  bool permit_abbrev)
 918{
 919    Error *err = NULL;
 920    QemuOpts *opts;
 921
 922    opts = opts_parse(list, params, permit_abbrev, false, &err);
 923    if (err) {
 924        error_report_err(err);
 925    }
 926    return opts;
 927}
 928
 929void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
 930                            int permit_abbrev)
 931{
 932    QemuOpts *opts;
 933
 934    opts = opts_parse(list, params, permit_abbrev, true, NULL);
 935    assert(opts);
 936}
 937
 938typedef struct OptsFromQDictState {
 939    QemuOpts *opts;
 940    Error **errp;
 941} OptsFromQDictState;
 942
 943static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 944{
 945    OptsFromQDictState *state = opaque;
 946    char buf[32];
 947    const char *value;
 948    int n;
 949
 950    if (!strcmp(key, "id") || *state->errp) {
 951        return;
 952    }
 953
 954    switch (qobject_type(obj)) {
 955    case QTYPE_QSTRING:
 956        value = qstring_get_str(qobject_to_qstring(obj));
 957        break;
 958    case QTYPE_QINT:
 959        n = snprintf(buf, sizeof(buf), "%" PRId64,
 960                     qint_get_int(qobject_to_qint(obj)));
 961        assert(n < sizeof(buf));
 962        value = buf;
 963        break;
 964    case QTYPE_QFLOAT:
 965        n = snprintf(buf, sizeof(buf), "%.17g",
 966                     qfloat_get_double(qobject_to_qfloat(obj)));
 967        assert(n < sizeof(buf));
 968        value = buf;
 969        break;
 970    case QTYPE_QBOOL:
 971        pstrcpy(buf, sizeof(buf),
 972                qbool_get_bool(qobject_to_qbool(obj)) ? "on" : "off");
 973        value = buf;
 974        break;
 975    default:
 976        return;
 977    }
 978
 979    qemu_opt_set(state->opts, key, value, state->errp);
 980}
 981
 982/*
 983 * Create QemuOpts from a QDict.
 984 * Use value of key "id" as ID if it exists and is a QString.
 985 * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
 986 * other types are silently ignored.
 987 */
 988QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
 989                               Error **errp)
 990{
 991    OptsFromQDictState state;
 992    Error *local_err = NULL;
 993    QemuOpts *opts;
 994
 995    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
 996                            &local_err);
 997    if (local_err) {
 998        error_propagate(errp, local_err);
 999        return NULL;
1000    }
1001
1002    assert(opts != NULL);
1003
1004    state.errp = &local_err;
1005    state.opts = opts;
1006    qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
1007    if (local_err) {
1008        error_propagate(errp, local_err);
1009        qemu_opts_del(opts);
1010        return NULL;
1011    }
1012
1013    return opts;
1014}
1015
1016/*
1017 * Adds all QDict entries to the QemuOpts that can be added and removes them
1018 * from the QDict. When this function returns, the QDict contains only those
1019 * entries that couldn't be added to the QemuOpts.
1020 */
1021void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
1022{
1023    const QDictEntry *entry, *next;
1024
1025    entry = qdict_first(qdict);
1026
1027    while (entry != NULL) {
1028        Error *local_err = NULL;
1029        OptsFromQDictState state = {
1030            .errp = &local_err,
1031            .opts = opts,
1032        };
1033
1034        next = qdict_next(qdict, entry);
1035
1036        if (find_desc_by_name(opts->list->desc, entry->key)) {
1037            qemu_opts_from_qdict_1(entry->key, entry->value, &state);
1038            if (local_err) {
1039                error_propagate(errp, local_err);
1040                return;
1041            } else {
1042                qdict_del(qdict, entry->key);
1043            }
1044        }
1045
1046        entry = next;
1047    }
1048}
1049
1050/*
1051 * Convert from QemuOpts to QDict.
1052 * The QDict values are of type QString.
1053 * TODO We'll want to use types appropriate for opt->desc->type, but
1054 * this is enough for now.
1055 */
1056QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
1057{
1058    QemuOpt *opt;
1059    QObject *val;
1060
1061    if (!qdict) {
1062        qdict = qdict_new();
1063    }
1064    if (opts->id) {
1065        qdict_put(qdict, "id", qstring_from_str(opts->id));
1066    }
1067    QTAILQ_FOREACH(opt, &opts->head, next) {
1068        val = QOBJECT(qstring_from_str(opt->str));
1069        qdict_put_obj(qdict, opt->name, val);
1070    }
1071    return qdict;
1072}
1073
1074/* Validate parsed opts against descriptions where no
1075 * descriptions were provided in the QemuOptsList.
1076 */
1077void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
1078{
1079    QemuOpt *opt;
1080    Error *local_err = NULL;
1081
1082    assert(opts_accepts_any(opts));
1083
1084    QTAILQ_FOREACH(opt, &opts->head, next) {
1085        opt->desc = find_desc_by_name(desc, opt->name);
1086        if (!opt->desc) {
1087            error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
1088            return;
1089        }
1090
1091        qemu_opt_parse(opt, &local_err);
1092        if (local_err) {
1093            error_propagate(errp, local_err);
1094            return;
1095        }
1096    }
1097}
1098
1099/**
1100 * For each member of @list, call @func(@opaque, member, @errp).
1101 * Call it with the current location temporarily set to the member's.
1102 * @func() may store an Error through @errp, but must return non-zero then.
1103 * When @func() returns non-zero, break the loop and return that value.
1104 * Return zero when the loop completes.
1105 */
1106int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
1107                      void *opaque, Error **errp)
1108{
1109    Location loc;
1110    QemuOpts *opts;
1111    int rc = 0;
1112
1113    loc_push_none(&loc);
1114    QTAILQ_FOREACH(opts, &list->head, next) {
1115        loc_restore(&opts->loc);
1116        rc = func(opaque, opts, errp);
1117        if (rc) {
1118            break;
1119        }
1120        assert(!errp || !*errp);
1121    }
1122    loc_pop(&loc);
1123    return rc;
1124}
1125
1126static size_t count_opts_list(QemuOptsList *list)
1127{
1128    QemuOptDesc *desc = NULL;
1129    size_t num_opts = 0;
1130
1131    if (!list) {
1132        return 0;
1133    }
1134
1135    desc = list->desc;
1136    while (desc && desc->name) {
1137        num_opts++;
1138        desc++;
1139    }
1140
1141    return num_opts;
1142}
1143
1144void qemu_opts_free(QemuOptsList *list)
1145{
1146    g_free(list);
1147}
1148
1149/* Realloc dst option list and append options from an option list (list)
1150 * to it. dst could be NULL or a malloced list.
1151 * The lifetime of dst must be shorter than the input list because the
1152 * QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
1153 */
1154QemuOptsList *qemu_opts_append(QemuOptsList *dst,
1155                               QemuOptsList *list)
1156{
1157    size_t num_opts, num_dst_opts;
1158    QemuOptDesc *desc;
1159    bool need_init = false;
1160    bool need_head_update;
1161
1162    if (!list) {
1163        return dst;
1164    }
1165
1166    /* If dst is NULL, after realloc, some area of dst should be initialized
1167     * before adding options to it.
1168     */
1169    if (!dst) {
1170        need_init = true;
1171        need_head_update = true;
1172    } else {
1173        /* Moreover, even if dst is not NULL, the realloc may move it to a
1174         * different address in which case we may get a stale tail pointer
1175         * in dst->head. */
1176        need_head_update = QTAILQ_EMPTY(&dst->head);
1177    }
1178
1179    num_opts = count_opts_list(dst);
1180    num_dst_opts = num_opts;
1181    num_opts += count_opts_list(list);
1182    dst = g_realloc(dst, sizeof(QemuOptsList) +
1183                    (num_opts + 1) * sizeof(QemuOptDesc));
1184    if (need_init) {
1185        dst->name = NULL;
1186        dst->implied_opt_name = NULL;
1187        dst->merge_lists = false;
1188    }
1189    if (need_head_update) {
1190        QTAILQ_INIT(&dst->head);
1191    }
1192    dst->desc[num_dst_opts].name = NULL;
1193
1194    /* append list->desc to dst->desc */
1195    if (list) {
1196        desc = list->desc;
1197        while (desc && desc->name) {
1198            if (find_desc_by_name(dst->desc, desc->name) == NULL) {
1199                dst->desc[num_dst_opts++] = *desc;
1200                dst->desc[num_dst_opts].name = NULL;
1201            }
1202            desc++;
1203        }
1204    }
1205
1206    return dst;
1207}
1208