From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, imammedo@redhat.com, armbru@redhat.com,
qemu-block@nongnu.org
Subject: [PATCH 16/28] qemu-config: parse configuration files to a QDict
Date: Wed, 2 Dec 2020 04:02:53 -0500 [thread overview]
Message-ID: <20201202090305.4129317-17-pbonzini@redhat.com> (raw)
In-Reply-To: <20201202090305.4129317-1-pbonzini@redhat.com>
Change the parser to put the values into a QDict and pass them
to a callback. qemu_config_parse's QemuOpts creation is
itself turned into a callback function.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
include/qemu/config-file.h | 6 ++-
softmmu/vl.c | 4 +-
util/qemu-config.c | 91 +++++++++++++++++++++++++-------------
3 files changed, 68 insertions(+), 33 deletions(-)
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index da6f4690b7..dcf2948435 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -1,6 +1,7 @@
#ifndef QEMU_CONFIG_FILE_H
#define QEMU_CONFIG_FILE_H
+typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp);
QemuOptsList *qemu_find_opts(const char *group);
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
@@ -12,7 +13,10 @@ int qemu_global_option(const char *str);
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp);
-int qemu_read_config_file(const char *filename, Error **errp);
+/* A default callback for qemu_read_config_file(). */
+void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp);
+
+int qemu_read_config_file(const char *filename, QEMUConfigCB *f, Error **errp);
/* Parse QDict options as a replacement for a config file (allowing multiple
enumerated (0..(n-1)) configuration "sections") */
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 16a5cd1046..771af8bb85 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2051,7 +2051,7 @@ static void qemu_read_default_config_file(Error **errp)
Error *local_err = NULL;
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
- ret = qemu_read_config_file(file, &local_err);
+ ret = qemu_read_config_file(file, qemu_config_do_parse, &local_err);
if (ret < 0) {
if (ret == -ENOENT) {
error_free(local_err);
@@ -3285,7 +3285,7 @@ void qemu_init(int argc, char **argv, char **envp)
qemu_plugin_opt_parse(optarg, &plugin_list);
break;
case QEMU_OPTION_readconfig:
- qemu_read_config_file(optarg, &error_fatal);
+ qemu_read_config_file(optarg, qemu_config_do_parse, &error_fatal);
break;
case QEMU_OPTION_spice:
olist = qemu_find_opts_err("spice", NULL);
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 85f20079de..32d3d6e954 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -314,19 +314,19 @@ void qemu_add_opts(QemuOptsList *list)
}
/* Returns number of config groups on success, -errno on error */
-int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
+static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
+ const char *fname, Error **errp)
{
- char line[1024], group[64], id[64], arg[64], value[1024];
+ char line[1024], prev_group[64], group[64], arg[64], value[1024];
Location loc;
- QemuOptsList *list = NULL;
Error *local_err = NULL;
- QemuOpts *opts = NULL;
+ QDict *qdict = NULL;
int res = -EINVAL, lno = 0;
int count = 0;
loc_push_none(&loc);
while (fgets(line, sizeof(line), fp) != NULL) {
- loc_set_file(fname, ++lno);
+ ++lno;
if (line[0] == '\n') {
/* skip empty lines */
continue;
@@ -335,39 +335,39 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
/* comment */
continue;
}
- if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
- /* group with id */
- list = find_list(lists, group, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
+ if (line[0] == '[') {
+ QDict *prev = qdict;
+ if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
+ qdict = qdict_new();
+ qdict_put_str(qdict, "id", value);
+ count++;
+ } else if (sscanf(line, "[%63[^]]]", group) == 1) {
+ qdict = qdict_new();
+ count++;
}
- opts = qemu_opts_create(list, id, 1, NULL);
- count++;
- continue;
- }
- if (sscanf(line, "[%63[^]]]", group) == 1) {
- /* group without id */
- list = find_list(lists, group, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
+ if (qdict != prev) {
+ if (prev) {
+ cb(prev_group, prev, opaque, &local_err);
+ qobject_unref(prev);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ goto out;
+ }
+ }
+ strcpy(prev_group, group);
+ continue;
}
- opts = qemu_opts_create(list, NULL, 0, &error_abort);
- count++;
- continue;
}
+ loc_set_file(fname, lno);
value[0] = '\0';
if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
sscanf(line, " %63s = \"\"", arg) == 1) {
/* arg = value */
- if (opts == NULL) {
+ if (qdict == NULL) {
error_setg(errp, "no group defined");
goto out;
}
- if (!qemu_opt_set(opts, arg, value, errp)) {
- goto out;
- }
+ qdict_put_str(qdict, arg, value);
continue;
}
error_setg(errp, "parse error");
@@ -380,10 +380,41 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
res = count;
out:
loc_pop(&loc);
+ if (qdict) {
+ cb(group, qdict, opaque, errp);
+ qobject_unref(qdict);
+ }
return res;
}
-int qemu_read_config_file(const char *filename, Error **errp)
+void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
+{
+ QemuOptsList **lists = opaque;
+ const char *id = qdict_get_try_str(qdict, "id");
+ QemuOptsList *list;
+ QemuOpts *opts;
+
+ list = find_list(lists, group, errp);
+ if (!list) {
+ return;
+ }
+
+ opts = qemu_opts_create(list, id, 1, errp);
+ if (!opts) {
+ return;
+ }
+ if (id) {
+ qdict_del(qdict, "id");
+ }
+ qemu_opts_absorb_qdict(opts, qdict, errp);
+}
+
+int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
+{
+ return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
+}
+
+int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
{
FILE *f = fopen(filename, "r");
int ret;
@@ -393,7 +424,7 @@ int qemu_read_config_file(const char *filename, Error **errp)
return -errno;
}
- ret = qemu_config_parse(f, vm_config_groups, filename, errp);
+ ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
fclose(f);
return ret;
}
--
2.26.2
next prev parent reply other threads:[~2020-12-02 10:10 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-02 9:02 [PATCH 00/28] qemu-option, keyval, vl: switch -object/-M/-accel to keyval parsing Paolo Bonzini
2020-12-02 9:02 ` [PATCH 01/28] qemu-option: simplify search for end of key Paolo Bonzini
2020-12-02 9:02 ` [PATCH 02/28] qemu-option: pass QemuOptsList to opts_accepts_any Paolo Bonzini
2020-12-02 9:02 ` [PATCH 03/28] qemu-option: clean up id vs. list->merge_lists Paolo Bonzini
2020-12-02 9:02 ` [PATCH 04/28] qemu-option: move help handling to get_opt_name_value Paolo Bonzini
2020-12-02 9:02 ` [PATCH 05/28] qemu-option: warn for short-form boolean options Paolo Bonzini
2020-12-02 9:02 ` [PATCH 06/28] keyval: accept escaped commas in implied option Paolo Bonzini
2020-12-02 9:02 ` [PATCH 07/28] keyval: simplify keyval_parse_one Paolo Bonzini
2020-12-02 9:02 ` [PATCH 08/28] tests: convert check-qom-proplist to keyval Paolo Bonzini
2020-12-02 9:02 ` [PATCH 09/28] keyval: introduce keyval_parse_into Paolo Bonzini
2020-12-02 9:02 ` [PATCH 10/28] hmp: replace "O" parser with keyval Paolo Bonzini
2020-12-02 9:02 ` [PATCH 11/28] qom: use qemu_printf to print help for user-creatable objects Paolo Bonzini
2020-12-02 9:02 ` [PATCH 12/28] hmp: special case help options for object_add Paolo Bonzini
2020-12-02 9:02 ` [PATCH 13/28] remove -writeconfig Paolo Bonzini
2020-12-02 9:02 ` [PATCH 14/28] qemu-config: add error propagation to qemu_config_parse Paolo Bonzini
2020-12-02 9:02 ` [PATCH 15/28] qemu-option: support accept-any QemuOptsList in qemu_opts_absorb_qdict Paolo Bonzini
2020-12-02 9:02 ` Paolo Bonzini [this message]
2020-12-02 9:02 ` [PATCH 17/28] vl: plumb keyval-based options into -set and -readconfig Paolo Bonzini
2020-12-02 9:02 ` [PATCH 18/28] qom: do not modify QDict argument in user_creatable_add_dict Paolo Bonzini
2020-12-02 9:02 ` [PATCH 19/28] qemu-io: use keyval for -object parsing Paolo Bonzini
2020-12-02 9:02 ` [PATCH 20/28] qemu-nbd: " Paolo Bonzini
2020-12-02 9:02 ` [PATCH 21/28] qemu-img: " Paolo Bonzini
2020-12-02 9:02 ` [PATCH 22/28] qemu: " Paolo Bonzini
2020-12-02 9:03 ` [PATCH 23/28] storage-daemon: do not register the "object" group with QemuOpts Paolo Bonzini
2020-12-02 9:03 ` [PATCH 24/28] qom: export more functions for use with non-UserCreatable objects Paolo Bonzini
2020-12-02 9:03 ` [PATCH 25/28] vl: rename local variable in configure_accelerators Paolo Bonzini
2020-12-02 9:03 ` [PATCH 26/28] vl: switch -M parsing to keyval Paolo Bonzini
2020-12-02 9:03 ` [PATCH 27/28] qemu-option: remove now-dead code Paolo Bonzini
2020-12-02 9:03 ` [PATCH 28/28] vl: switch -accel parsing to keyval Paolo Bonzini
2021-01-17 16:48 ` [PATCH 00/28] qemu-option, keyval, vl: switch -object/-M/-accel to keyval parsing Paolo Bonzini
2021-01-18 10:29 ` Kevin Wolf
2021-01-18 12:47 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201202090305.4129317-17-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=armbru@redhat.com \
--cc=imammedo@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).