#include "qemu-common.h"
#include "qemu-error.h"
#include "qemu-objects.h"
-#include "qemu-option.h"
#include "error.h"
#include "qerror.h"
+#include "qemu-option-internal.h"
/*
* Extracts the name of an option from the parameter string (p points at the
/* ------------------------------------------------------------------ */
-struct QemuOpt {
- const char *name;
- const char *str;
-
- const QemuOptDesc *desc;
- union {
- bool boolean;
- uint64_t uint;
- } value;
-
- QemuOpts *opts;
- QTAILQ_ENTRY(QemuOpt) next;
-};
-
-struct QemuOpts {
- char *id;
- QemuOptsList *list;
- Location loc;
- QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
- QTAILQ_ENTRY(QemuOpts) next;
-};
-
static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
{
QemuOpt *opt;
return opt ? opt->str : NULL;
}
+bool qemu_opt_has_help_opt(QemuOpts *opts)
+{
+ QemuOpt *opt;
+
+ QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
+ if (is_help_option(opt->name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
{
QemuOpt *opt = qemu_opt_find(opts, name);
return opt->value.uint;
}
-static int qemu_opt_parse(QemuOpt *opt)
+static void qemu_opt_parse(QemuOpt *opt, Error **errp)
{
- Error *local_err = NULL;
-
if (opt->desc == NULL)
- return 0;
+ return;
switch (opt->desc->type) {
case QEMU_OPT_STRING:
/* nothing */
- return 0;
+ return;
case QEMU_OPT_BOOL:
- parse_option_bool(opt->name, opt->str, &opt->value.boolean, &local_err);
+ parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
break;
case QEMU_OPT_NUMBER:
- parse_option_number(opt->name, opt->str, &opt->value.uint,
- &local_err);
+ parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
break;
case QEMU_OPT_SIZE:
- parse_option_size(opt->name, opt->str, &opt->value.uint, &local_err);
+ parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
break;
default:
abort();
}
-
- if (error_is_set(&local_err)) {
- qerror_report_err(local_err);
- error_free(local_err);
- return -1;
- }
-
- return 0;
}
static void qemu_opt_del(QemuOpt *opt)
g_free(opt);
}
-static int opt_set(QemuOpts *opts, const char *name, const char *value,
- bool prepend)
+static void opt_set(QemuOpts *opts, const char *name, const char *value,
+ bool prepend, Error **errp)
{
QemuOpt *opt;
const QemuOptDesc *desc = opts->list->desc;
+ Error *local_err = NULL;
int i;
for (i = 0; desc[i].name != NULL; i++) {
if (i == 0) {
/* empty list -> allow any */;
} else {
- qerror_report(QERR_INVALID_PARAMETER, name);
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER, name);
+ return;
}
}
if (value) {
opt->str = g_strdup(value);
}
- if (qemu_opt_parse(opt) < 0) {
+ qemu_opt_parse(opt, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
qemu_opt_del(opt);
+ }
+}
+
+int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
+{
+ Error *local_err = NULL;
+
+ opt_set(opts, name, value, false, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
}
+
return 0;
}
-int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+ Error **errp)
{
- return opt_set(opts, name, value, false);
+ opt_set(opts, name, value, false, errp);
}
int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
{
char option[128], value[1024];
const char *p,*pe,*pc;
+ Error *local_err = NULL;
for (p = params; *p != '\0'; p++) {
pe = strchr(p, '=');
}
if (strcmp(option, "id") != 0) {
/* store and parse */
- if (opt_set(opts, option, value, prepend) == -1) {
+ opt_set(opts, option, value, prepend, &local_err);
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
return -1;
}
}
assert(opts);
}
+typedef struct OptsFromQDictState {
+ QemuOpts *opts;
+ Error **errp;
+} OptsFromQDictState;
+
static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
{
+ OptsFromQDictState *state = opaque;
char buf[32];
const char *value;
int n;
- if (!strcmp(key, "id")) {
+ if (!strcmp(key, "id") || error_is_set(state->errp)) {
return;
}
default:
return;
}
- qemu_opt_set(opaque, key, value);
+
+ qemu_opt_set_err(state->opts, key, value, state->errp);
}
/*
* Only QStrings, QInts, QFloats and QBools are copied. Entries with
* other types are silently ignored.
*/
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+ Error **errp)
{
- QemuOpts *opts;
+ OptsFromQDictState state;
Error *local_err = NULL;
+ QemuOpts *opts;
opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
&local_err);
if (error_is_set(&local_err)) {
- qerror_report_err(local_err);
- error_free(local_err);
+ error_propagate(errp, local_err);
return NULL;
}
assert(opts != NULL);
- qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
+
+ state.errp = &local_err;
+ state.opts = opts;
+ qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ qemu_opts_del(opts);
+ return NULL;
+ }
+
return opts;
}
/* Validate parsed opts against descriptions where no
* descriptions were provided in the QemuOptsList.
*/
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
{
QemuOpt *opt;
+ Error *local_err = NULL;
assert(opts->list->desc[0].name == NULL);
}
}
if (desc[i].name == NULL) {
- qerror_report(QERR_INVALID_PARAMETER, opt->name);
- return -1;
+ error_set(errp, QERR_INVALID_PARAMETER, opt->name);
+ return;
}
opt->desc = &desc[i];
- if (qemu_opt_parse(opt) < 0) {
- return -1;
+ qemu_opt_parse(opt, &local_err);
+ if (error_is_set(&local_err)) {
+ error_propagate(errp, local_err);
+ return;
}
}
-
- return 0;
}
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,