parse: dump option type when using --debug=parse
[fio.git] / parse.c
diff --git a/parse.c b/parse.c
index e330deae2c805602be5b5df5f4c462c0f773c9e0..a9486de9b7fbea40af8bf98237dcff15d1d0d69d 100644 (file)
--- a/parse.c
+++ b/parse.c
 #include <math.h>
 #include <float.h>
 
+#include "compiler/compiler.h"
 #include "parse.h"
 #include "debug.h"
 #include "options.h"
+#include "optgroup.h"
 #include "minmax.h"
 #include "lib/ieee754.h"
 #include "lib/pow2.h"
 #include "y.tab.h"
 #endif
 
+static const char *opt_type_names[] = {
+       "OPT_INVALID",
+       "OPT_STR",
+       "OPT_STR_MULTI",
+       "OPT_STR_VAL",
+       "OPT_STR_VAL_TIME",
+       "OPT_STR_STORE",
+       "OPT_RANGE",
+       "OPT_INT",
+       "OPT_BOOL",
+       "OPT_FLOAT_LIST",
+       "OPT_STR_SET",
+       "OPT_DEPRECATED",
+       "OPT_UNSUPPORTED",
+};
+
 static struct fio_option *__fio_options;
 
 static int vp_cmp(const void *p1, const void *p2)
@@ -108,6 +126,7 @@ static void show_option_help(struct fio_option *o, int is_err)
                "list of floating point values separated by ':' (opt=5.9:7.8)",
                "no argument (opt)",
                "deprecated",
+               "unsupported",
        };
        size_t (*logger)(const char *format, ...);
 
@@ -133,6 +152,7 @@ static unsigned long long get_mult_time(const char *str, int len,
        const char *p = str;
        char *c;
        unsigned long long mult = 1;
+       int i;
 
        /*
          * Go forward until we hit a non-digit, or +/- sign
@@ -151,7 +171,7 @@ static unsigned long long get_mult_time(const char *str, int len,
        }
 
        c = strdup(p);
-       for (int i = 0; i < strlen(c); i++)
+       for (i = 0; i < strlen(c); i++)
                c[i] = tolower(c[i]);
 
        if (!strncmp("us", c, 2) || !strncmp("usec", c, 4))
@@ -165,7 +185,7 @@ static unsigned long long get_mult_time(const char *str, int len,
        else if (!strcmp("h", c))
                mult = 60 * 60 * 1000000UL;
        else if (!strcmp("d", c))
-               mult = 24 * 60 * 60 * 1000000UL;
+               mult = 24 * 60 * 60 * 1000000ULL;
 
        free(c);
        return mult;
@@ -205,32 +225,50 @@ static unsigned long long __get_mult_bytes(const char *p, void *data,
                }
        }
 
+       /* If kb_base is 1000, use true units.
+        * If kb_base is 1024, use opposite units.
+        */
        if (!strncmp("pib", c, 3)) {
                pow = 5;
-               mult = 1000;
+               if (kb_base == 1000)
+                       mult = 1024;
+               else if (kb_base == 1024)
+                       mult = 1000;
        } else if (!strncmp("tib", c, 3)) {
                pow = 4;
-               mult = 1000;
+               if (kb_base == 1000)
+                       mult = 1024;
+               else if (kb_base == 1024)
+                       mult = 1000;
        } else if (!strncmp("gib", c, 3)) {
                pow = 3;
-               mult = 1000;
+               if (kb_base == 1000)
+                       mult = 1024;
+               else if (kb_base == 1024)
+                       mult = 1000;
        } else if (!strncmp("mib", c, 3)) {
                pow = 2;
-               mult = 1000;
+               if (kb_base == 1000)
+                       mult = 1024;
+               else if (kb_base == 1024)
+                       mult = 1000;
        } else if (!strncmp("kib", c, 3)) {
                pow = 1;
-               mult = 1000;
-       } else if (!strncmp("p", c, 1) || !strncmp("pb", c, 2))
+               if (kb_base == 1000)
+                       mult = 1024;
+               else if (kb_base == 1024)
+                       mult = 1000;
+       } else if (!strncmp("p", c, 1) || !strncmp("pb", c, 2)) {
                pow = 5;
-       else if (!strncmp("t", c, 1) || !strncmp("tb", c, 2))
+       } else if (!strncmp("t", c, 1) || !strncmp("tb", c, 2)) {
                pow = 4;
-       else if (!strncmp("g", c, 1) || !strncmp("gb", c, 2))
+       } else if (!strncmp("g", c, 1) || !strncmp("gb", c, 2)) {
                pow = 3;
-       else if (!strncmp("m", c, 1) || !strncmp("mb", c, 2))
+       } else if (!strncmp("m", c, 1) || !strncmp("mb", c, 2)) {
                pow = 2;
-       else if (!strncmp("k", c, 1) || !strncmp("kb", c, 2))
+       } else if (!strncmp("k", c, 1) || !strncmp("kb", c, 2)) {
                pow = 1;
-       else if (!strncmp("%", c, 1)) {
+       else if (!strncmp("%", c, 1)) {
                *percent = 1;
                free(c);
                return ret;
@@ -448,6 +486,17 @@ static int str_match_len(const struct value_pair *vp, const char *str)
                        *ptr = (val);                   \
        } while (0)
 
+static const char *opt_type_name(struct fio_option *o)
+{
+       compiletime_assert(ARRAY_SIZE(opt_type_names) - 1 == FIO_OPT_UNSUPPORTED,
+                               "opt_type_names[] index");
+
+       if (o->type >= 0 && o->type <= FIO_OPT_UNSUPPORTED)
+               return opt_type_names[o->type];
+
+       return "OPT_UNKNOWN?";
+}
+
 static int __handle_option(struct fio_option *o, const char *ptr, void *data,
                           int first, int more, int curr)
 {
@@ -462,8 +511,8 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data,
        struct value_pair posval[PARSE_MAX_VP];
        int i, all_skipped = 1;
 
-       dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name,
-                                                       o->type, ptr);
+       dprint(FD_PARSE, "__handle_option=%s, type=%s, ptr=%s\n", o->name,
+                                                       opt_type_name(o), ptr);
 
        if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) {
                log_err("Option %s requires an argument\n", o->name);
@@ -483,6 +532,8 @@ 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 (!ptr)
+                               break;
                        if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) {
                                ret = 0;
                                if (o->off1)
@@ -533,8 +584,8 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data,
                        return 1;
                }
                if (o->minval && ull < o->minval) {
-                       log_err("min value out of range: %llu"
-                                       " (%u min)\n", ull, o->minval);
+                       log_err("min value out of range: %lld"
+                                       " (%d min)\n", ull, o->minval);
                        return 1;
                }
                if (o->posval[0].ival) {
@@ -903,6 +954,25 @@ static int handle_option(struct fio_option *o, const char *__ptr, void *data)
        return ret;
 }
 
+struct fio_option *find_option(struct fio_option *options, const char *opt)
+{
+       struct fio_option *o;
+
+       for (o = &options[0]; o->name; o++) {
+               if (!o_match(o, opt))
+                       continue;
+               if (o->type == FIO_OPT_UNSUPPORTED) {
+                       log_err("Option <%s>: %s\n", o->name, o->help);
+                       continue;
+               }
+
+               return o;
+       }
+
+       return NULL;
+}
+
+
 static struct fio_option *get_option(char *opt,
                                     struct fio_option *options, char **post)
 {
@@ -958,8 +1028,27 @@ void sort_options(char **opts, struct fio_option *options, int num_opts)
        __fio_options = NULL;
 }
 
+static void add_to_dump_list(struct fio_option *o, struct flist_head *dump_list,
+                            const char *post)
+{
+       struct print_option *p;
+
+       if (!dump_list)
+               return;
+
+       p = malloc(sizeof(*p));
+       p->name = strdup(o->name);
+       if (post)
+               p->value = strdup(post);
+       else
+               p->value = NULL;
+
+       flist_add_tail(&p->list, dump_list);
+}
+
 int parse_cmd_option(const char *opt, const char *val,
-                    struct fio_option *options, void *data)
+                    struct fio_option *options, void *data,
+                    struct flist_head *dump_list)
 {
        struct fio_option *o;
 
@@ -969,16 +1058,18 @@ int parse_cmd_option(const char *opt, const char *val,
                return 1;
        }
 
-       if (!handle_option(o, val, data))
-               return 0;
+       if (handle_option(o, val, data)) {
+               log_err("fio: failed parsing %s=%s\n", opt, val);
+               return 1;
+       }
 
-       log_err("fio: failed parsing %s=%s\n", opt, val);
-       return 1;
+       add_to_dump_list(o, dump_list, val);
+       return 0;
 }
 
 int parse_option(char *opt, const char *input,
                 struct fio_option *options, struct fio_option **o, void *data,
-                int dump_cmdline)
+                struct flist_head *dump_list)
 {
        char *post;
 
@@ -1004,19 +1095,7 @@ int parse_option(char *opt, const char *input,
                return 1;
        }
 
-       if (dump_cmdline) {
-               const char *delim;
-
-               if (!strcmp("description", (*o)->name))
-                       delim = "\"";
-               else
-                       delim = "";
-
-               log_info("--%s%s", (*o)->name, post ? "" : " ");
-               if (post)
-                       log_info("=%s%s%s ", delim, post, delim);
-       }
-
+       add_to_dump_list(*o, dump_list, post);
        return 0;
 }
 
@@ -1218,10 +1297,12 @@ void fill_default_options(void *data, struct fio_option *options)
                        handle_option(o, o->def, data);
 }
 
-void option_init(struct fio_option *o)
+static void option_init(struct fio_option *o)
 {
-       if (o->type == FIO_OPT_DEPRECATED)
+       if (o->type == FIO_OPT_DEPRECATED || o->type == FIO_OPT_UNSUPPORTED)
                return;
+       if (o->name && !o->lname)
+               log_err("Option %s: missing long option name\n", o->name);
        if (o->type == FIO_OPT_BOOL) {
                o->minval = 0;
                o->maxval = 1;
@@ -1267,6 +1348,23 @@ void options_init(struct fio_option *options)
        }
 }
 
+void options_mem_dupe(struct fio_option *options, void *data)
+{
+       struct fio_option *o;
+       char **ptr;
+
+       dprint(FD_PARSE, "dup options\n");
+
+       for (o = &options[0]; o->name; o++) {
+               if (o->type != FIO_OPT_STR_STORE)
+                       continue;
+
+               ptr = td_var(data, o, o->off1);
+               if (*ptr)
+                       *ptr = strdup(*ptr);
+       }
+}
+
 void options_free(struct fio_option *options, void *data)
 {
        struct fio_option *o;
@@ -1275,7 +1373,7 @@ void options_free(struct fio_option *options, void *data)
        dprint(FD_PARSE, "free options\n");
 
        for (o = &options[0]; o->name; o++) {
-               if (o->type != FIO_OPT_STR_STORE || !o->off1)
+               if (o->type != FIO_OPT_STR_STORE || !o->off1 || o->no_free)
                        continue;
 
                ptr = td_var(data, o, o->off1);