File:  [Qemu by Fabrice Bellard] / qemu / qemu-option.c
Revision 1.1.1.6 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:33:20 2018 UTC (2 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

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

unix.superglobalmegacorp.com