From c445909e1f3d5722ed26f067bbffed71cbefd711 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 2 Nov 2020 07:36:48 -0500 Subject: [PATCH] keyval: introduce keyval_parse_into Allow parsing multiple keyval sequences into the same dictionary. This will be used to simplify the parsing of the -M command line option, which is currently a .merge_lists = true QemuOpts group. Signed-off-by: Paolo Bonzini --- include/qemu/option.h | 2 ++ util/keyval.c | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/qemu/option.h b/include/qemu/option.h index d89c66145a..fffb03d848 100644 --- a/include/qemu/option.h +++ b/include/qemu/option.h @@ -147,6 +147,8 @@ void qemu_opts_print_help(QemuOptsList *list, bool print_caption); void qemu_opts_free(QemuOptsList *list); QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list); +QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key, + bool *p_help, Error **errp); QDict *keyval_parse(const char *params, const char *implied_key, bool *help, Error **errp); void keyval_merge(QDict *old, const QDict *new, Error **errp); diff --git a/util/keyval.c b/util/keyval.c index 9bc380686a..904337c8a1 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -511,13 +511,14 @@ static QObject *keyval_listify(QDict *cur, GSList *key_of_cur, Error **errp) * If @p_help is not NULL, store whether help is requested there. * If @p_help is NULL and help is requested, fail. * - * On success, return a dictionary of the parsed keys and values. - * On failure, store an error through @errp and return NULL. + * On success, return @dict, now filled with the parsed keys and values. + * + * On failure, store an error through @errp and return NULL. Any keys + * and values parsed so far will be in @dict nevertheless. */ -QDict *keyval_parse(const char *params, const char *implied_key, - bool *p_help, Error **errp) +QDict *keyval_parse_into(QDict *qdict, const char *params, const char *implied_key, + bool *p_help, Error **errp) { - QDict *qdict = qdict_new(); QObject *listified; const char *s; bool help = false; @@ -526,7 +527,6 @@ QDict *keyval_parse(const char *params, const char *implied_key, while (*s) { s = keyval_parse_one(qdict, s, implied_key, &help, errp); if (!s) { - qobject_unref(qdict); return NULL; } implied_key = NULL; @@ -536,15 +536,42 @@ QDict *keyval_parse(const char *params, const char *implied_key, *p_help = help; } else if (help) { error_setg(errp, "Help is not available for this option"); - qobject_unref(qdict); return NULL; } listified = keyval_listify(qdict, NULL, errp); if (!listified) { - qobject_unref(qdict); return NULL; } assert(listified == QOBJECT(qdict)); return qdict; } + +/* + * Parse @params in QEMU's traditional KEY=VALUE,... syntax. + * + * If @implied_key, the first KEY= can be omitted. @implied_key is + * implied then, and VALUE can't be empty or contain ',' or '='. + * + * A parameter "help" or "?" without a value isn't added to the + * resulting dictionary, but instead is interpreted as help request. + * All other options are parsed and returned normally so that context + * specific help can be printed. + * + * If @p_help is not NULL, store whether help is requested there. + * If @p_help is NULL and help is requested, fail. + * + * On success, return a dictionary of the parsed keys and values. + * On failure, store an error through @errp and return NULL. + */ +QDict *keyval_parse(const char *params, const char *implied_key, + bool *p_help, Error **errp) +{ + QDict *qdict = qdict_new(); + QDict *ret = keyval_parse_into(qdict, params, implied_key, p_help, errp); + + if (!ret) { + qobject_unref(qdict); + } + return ret; +}