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