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

unix.superglobalmegacorp.com