X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=parse.c;h=f54dae625bbbb59387f035cdb08f9fe1768675e1;hp=9a6494f32db811746ba46303b5f300a83e1ddfc6;hb=4ac23d27a5e5dea73c4db4a4fcc46a6afe645bd0;hpb=3d7174e3c4b8aa4daa36261a8e638b702fac5aba diff --git a/parse.c b/parse.c index 9a6494f3..f54dae62 100644 --- a/parse.c +++ b/parse.c @@ -10,10 +10,13 @@ #include #include #include +#include #include "parse.h" #include "debug.h" #include "options.h" +#include "minmax.h" +#include "lib/ieee754.h" static struct fio_option *__fio_options; @@ -47,14 +50,14 @@ static void show_option_range(struct fio_option *o, int (*logger)(const char *format, ...)) { if (o->type == FIO_OPT_FLOAT_LIST) { - if (isnan(o->minfp) && isnan(o->maxfp)) + if (o->minfp == DBL_MIN && o->maxfp == DBL_MAX) return; logger("%20s: min=%f", "range", o->minfp); - if (!isnan(o->maxfp)) + if (o->maxfp != DBL_MAX) logger(", max=%f", o->maxfp); logger("\n"); - } else { + } else if (!o->posval[0].ival) { if (!o->minval && !o->maxval) return; @@ -136,6 +139,19 @@ static unsigned long get_mult_time(char c) } } +static int is_separator(char c) +{ + switch (c) { + case ':': + case '-': + case ',': + case '/': + return 1; + default: + return 0; + } +} + static unsigned long long __get_mult_bytes(const char *p, void *data, int *percent) { @@ -149,8 +165,13 @@ static unsigned long long __get_mult_bytes(const char *p, void *data, c = strdup(p); - for (i = 0; i < strlen(c); i++) + for (i = 0; i < strlen(c); i++) { c[i] = tolower(c[i]); + if (is_separator(c[i])) { + c[i] = '\0'; + break; + } + } if (!strncmp("pib", c, 3)) { pow = 5; @@ -219,7 +240,7 @@ static unsigned long long get_mult_bytes(const char *str, int len, void *data, /* * Convert string into a floating number. Return 1 for success and 0 otherwise. */ -static int str_to_float(const char *str, double *val) +int str_to_float(const char *str, double *val) { return (1 == sscanf(str, "%lf", val)); } @@ -264,7 +285,7 @@ int check_str_bytes(const char *p, long long *val, void *data) return str_to_decimal(p, val, 1, data); } -static int check_str_time(const char *p, long long *val) +int check_str_time(const char *p, long long *val) { return str_to_decimal(p, val, 0, NULL); } @@ -342,6 +363,11 @@ static int opt_len(const char *str) return (int)(postfix - str); } +static int str_match_len(const struct value_pair *vp, const char *str) +{ + return max(strlen(vp->ival), opt_len(str)); +} + #define val_store(ptr, val, off, or, data) \ do { \ ptr = td_var((data), (off)); \ @@ -355,11 +381,11 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, int first, int more, int curr) { int il, *ilp; - double *flp; + fio_fp64_t *flp; long long ull, *ullp; long ul1, ul2; double uf; - char **cp; + char **cp = NULL; int ret = 0, is_time = 0; const struct value_pair *vp; struct value_pair posval[PARSE_MAX_VP]; @@ -386,7 +412,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, if (!vp->ival || vp->ival[0] == '\0') continue; all_skipped = 0; - if (!strncmp(vp->ival, ptr, opt_len(ptr))) { + if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) { ret = 0; if (o->roff1) { if (vp->or) @@ -425,6 +451,8 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, else ret = check_str_bytes(tmp, &ull, data); + dprint(FD_PARSE, " ret=%d, out=%llu\n", ret, ull); + if (ret) break; @@ -438,6 +466,25 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, " (%u min)\n", ull, o->minval); return 1; } + if (o->posval[0].ival) { + posval_sort(o, posval); + + ret = 1; + for (i = 0; i < PARSE_MAX_VP; i++) { + vp = &posval[i]; + if (!vp->ival || vp->ival[0] == '\0') + continue; + if (vp->oval == ull) { + ret = 0; + break; + } + } + if (ret) { + log_err("fio: value %llu not allowed:\n", ull); + show_option_values(o); + return 1; + } + } if (fn) ret = fn(data, &ull); @@ -493,11 +540,20 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, break; } case FIO_OPT_FLOAT_LIST: { + char *cp2; if (first) { - ul2 = 1; + /* + ** Initialize precision to 0 and zero out list + ** in case specified list is shorter than default + */ + ul2 = 0; ilp = td_var(data, o->off2); *ilp = ul2; + + flp = td_var(data, o->off1); + for(i = 0; i < o->maxlen; i++) + flp[i].u.f = 0.0; } if (curr >= o->maxlen) { log_err("the list exceeding max length %d\n", @@ -508,19 +564,38 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, log_err("not a floating point value: %s\n", ptr); return 1; } - if (!isnan(o->maxfp) && uf > o->maxfp) { + if (uf > o->maxfp) { log_err("value out of range: %f" " (range max: %f)\n", uf, o->maxfp); return 1; } - if (!isnan(o->minfp) && uf < o->minfp) { + if (uf < o->minfp) { log_err("value out of range: %f" " (range min: %f)\n", uf, o->minfp); return 1; } flp = td_var(data, o->off1); - flp[curr] = uf; + flp[curr].u.f = uf; + + dprint(FD_PARSE, " out=%f\n", uf); + + /* + ** Calculate precision for output by counting + ** number of digits after period. Find first + ** period in entire remaining list each time + */ + cp2 = strchr(ptr, '.'); + if (cp2 != NULL) { + int len = 0; + + while (*++cp2 != '\0' && *cp2 >= '0' && *cp2 <= '9') + len++; + + ilp = td_var(data, o->off2); + if (len > *ilp) + *ilp = len; + } break; } @@ -534,8 +609,6 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, cp = td_var(data, o->off1); *cp = strdup(ptr); - } else { - cp = NULL; } if (fn) @@ -549,7 +622,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, if (!vp->ival || vp->ival[0] == '\0') continue; all_skipped = 0; - if (!strncmp(vp->ival, ptr, opt_len(ptr))) { + if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) { char *rest; ret = 0; @@ -676,6 +749,8 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, else il = 1; + dprint(FD_PARSE, " ret=%d, out=%d\n", ret, il); + if (ret) break; @@ -1011,6 +1086,8 @@ int show_cmd_help(struct fio_option *options, const char *name) continue; if (!exec_profile && o->prof_name) continue; + if (exec_profile && !(o->prof_name && !strcmp(exec_profile, o->prof_name))) + continue; if (name) { if (!strcmp(name, o->name) || @@ -1090,8 +1167,8 @@ void option_init(struct fio_option *o) o->maxval = UINT_MAX; } if (o->type == FIO_OPT_FLOAT_LIST) { - o->minfp = NAN; - o->maxfp = NAN; + o->minfp = DBL_MIN; + o->maxfp = DBL_MAX; } if (o->type == FIO_OPT_STR_SET && o->def) { log_err("Option %s: string set option with" @@ -1099,6 +1176,11 @@ void option_init(struct fio_option *o) } if (!o->cb && (!o->off1 && !o->roff1)) log_err("Option %s: neither cb nor offset given\n", o->name); + if (!o->category) { + log_info("Option %s: no category defined. Setting to misc\n", o->name); + o->category = FIO_OPT_C_GENERAL; + o->group = FIO_OPT_G_INVALID; + } if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE || o->type == FIO_OPT_STR_MULTI) return; @@ -1106,10 +1188,6 @@ void option_init(struct fio_option *o) (o->roff1 || o->roff2 || o->roff3 || o->roff4))) { log_err("Option %s: both cb and offset given\n", o->name); } - if (!o->category) { - log_info("Options %s: no category defined. Setting to misc\n", o->name); - o->category = FIO_OPT_C_GENERAL; - } } /*