[PATCH] Add assignment operation to config file parser..

john cooper
2010-02-06T19:07:36Z

This patch reworks support for both assignment and
append in the config file parser. It was motivated
by comments received on the cpu model config file
format.

Commit dc9ca4ba27be4fe6a0284061b8f056c4364fb0d9
changed the behavior of "=" from assign to append.
This patch preserves the ability to append to an
option (however now via "+="), reverts "=" to its
previous behavior, and allows both to interoperate.

Signed-off-by: john cooper <john.cooper@redhat.com>
---

diff --git a/qemu-config.c b/qemu-config.c
index 246fae6..4e53250 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -429,6 +429,7 @@ int qemu_config_parse(FILE *fp)
char line[1024], group[64], id[64], arg[64], value[1024];
QemuOptsList *list = NULL;
QemuOpts *opts = NULL;
+ char append;

while (fgets(line, sizeof(line), fp) != NULL) {
if (line[0] == '\n') {
@@ -455,13 +456,16 @@ int qemu_config_parse(FILE *fp)
opts = qemu_opts_create(list, NULL, 0);
continue;
}
- if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
- /* arg = value */
+ append = 0;
+ if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
+ (sscanf(line, " %63s += \"%1023[^\"]\"", arg, value) == 2 ?
+ append = 1 : 0)) {
+ /* arg = value, arg += value */
if (opts == NULL) {
fprintf(stderr, "no group defined\n");
return -1;
}
- if (qemu_opt_set(opts, arg, value) != 0) {
+ if (_qemu_opt_set(opts, arg, value, append) != 0) {
fprintf(stderr, "failed to set \"%s\" for %s\n",
arg, group);
return -1;
diff --git a/qemu-option.c b/qemu-option.c
index a52a4c4..7c0faed 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -562,7 +562,11 @@ static void qemu_opt_del(QemuOpt *opt)
qemu_free(opt);
}

-int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
+/* add option *name,*value to group *opts. if append add to tail of option
+ * list, else set as sole element (overwrite any existing entries of *name).
+ */
+int _qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
+ char append)
{
QemuOpt *opt;
QemuOptDesc *desc = opts->list->desc;
@@ -582,13 +586,27 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
return -1;
}
}
-
- opt = qemu_mallocz(sizeof(*opt));
- opt->name = qemu_strdup(name);
- opt->opts = opts;
- QTAILQ_INSERT_TAIL(&opts->head, opt, next);
- if (desc[i].name != NULL) {
- opt->desc = desc+i;
+ if (append || !(opt = qemu_opt_find(opts, name))) {
+ opt = qemu_mallocz(sizeof(*opt));
+ opt->name = qemu_strdup(name);
+ opt->opts = opts;
+ QTAILQ_INSERT_TAIL(&opts->head, opt, next);
+ if (desc[i].name != NULL) {
+ opt->desc = desc+i;
+ }
+ } else if (!append) {
+ QemuOpt *p, *next;
+
+ /* assign to reclaimed *opt, remove all other *name defs */
+ QTAILQ_FOREACH_SAFE(p, &opts->head, next, next) {
+ if (p != opt && !strcmp(name, p->name)) {
+ qemu_free((char *)p->str);
+ QTAILQ_REMOVE(&opts->head, p, next);
+ qemu_free((char *)p);
+ }
+ }
+ qemu_free((char *)opt->str);
+ opt->str = NULL;
}
if (value) {
opt->str = qemu_strdup(value);
diff --git a/qemu-option.h b/qemu-option.h
index 666b666..2385b1a 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -104,7 +104,14 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name);
int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval);
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
-int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+int _qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
+ char append);
+static inline int qemu_opt_set(QemuOpts *opts, const char *name,
+ const char *value)
+{
+ return (_qemu_opt_set(opts, name, value, 0));
+}
+
typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
int abort_on_failure);