qemu/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 <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 */
  46const 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 */
  70const 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
  91int 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
 119int 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
 125int 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 */
 158QEMUOptionParameter *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
 171static int parse_option_bool(const char *name, const char *value, bool *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
 188static 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
 207static 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 */
 258int set_option_parameter(QEMUOptionParameter *list, const char *name,
 259    const char *value)
 260{
 261    bool 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 = g_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 */
 306int 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 */
 334void free_option_parameters(QEMUOptionParameter *list)
 335{
 336    QEMUOptionParameter *cur = list;
 337
 338    while (cur && cur->name) {
 339        if (cur->type == OPT_STRING) {
 340            g_free(cur->value.s);
 341        }
 342        cur++;
 343    }
 344
 345    g_free(list);
 346}
 347
 348/*
 349 * Count valid options in list
 350 */
 351static 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 */
 370QEMUOptionParameter *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 = g_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 */
 411QEMUOptionParameter *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
 457fail:
 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 */
 466void 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 */
 493void 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
 505struct QemuOpt {
 506    const char   *name;
 507    const char   *str;
 508
 509    const QemuOptDesc *desc;
 510    union {
 511        bool boolean;
 512        uint64_t uint;
 513    } value;
 514
 515    QemuOpts     *opts;
 516    QTAILQ_ENTRY(QemuOpt) next;
 517};
 518
 519struct QemuOpts {
 520    char *id;
 521    QemuOptsList *list;
 522    Location loc;
 523    QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
 524    QTAILQ_ENTRY(QemuOpts) next;
 525};
 526
 527static 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
 539const 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
 545bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool 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
 555uint64_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
 565uint64_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
 575static 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
 594static void qemu_opt_del(QemuOpt *opt)
 595{
 596    QTAILQ_REMOVE(&opt->opts->head, opt, next);
 597    g_free((/* !const */ char*)opt->name);
 598    g_free((/* !const */ char*)opt->str);
 599    g_free(opt);
 600}
 601
 602int 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 = g_malloc0(sizeof(*opt));
 623    opt->name = g_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 = g_strdup(value);
 631    }
 632    if (qemu_opt_parse(opt) < 0) {
 633        qemu_opt_del(opt);
 634        return -1;
 635    }
 636    return 0;
 637}
 638
 639int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
 640{
 641    QemuOpt *opt;
 642    const QemuOptDesc *desc = opts->list->desc;
 643    int i;
 644
 645    for (i = 0; desc[i].name != NULL; i++) {
 646        if (strcmp(desc[i].name, name) == 0) {
 647            break;
 648        }
 649    }
 650    if (desc[i].name == NULL) {
 651        if (i == 0) {
 652            /* empty list -> allow any */;
 653        } else {
 654            qerror_report(QERR_INVALID_PARAMETER, name);
 655            return -1;
 656        }
 657    }
 658
 659    opt = g_malloc0(sizeof(*opt));
 660    opt->name = g_strdup(name);
 661    opt->opts = opts;
 662    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 663    if (desc[i].name != NULL) {
 664        opt->desc = desc+i;
 665    }
 666    opt->value.boolean = !!val;
 667    return 0;
 668}
 669
 670int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
 671                     int abort_on_failure)
 672{
 673    QemuOpt *opt;
 674    int rc = 0;
 675
 676    QTAILQ_FOREACH(opt, &opts->head, next) {
 677        rc = func(opt->name, opt->str, opaque);
 678        if (abort_on_failure  &&  rc != 0)
 679            break;
 680    }
 681    return rc;
 682}
 683
 684QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
 685{
 686    QemuOpts *opts;
 687
 688    QTAILQ_FOREACH(opts, &list->head, next) {
 689        if (!opts->id) {
 690            continue;
 691        }
 692        if (strcmp(opts->id, id) != 0) {
 693            continue;
 694        }
 695        return opts;
 696    }
 697    return NULL;
 698}
 699
 700static int id_wellformed(const char *id)
 701{
 702    int i;
 703
 704    if (!qemu_isalpha(id[0])) {
 705        return 0;
 706    }
 707    for (i = 1; id[i]; i++) {
 708        if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
 709            return 0;
 710        }
 711    }
 712    return 1;
 713}
 714
 715QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
 716{
 717    QemuOpts *opts = NULL;
 718
 719    if (id) {
 720        if (!id_wellformed(id)) {
 721            qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
 722            error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
 723            return NULL;
 724        }
 725        opts = qemu_opts_find(list, id);
 726        if (opts != NULL) {
 727            if (fail_if_exists) {
 728                qerror_report(QERR_DUPLICATE_ID, id, list->name);
 729                return NULL;
 730            } else {
 731                return opts;
 732            }
 733        }
 734    }
 735    opts = g_malloc0(sizeof(*opts));
 736    if (id) {
 737        opts->id = g_strdup(id);
 738    }
 739    opts->list = list;
 740    loc_save(&opts->loc);
 741    QTAILQ_INIT(&opts->head);
 742    QTAILQ_INSERT_TAIL(&list->head, opts, next);
 743    return opts;
 744}
 745
 746void qemu_opts_reset(QemuOptsList *list)
 747{
 748    QemuOpts *opts, *next_opts;
 749
 750    QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
 751        qemu_opts_del(opts);
 752    }
 753}
 754
 755void qemu_opts_loc_restore(QemuOpts *opts)
 756{
 757    loc_restore(&opts->loc);
 758}
 759
 760int qemu_opts_set(QemuOptsList *list, const char *id,
 761                  const char *name, const char *value)
 762{
 763    QemuOpts *opts;
 764
 765    opts = qemu_opts_create(list, id, 1);
 766    if (opts == NULL) {
 767        return -1;
 768    }
 769    return qemu_opt_set(opts, name, value);
 770}
 771
 772const char *qemu_opts_id(QemuOpts *opts)
 773{
 774    return opts->id;
 775}
 776
 777void qemu_opts_del(QemuOpts *opts)
 778{
 779    QemuOpt *opt;
 780
 781    for (;;) {
 782        opt = QTAILQ_FIRST(&opts->head);
 783        if (opt == NULL)
 784            break;
 785        qemu_opt_del(opt);
 786    }
 787    QTAILQ_REMOVE(&opts->list->head, opts, next);
 788    g_free(opts->id);
 789    g_free(opts);
 790}
 791
 792int qemu_opts_print(QemuOpts *opts, void *dummy)
 793{
 794    QemuOpt *opt;
 795
 796    fprintf(stderr, "%s: %s:", opts->list->name,
 797            opts->id ? opts->id : "<noid>");
 798    QTAILQ_FOREACH(opt, &opts->head, next) {
 799        fprintf(stderr, " %s=\"%s\"", opt->name, opt->str);
 800    }
 801    fprintf(stderr, "\n");
 802    return 0;
 803}
 804
 805int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
 806{
 807    char option[128], value[1024];
 808    const char *p,*pe,*pc;
 809
 810    for (p = params; *p != '\0'; p++) {
 811        pe = strchr(p, '=');
 812        pc = strchr(p, ',');
 813        if (!pe || (pc && pc < pe)) {
 814            /* found "foo,more" */
 815            if (p == params && firstname) {
 816                /* implicitly named first option */
 817                pstrcpy(option, sizeof(option), firstname);
 818                p = get_opt_value(value, sizeof(value), p);
 819            } else {
 820                /* option without value, probably a flag */
 821                p = get_opt_name(option, sizeof(option), p, ',');
 822                if (strncmp(option, "no", 2) == 0) {
 823                    memmove(option, option+2, strlen(option+2)+1);
 824                    pstrcpy(value, sizeof(value), "off");
 825                } else {
 826                    pstrcpy(value, sizeof(value), "on");
 827                }
 828            }
 829        } else {
 830            /* found "foo=bar,more" */
 831            p = get_opt_name(option, sizeof(option), p, '=');
 832            if (*p != '=') {
 833                break;
 834            }
 835            p++;
 836            p = get_opt_value(value, sizeof(value), p);
 837        }
 838        if (strcmp(option, "id") != 0) {
 839            /* store and parse */
 840            if (qemu_opt_set(opts, option, value) == -1) {
 841                return -1;
 842            }
 843        }
 844        if (*p != ',') {
 845            break;
 846        }
 847    }
 848    return 0;
 849}
 850
 851QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
 852                          int permit_abbrev)
 853{
 854    const char *firstname;
 855    char value[1024], *id = NULL;
 856    const char *p;
 857    QemuOpts *opts;
 858
 859    assert(!permit_abbrev || list->implied_opt_name);
 860    firstname = permit_abbrev ? list->implied_opt_name : NULL;
 861
 862    if (strncmp(params, "id=", 3) == 0) {
 863        get_opt_value(value, sizeof(value), params+3);
 864        id = value;
 865    } else if ((p = strstr(params, ",id=")) != NULL) {
 866        get_opt_value(value, sizeof(value), p+4);
 867        id = value;
 868    }
 869    opts = qemu_opts_create(list, id, 1);
 870    if (opts == NULL)
 871        return NULL;
 872
 873    if (qemu_opts_do_parse(opts, params, firstname) != 0) {
 874        qemu_opts_del(opts);
 875        return NULL;
 876    }
 877
 878    return opts;
 879}
 880
 881static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 882{
 883    char buf[32];
 884    const char *value;
 885    int n;
 886
 887    if (!strcmp(key, "id")) {
 888        return;
 889    }
 890
 891    switch (qobject_type(obj)) {
 892    case QTYPE_QSTRING:
 893        value = qstring_get_str(qobject_to_qstring(obj));
 894        break;
 895    case QTYPE_QINT:
 896        n = snprintf(buf, sizeof(buf), "%" PRId64,
 897                     qint_get_int(qobject_to_qint(obj)));
 898        assert(n < sizeof(buf));
 899        value = buf;
 900        break;
 901    case QTYPE_QFLOAT:
 902        n = snprintf(buf, sizeof(buf), "%.17g",
 903                     qfloat_get_double(qobject_to_qfloat(obj)));
 904        assert(n < sizeof(buf));
 905        value = buf;
 906        break;
 907    case QTYPE_QBOOL:
 908        pstrcpy(buf, sizeof(buf),
 909                qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off");
 910        value = buf;
 911        break;
 912    default:
 913        return;
 914    }
 915    qemu_opt_set(opaque, key, value);
 916}
 917
 918/*
 919 * Create QemuOpts from a QDict.
 920 * Use value of key "id" as ID if it exists and is a QString.
 921 * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
 922 * other types are silently ignored.
 923 */
 924QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
 925{
 926    QemuOpts *opts;
 927
 928    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
 929    if (opts == NULL)
 930        return NULL;
 931
 932    qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
 933    return opts;
 934}
 935
 936/*
 937 * Convert from QemuOpts to QDict.
 938 * The QDict values are of type QString.
 939 * TODO We'll want to use types appropriate for opt->desc->type, but
 940 * this is enough for now.
 941 */
 942QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
 943{
 944    QemuOpt *opt;
 945    QObject *val;
 946
 947    if (!qdict) {
 948        qdict = qdict_new();
 949    }
 950    if (opts->id) {
 951        qdict_put(qdict, "id", qstring_from_str(opts->id));
 952    }
 953    QTAILQ_FOREACH(opt, &opts->head, next) {
 954        val = QOBJECT(qstring_from_str(opt->str));
 955        qdict_put_obj(qdict, opt->name, val);
 956    }
 957    return qdict;
 958}
 959
 960/* Validate parsed opts against descriptions where no
 961 * descriptions were provided in the QemuOptsList.
 962 */
 963int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
 964{
 965    QemuOpt *opt;
 966
 967    assert(opts->list->desc[0].name == NULL);
 968
 969    QTAILQ_FOREACH(opt, &opts->head, next) {
 970        int i;
 971
 972        for (i = 0; desc[i].name != NULL; i++) {
 973            if (strcmp(desc[i].name, opt->name) == 0) {
 974                break;
 975            }
 976        }
 977        if (desc[i].name == NULL) {
 978            qerror_report(QERR_INVALID_PARAMETER, opt->name);
 979            return -1;
 980        }
 981
 982        opt->desc = &desc[i];
 983
 984        if (qemu_opt_parse(opt) < 0) {
 985            return -1;
 986        }
 987    }
 988
 989    return 0;
 990}
 991
 992int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
 993                      int abort_on_failure)
 994{
 995    Location loc;
 996    QemuOpts *opts;
 997    int rc = 0;
 998
 999    loc_push_none(&loc);
1000    QTAILQ_FOREACH(opts, &list->head, next) {
1001        loc_restore(&opts->loc);
1002        rc |= func(opts, opaque);
1003        if (abort_on_failure  &&  rc != 0)
1004            break;
1005    }
1006    loc_pop(&loc);
1007    return rc;
1008}
1009