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