[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] rewamp/simplify option parsing
From: |
Michael Tokarev |
Subject: |
[Qemu-devel] [PATCH] rewamp/simplify option parsing |
Date: |
Mon, 12 May 2014 11:55:24 +0400 |
Main change is to allow get_opt_name() to accept
a set of delimiters (string) instead of a single
delimiter (char). This way it is easier to search
for the next (sub)option in an option string, so
other code using get_opt_name() can be simplified.
Signed-off-by: Michael Tokarev <address@hidden>
---
This is an old patch (from Jun 2013) which was
sitting in my local git repository since that.
I rebased it to current master (with 2 trivial
conflicts resolved).
FWIW.
include/qemu/option.h | 3 +-
util/qemu-option.c | 136 +++++++++++++++++++++++--------------------------
vl.c | 4 +-
3 files changed, 67 insertions(+), 76 deletions(-)
diff --git a/include/qemu/option.h b/include/qemu/option.h
index 8c0ac34..24fdec8 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -50,7 +50,8 @@ typedef struct QEMUOptionParameter {
} QEMUOptionParameter;
-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
+const char *get_opt_name(char *buf, int buf_size,
+ const char *p, const char *delim);
const char *get_opt_value(char *buf, int buf_size, const char *p);
int get_next_param_value(char *buf, int buf_size,
const char *tag, const char **pstr);
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 324e4c5..332b177 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -37,27 +37,25 @@
* Extracts the name of an option from the parameter string (p points at the
* first byte of the option name)
*
- * The option name is delimited by delim (usually , or =) or the string end
+ * The option name is delimited by delim (usually "=,") or the string end
* and is copied into buf. If the option name is longer than buf_size, it is
* truncated. buf is always zero terminated.
*
* The return value is the position of the delimiter/zero byte after the option
* name in p.
*/
-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
+const char *get_opt_name(char *buf, int buf_size,
+ const char *p, const char *delim)
{
- char *q;
-
- q = buf;
- while (*p != '\0' && *p != delim) {
- if (q && (q - buf) < buf_size - 1)
- *q++ = *p;
- p++;
+ int len = strcspn(p, delim);
+ if (buf_size > len) {
+ buf_size = len;
+ } else {
+ --buf_size;
}
- if (q)
- *q = '\0';
-
- return p;
+ memcpy(buf, p, buf_size);
+ buf[buf_size] = '\0';
+ return p + len;
}
/*
@@ -97,24 +95,27 @@ int get_next_param_value(char *buf, int buf_size,
p = *pstr;
for(;;) {
- p = get_opt_name(option, sizeof(option), p, '=');
- if (*p != '=')
- break;
- p++;
- if (!strcmp(tag, option)) {
- *pstr = get_opt_value(buf, buf_size, p);
- if (**pstr == ',') {
- (*pstr)++;
+ if (*p == '\0') {
+ return 0;
+ }
+ p = get_opt_name(option, sizeof(option), p, "=,");
+ if (strcmp(tag, option) == 0) {
+ if (*p == '=') {
+ p = get_opt_value(buf, buf_size, p + 1);
+ } else {
+ buf[0] = '\0';
}
- return strlen(buf);
+ *pstr = *p == ',' ? p + 1 : p;
+ return 1;
} else {
- p = get_opt_value(NULL, 0, p);
+ if (*p == '=') {
+ p = get_opt_value(NULL, 0, p + 1);
+ }
+ if (*p == ',') {
+ ++p;
+ }
}
- if (*p != ',')
- break;
- p++;
}
- return 0;
}
int get_param_value(char *buf, int buf_size,
@@ -399,8 +400,7 @@ QEMUOptionParameter *parse_option_parameters(const char
*param,
QEMUOptionParameter *allocated = NULL;
char name[256];
char value[256];
- char *param_delim, *value_delim;
- char next_delim;
+ char *value_p;
int i;
if (list == NULL) {
@@ -417,27 +417,19 @@ QEMUOptionParameter *parse_option_parameters(const char
*param,
while (*param) {
- // Find parameter name and value in the string
- param_delim = strchr(param, ',');
- value_delim = strchr(param, '=');
-
- if (value_delim && (value_delim < param_delim || !param_delim)) {
- next_delim = '=';
- } else {
- next_delim = ',';
- value_delim = NULL;
- }
-
- param = get_opt_name(name, sizeof(name), param, next_delim);
- if (value_delim) {
+ param = get_opt_name(name, sizeof(name), param, "=,");
+ if (*param == '=') {
param = get_opt_value(value, sizeof(value), param + 1);
+ value_p = value;
+ } else {
+ value_p = NULL;
}
if (*param != '\0') {
param++;
}
// Set the parameter
- if (set_option_parameter(dest, name, value_delim ? value : NULL)) {
+ if (set_option_parameter(dest, name, value_p)) {
goto fail;
}
}
@@ -911,49 +903,47 @@ int qemu_opts_print(QemuOpts *opts, void *dummy)
static int opts_do_parse(QemuOpts *opts, const char *params,
const char *firstname, bool prepend)
{
- char option[128], value[1024];
- const char *p,*pe,*pc;
+ char buf[1024+128], *bp;
+ const char *opt, *val;
+ const char *p = params;
+ bool first = true;
Error *local_err = NULL;
- for (p = params; *p != '\0'; p++) {
- pe = strchr(p, '=');
- pc = strchr(p, ',');
- if (!pe || (pc && pc < pe)) {
+ while (*p != '\0') {
+ p = get_opt_name(buf, sizeof(buf), p, "=,");
+ if (*p == '=') {
+ /* found "foo=bar,more" */
+ opt = buf;
+ bp = buf + strlen(buf) + 1;
+ p = get_opt_value(bp, buf + sizeof(buf) - bp, p + 1);
+ val = bp;
+ } else if (first && firstname) {
/* found "foo,more" */
- if (p == params && firstname) {
- /* implicitly named first option */
- pstrcpy(option, sizeof(option), firstname);
- p = get_opt_value(value, sizeof(value), p);
- } else {
- /* option without value, probably a flag */
- p = get_opt_name(option, sizeof(option), p, ',');
- if (strncmp(option, "no", 2) == 0) {
- memmove(option, option+2, strlen(option+2)+1);
- pstrcpy(value, sizeof(value), "off");
- } else {
- pstrcpy(value, sizeof(value), "on");
- }
- }
+ /* implicitly named first option */
+ val = buf;
+ opt = firstname;
} else {
- /* found "foo=bar,more" */
- p = get_opt_name(option, sizeof(option), p, '=');
- if (*p != '=') {
- break;
+ /* option without value, probably a flag */
+ if (strncmp(buf, "no", 2) == 0) {
+ opt = buf + 2;
+ val = "off";
+ } else {
+ opt = buf;
+ val = "on";
}
- p++;
- p = get_opt_value(value, sizeof(value), p);
}
- if (strcmp(option, "id") != 0) {
+ if (strcmp(opt, "id") != 0) {
/* store and parse */
- opt_set(opts, option, value, prepend, &local_err);
+ opt_set(opts, opt, val, prepend, &local_err);
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
}
}
- if (*p != ',') {
- break;
+ first = false;
+ if (*p == ',') {
+ ++p;
}
}
return 0;
diff --git a/vl.c b/vl.c
index 73e0661..8d858d2 100644
--- a/vl.c
+++ b/vl.c
@@ -1315,7 +1315,7 @@ static void numa_add(const char *optarg)
char *endptr;
unsigned long long nodenr;
- optarg = get_opt_name(option, 128, optarg, ',');
+ optarg = get_opt_name(option, sizeof(option), optarg, ",");
if (*optarg == ',') {
optarg++;
}
@@ -2757,7 +2757,7 @@ static int configure_accelerator(MachineClass *mc)
if (*p == ':') {
p++;
}
- p = get_opt_name(buf, sizeof (buf), p, ':');
+ p = get_opt_name(buf, sizeof(buf), p, ":");
for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
if (strcmp(accel_list[i].opt_name, buf) == 0) {
if (!accel_list[i].available()) {
--
1.7.10.4
- [Qemu-devel] [PATCH] rewamp/simplify option parsing,
Michael Tokarev <=