Add section 9 to HOWTO table of contents.
[fio.git] / parse.c
diff --git a/parse.c b/parse.c
index 13783fa6d60c06f1df0fb82dcaf18ac2636750ae..51cefcaef4abd3d93db61e658d5ae4c29b6d437a 100644 (file)
--- a/parse.c
+++ b/parse.c
 #include <limits.h>
 #include <stdlib.h>
 #include <math.h>
+#include <float.h>
 
 #include "parse.h"
 #include "debug.h"
 #include "options.h"
 #include "minmax.h"
+#include "lib/ieee754.h"
 
 static struct fio_option *fio_options;
 extern unsigned int fio_get_kb_base(void *);
@@ -49,11 +51,11 @@ 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 {
@@ -344,6 +346,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));            \
@@ -357,7 +364,7 @@ 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;
@@ -388,7 +395,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)
@@ -495,34 +502,60 @@ 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",
                                        o->maxlen);
                        return 1;
                }
-               if (!str_to_float(ptr, &uf)){
+               if (!str_to_float(ptr, &uf)) {
                        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;
+
+               /*
+               ** 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;
        }
@@ -549,7 +582,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;
@@ -1091,8 +1124,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"