From be46676df5c4e4c75a9fe46ac7c0221aae78051b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Tue, 7 Jun 2011 23:41:12 +0400 Subject: [PATCH] kvm tools: Options parser to handle hex numbers Some kernel parameters are convenient if passed in hex form so our options parser should handle even such form of input. Signed-off-by: Cyrill Gorcunov Signed-off-by: Pekka Enberg --- tools/kvm/util/parse-options.c | 102 ++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 20 deletions(-) diff --git a/tools/kvm/util/parse-options.c b/tools/kvm/util/parse-options.c index 7866c55204e0..c2803796ac27 100644 --- a/tools/kvm/util/parse-options.c +++ b/tools/kvm/util/parse-options.c @@ -39,6 +39,84 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, return 0; } +#define numvalue(c) \ + ((c) >= 'a' ? (c) - 'a' + 10 : \ + (c) >= 'A' ? (c) - 'A' + 10 : (c) - '0') + +static u64 readhex(const char *str, bool *error) +{ + char *pos = strchr(str, 'x') + 1; + u64 res = 0; + + while (*pos) { + unsigned int v = numvalue(*pos); + if (v > 16) { + *error = true; + return 0; + } + + res = (res * 16) + v; + pos++; + } + + *error = false; + return res; +} + +static int readnum(const struct option *opt, int flags, + const char *str, char **end) +{ + if (strchr(str, 'x')) { + bool error; + u64 value; + + value = readhex(str, &error); + if (error) + goto enotnum; + + switch (opt->type) { + case OPTION_INTEGER: + *(int *)opt->value = value; + break; + case OPTION_UINTEGER: + *(unsigned int *)opt->value = value; + break; + case OPTION_LONG: + *(long *)opt->value = value; + break; + case OPTION_U64: + *(u64 *)opt->value = value; + break; + default: + goto invcall; + } + } else { + switch (opt->type) { + case OPTION_INTEGER: + *(int *)opt->value = strtol(str, end, 10); + break; + case OPTION_UINTEGER: + *(unsigned int *)opt->value = strtol(str, end, 10); + break; + case OPTION_LONG: + *(long *)opt->value = strtol(str, end, 10); + break; + case OPTION_U64: + *(u64 *)opt->value = strtoull(str, end, 10); + break; + default: + goto invcall; + } + } + + return 0; + +enotnum: + return opterror(opt, "expects a numerical value", flags); +invcall: + return opterror(opt, "invalid numeric conversion", flags); +} + static int get_value(struct parse_opt_ctx_t *p, const struct option *opt, int flags) { @@ -131,11 +209,7 @@ static int get_value(struct parse_opt_ctx_t *p, } if (get_arg(p, opt, flags, &arg)) return -1; - *(int *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return opterror(opt, "expects a numerical value", - flags); - return 0; + return readnum(opt, flags, arg, (char **)&s); case OPTION_UINTEGER: if (unset) { @@ -148,11 +222,7 @@ static int get_value(struct parse_opt_ctx_t *p, } if (get_arg(p, opt, flags, &arg)) return -1; - *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return opterror(opt, - "expects a numerical value", flags); - return 0; + return readnum(opt, flags, arg, (char **)&s); case OPTION_LONG: if (unset) { @@ -165,11 +235,7 @@ static int get_value(struct parse_opt_ctx_t *p, } if (get_arg(p, opt, flags, &arg)) return -1; - *(long *)opt->value = strtol(arg, (char **)&s, 10); - if (*s) - return opterror(opt, - "expects a numerical value", flags); - return 0; + return readnum(opt, flags, arg, (char **)&s); case OPTION_U64: if (unset) { @@ -182,11 +248,7 @@ static int get_value(struct parse_opt_ctx_t *p, } if (get_arg(p, opt, flags, &arg)) return -1; - *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); - if (*s) - return opterror(opt, - "expects a numerical value", flags); - return 0; + return readnum(opt, flags, arg, (char **)&s); case OPTION_END: case OPTION_ARGUMENT: -- 2.39.5