#include "qemu-error.h"
#include "qemu-objects.h"
#include "qemu-option.h"
+#include "qerror.h"
/*
* Extracts the name of an option from the parameter string (p points at the
} else if (!strcmp(value, "off")) {
*ret = 0;
} else {
- fprintf(stderr, "Option '%s': Use 'on' or 'off'\n", name);
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
return -1;
}
} else {
if (value != NULL) {
number = strtoull(value, &postfix, 0);
if (*postfix != '\0') {
- fprintf(stderr, "Option '%s' needs a number as parameter\n", name);
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
return -1;
}
*ret = number;
} else {
- fprintf(stderr, "Option '%s' needs a parameter\n", name);
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
return -1;
}
return 0;
*ret = (uint64_t) sizef;
break;
default:
- fprintf(stderr, "Option '%s' needs size as parameter\n", name);
- fprintf(stderr, "You may use k, M, G or T suffixes for "
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
+ error_printf_unless_qmp("You may use k, M, G or T suffixes for "
"kilobytes, megabytes, gigabytes and terabytes.\n");
return -1;
}
} else {
- fprintf(stderr, "Option '%s' needs a parameter\n", name);
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
return -1;
}
return 0;
case OPT_STRING:
if (value != NULL) {
- list->value.s = qemu_strdup(value);
+ list->value.s = g_strdup(value);
} else {
fprintf(stderr, "Option '%s' needs a parameter\n", name);
return -1;
while (cur && cur->name) {
if (cur->type == OPT_STRING) {
- qemu_free(cur->value.s);
+ g_free(cur->value.s);
}
cur++;
}
- qemu_free(list);
+ g_free(list);
+}
+
+/*
+ * Count valid options in list
+ */
+static size_t count_option_parameters(QEMUOptionParameter *list)
+{
+ size_t num_options = 0;
+
+ while (list && list->name) {
+ num_options++;
+ list++;
+ }
+
+ return num_options;
+}
+
+/*
+ * Append an option list (list) to an option list (dest).
+ *
+ * If dest is NULL, a new copy of list is created.
+ *
+ * Returns a pointer to the first element of dest (or the newly allocated copy)
+ */
+QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
+ QEMUOptionParameter *list)
+{
+ size_t num_options, num_dest_options;
+
+ num_options = count_option_parameters(dest);
+ num_dest_options = num_options;
+
+ num_options += count_option_parameters(list);
+
+ dest = g_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
+ dest[num_dest_options].name = NULL;
+
+ while (list && list->name) {
+ if (get_option_parameter(dest, list->name) == NULL) {
+ dest[num_dest_options++] = *list;
+ dest[num_dest_options].name = NULL;
+ }
+ list++;
+ }
+
+ return dest;
}
/*
* Parses a parameter string (param) into an option list (dest).
*
- * list is the templace is. If dest is NULL, a new copy of list is created for
- * it. If list is NULL, this function fails.
+ * list is the template option list. If dest is NULL, a new copy of list is
+ * created. If list is NULL, this function fails.
*
* A parameter string consists of one or more parameters, separated by commas.
* Each parameter consists of its name and possibly of a value. In the latter
QEMUOptionParameter *parse_option_parameters(const char *param,
QEMUOptionParameter *list, QEMUOptionParameter *dest)
{
- QEMUOptionParameter *cur;
QEMUOptionParameter *allocated = NULL;
char name[256];
char value[256];
char *param_delim, *value_delim;
char next_delim;
- size_t num_options;
if (list == NULL) {
return NULL;
}
if (dest == NULL) {
- // Count valid options
- num_options = 0;
- cur = list;
- while (cur->name) {
- num_options++;
- cur++;
- }
-
- // Create a copy of the option list to fill in values
- dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
- allocated = dest;
- memcpy(dest, list, (num_options + 1) * sizeof(QEMUOptionParameter));
+ dest = allocated = append_option_parameters(NULL, list);
}
while (*param) {
static void qemu_opt_del(QemuOpt *opt)
{
QTAILQ_REMOVE(&opt->opts->head, opt, next);
- qemu_free((/* !const */ char*)opt->name);
- qemu_free((/* !const */ char*)opt->str);
- qemu_free(opt);
+ g_free((/* !const */ char*)opt->name);
+ g_free((/* !const */ char*)opt->str);
+ g_free(opt);
}
int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
if (i == 0) {
/* empty list -> allow any */;
} else {
- fprintf(stderr, "option \"%s\" is not valid for %s\n",
- name, opts->list->name);
+ qerror_report(QERR_INVALID_PARAMETER, name);
return -1;
}
}
- opt = qemu_mallocz(sizeof(*opt));
- opt->name = qemu_strdup(name);
+ opt = g_malloc0(sizeof(*opt));
+ opt->name = g_strdup(name);
opt->opts = opts;
QTAILQ_INSERT_TAIL(&opts->head, opt, next);
if (desc[i].name != NULL) {
opt->desc = desc+i;
}
if (value) {
- opt->str = qemu_strdup(value);
+ opt->str = g_strdup(value);
}
if (qemu_opt_parse(opt) < 0) {
- fprintf(stderr, "Failed to parse \"%s\" for \"%s.%s\"\n", opt->str,
- opts->list->name, opt->name);
qemu_opt_del(opt);
return -1;
}
return NULL;
}
+static int id_wellformed(const char *id)
+{
+ int i;
+
+ if (!qemu_isalpha(id[0])) {
+ return 0;
+ }
+ for (i = 1; id[i]; i++) {
+ if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
{
QemuOpts *opts = NULL;
if (id) {
+ if (!id_wellformed(id)) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+ error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
+ return NULL;
+ }
opts = qemu_opts_find(list, id);
if (opts != NULL) {
if (fail_if_exists) {
- fprintf(stderr, "tried to create id \"%s\" twice for \"%s\"\n",
- id, list->name);
+ qerror_report(QERR_DUPLICATE_ID, id, list->name);
return NULL;
} else {
return opts;
}
}
}
- opts = qemu_mallocz(sizeof(*opts));
+ opts = g_malloc0(sizeof(*opts));
if (id) {
- opts->id = qemu_strdup(id);
+ opts->id = g_strdup(id);
}
opts->list = list;
loc_save(&opts->loc);
return opts;
}
+void qemu_opts_reset(QemuOptsList *list)
+{
+ QemuOpts *opts, *next_opts;
+
+ QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
+ qemu_opts_del(opts);
+ }
+}
+
+void qemu_opts_loc_restore(QemuOpts *opts)
+{
+ loc_restore(&opts->loc);
+}
+
int qemu_opts_set(QemuOptsList *list, const char *id,
const char *name, const char *value)
{
qemu_opt_del(opt);
}
QTAILQ_REMOVE(&opts->list->head, opts, next);
- qemu_free(opts->id);
- qemu_free(opts);
+ g_free(opts->id);
+ g_free(opts);
}
int qemu_opts_print(QemuOpts *opts, void *dummy)
if (strncmp(params, "id=", 3) == 0) {
get_opt_value(value, sizeof(value), params+3);
- id = qemu_strdup(value);
+ id = value;
} else if ((p = strstr(params, ",id=")) != NULL) {
get_opt_value(value, sizeof(value), p+4);
- id = qemu_strdup(value);
+ id = value;
}
opts = qemu_opts_create(list, id, 1);
if (opts == NULL)
}
}
if (desc[i].name == NULL) {
- fprintf(stderr, "option \"%s\" is not valid for %s\n",
- opt->name, opts->list->name);
+ qerror_report(QERR_INVALID_PARAMETER, opt->name);
return -1;
}