File:  [Qemu by Fabrice Bellard] / qemu / qemu-option.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:22:58 2018 UTC (2 years, 6 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0130, HEAD
qemu 0.13.0

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

unix.superglobalmegacorp.com