Merge branch 'master' into gfio
[fio.git] / parse.c
1 /*
2  * This file contains the ini and command liner parser main.
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <limits.h>
11 #include <stdlib.h>
12 #include <math.h>
13
14 #include "parse.h"
15 #include "debug.h"
16 #include "options.h"
17 #include "minmax.h"
18
19 static struct fio_option *__fio_options;
20
21 static int vp_cmp(const void *p1, const void *p2)
22 {
23         const struct value_pair *vp1 = p1;
24         const struct value_pair *vp2 = p2;
25
26         return strlen(vp2->ival) - strlen(vp1->ival);
27 }
28
29 static void posval_sort(struct fio_option *o, struct value_pair *vpmap)
30 {
31         const struct value_pair *vp;
32         int entries;
33
34         memset(vpmap, 0, PARSE_MAX_VP * sizeof(struct value_pair));
35
36         for (entries = 0; entries < PARSE_MAX_VP; entries++) {
37                 vp = &o->posval[entries];
38                 if (!vp->ival || vp->ival[0] == '\0')
39                         break;
40
41                 memcpy(&vpmap[entries], vp, sizeof(*vp));
42         }
43
44         qsort(vpmap, entries, sizeof(struct value_pair), vp_cmp);
45 }
46
47 static void show_option_range(struct fio_option *o,
48                                 int (*logger)(const char *format, ...))
49 {
50         if (o->type == FIO_OPT_FLOAT_LIST) {
51                 if (isnan(o->minfp) && isnan(o->maxfp))
52                         return;
53
54                 logger("%20s: min=%f", "range", o->minfp);
55                 if (!isnan(o->maxfp))
56                         logger(", max=%f", o->maxfp);
57                 logger("\n");
58         } else {
59                 if (!o->minval && !o->maxval)
60                         return;
61
62                 logger("%20s: min=%d", "range", o->minval);
63                 if (o->maxval)
64                         logger(", max=%d", o->maxval);
65                 logger("\n");
66         }
67 }
68
69 static void show_option_values(struct fio_option *o)
70 {
71         int i;
72
73         for (i = 0; i < PARSE_MAX_VP; i++) {
74                 const struct value_pair *vp = &o->posval[i];
75
76                 if (!vp->ival)
77                         continue;
78
79                 log_info("%20s: %-10s", i == 0 ? "valid values" : "", vp->ival);
80                 if (vp->help)
81                         log_info(" %s", vp->help);
82                 log_info("\n");
83         }
84
85         if (i)
86                 log_info("\n");
87 }
88
89 static void show_option_help(struct fio_option *o, int is_err)
90 {
91         const char *typehelp[] = {
92                 "invalid",
93                 "string (opt=bla)",
94                 "string (opt=bla)",
95                 "string with possible k/m/g postfix (opt=4k)",
96                 "string with time postfix (opt=10s)",
97                 "string (opt=bla)",
98                 "string with dual range (opt=1k-4k,4k-8k)",
99                 "integer value (opt=100)",
100                 "boolean value (opt=1)",
101                 "list of floating point values separated by ':' (opt=5.9:7.8)",
102                 "no argument (opt)",
103                 "deprecated",
104         };
105         int (*logger)(const char *format, ...);
106
107         if (is_err)
108                 logger = log_err;
109         else
110                 logger = log_info;
111
112         if (o->alias)
113                 logger("%20s: %s\n", "alias", o->alias);
114
115         logger("%20s: %s\n", "type", typehelp[o->type]);
116         logger("%20s: %s\n", "default", o->def ? o->def : "no default");
117         if (o->prof_name)
118                 logger("%20s: only for profile '%s'\n", "valid", o->prof_name);
119         show_option_range(o, logger);
120         show_option_values(o);
121 }
122
123 static unsigned long get_mult_time(char c)
124 {
125         switch (c) {
126         case 'm':
127         case 'M':
128                 return 60;
129         case 'h':
130         case 'H':
131                 return 60 * 60;
132         case 'd':
133         case 'D':
134                 return 24 * 60 * 60;
135         default:
136                 return 1;
137         }
138 }
139
140 static unsigned long long __get_mult_bytes(const char *p, void *data,
141                                            int *percent)
142 {
143         unsigned int kb_base = fio_get_kb_base(data);
144         unsigned long long ret = 1;
145         unsigned int i, pow = 0, mult = kb_base;
146         char *c;
147
148         if (!p)
149                 return 1;
150
151         c = strdup(p);
152
153         for (i = 0; i < strlen(c); i++)
154                 c[i] = tolower(c[i]);
155
156         if (!strncmp("pib", c, 3)) {
157                 pow = 5;
158                 mult = 1000;
159         } else if (!strncmp("tib", c, 3)) {
160                 pow = 4;
161                 mult = 1000;
162         } else if (!strncmp("gib", c, 3)) {
163                 pow = 3;
164                 mult = 1000;
165         } else if (!strncmp("mib", c, 3)) {
166                 pow = 2;
167                 mult = 1000;
168         } else if (!strncmp("kib", c, 3)) {
169                 pow = 1;
170                 mult = 1000;
171         } else if (!strncmp("p", c, 1) || !strncmp("pb", c, 2))
172                 pow = 5;
173         else if (!strncmp("t", c, 1) || !strncmp("tb", c, 2))
174                 pow = 4;
175         else if (!strncmp("g", c, 1) || !strncmp("gb", c, 2))
176                 pow = 3;
177         else if (!strncmp("m", c, 1) || !strncmp("mb", c, 2))
178                 pow = 2;
179         else if (!strncmp("k", c, 1) || !strncmp("kb", c, 2))
180                 pow = 1;
181         else if (!strncmp("%", c, 1)) {
182                 *percent = 1;
183                 free(c);
184                 return ret;
185         }
186
187         while (pow--)
188                 ret *= (unsigned long long) mult;
189
190         free(c);
191         return ret;
192 }
193
194 static unsigned long long get_mult_bytes(const char *str, int len, void *data,
195                                          int *percent)
196 {
197         const char *p = str;
198         int digit_seen = 0;
199
200         if (len < 2)
201                 return __get_mult_bytes(str, data, percent);
202
203         /*
204          * Go forward until we hit a non-digit, or +/- sign
205          */
206         while ((p - str) <= len) {
207                 if (!isdigit((int) *p) &&
208                     (((*p != '+') && (*p != '-')) || digit_seen))
209                         break;
210                 digit_seen |= isdigit((int) *p);
211                 p++;
212         }
213
214         if (!isalpha((int) *p) && (*p != '%'))
215                 p = NULL;
216
217         return __get_mult_bytes(p, data, percent);
218 }
219
220 /*
221  * Convert string into a floating number. Return 1 for success and 0 otherwise.
222  */
223 int str_to_float(const char *str, double *val)
224 {
225         return (1 == sscanf(str, "%lf", val));
226 }
227
228 /*
229  * convert string into decimal value, noting any size suffix
230  */
231 int str_to_decimal(const char *str, long long *val, int kilo, void *data)
232 {
233         int len, base;
234
235         len = strlen(str);
236         if (!len)
237                 return 1;
238
239         if (strstr(str, "0x") || strstr(str, "0X"))
240                 base = 16;
241         else
242                 base = 10;
243
244         *val = strtoll(str, NULL, base);
245         if (*val == LONG_MAX && errno == ERANGE)
246                 return 1;
247
248         if (kilo) {
249                 unsigned long long mult;
250                 int perc = 0;
251
252                 mult = get_mult_bytes(str, len, data, &perc);
253                 if (perc)
254                         *val = -1ULL - *val;
255                 else
256                         *val *= mult;
257         } else
258                 *val *= get_mult_time(str[len - 1]);
259
260         return 0;
261 }
262
263 int check_str_bytes(const char *p, long long *val, void *data)
264 {
265         return str_to_decimal(p, val, 1, data);
266 }
267
268 static int check_str_time(const char *p, long long *val)
269 {
270         return str_to_decimal(p, val, 0, NULL);
271 }
272
273 void strip_blank_front(char **p)
274 {
275         char *s = *p;
276
277         if (!strlen(s))
278                 return;
279         while (isspace((int) *s))
280                 s++;
281
282         *p = s;
283 }
284
285 void strip_blank_end(char *p)
286 {
287         char *start = p, *s;
288
289         if (!strlen(p))
290                 return;
291
292         s = strchr(p, ';');
293         if (s)
294                 *s = '\0';
295         s = strchr(p, '#');
296         if (s)
297                 *s = '\0';
298         if (s)
299                 p = s;
300
301         s = p + strlen(p);
302         while ((isspace((int) *s) || iscntrl((int) *s)) && (s > start))
303                 s--;
304
305         *(s + 1) = '\0';
306 }
307
308 static int check_range_bytes(const char *str, long *val, void *data)
309 {
310         long long __val;
311
312         if (!str_to_decimal(str, &__val, 1, data)) {
313                 *val = __val;
314                 return 0;
315         }
316
317         return 1;
318 }
319
320 static int check_int(const char *p, int *val)
321 {
322         if (!strlen(p))
323                 return 1;
324         if (strstr(p, "0x") || strstr(p, "0X")) {
325                 if (sscanf(p, "%x", val) == 1)
326                         return 0;
327         } else {
328                 if (sscanf(p, "%u", val) == 1)
329                         return 0;
330         }
331
332         return 1;
333 }
334
335 static int opt_len(const char *str)
336 {
337         char *postfix;
338
339         postfix = strchr(str, ':');
340         if (!postfix)
341                 return strlen(str);
342
343         return (int)(postfix - str);
344 }
345
346 static int str_match_len(const struct value_pair *vp, const char *str)
347 {
348         return max(strlen(vp->ival), opt_len(str));
349 }
350
351 #define val_store(ptr, val, off, or, data)              \
352         do {                                            \
353                 ptr = td_var((data), (off));            \
354                 if ((or))                               \
355                         *ptr |= (val);                  \
356                 else                                    \
357                         *ptr = (val);                   \
358         } while (0)
359
360 static int __handle_option(struct fio_option *o, const char *ptr, void *data,
361                            int first, int more, int curr)
362 {
363         int il, *ilp;
364         double *flp;
365         long long ull, *ullp;
366         long ul1, ul2;
367         double uf;
368         char **cp = NULL;
369         int ret = 0, is_time = 0;
370         const struct value_pair *vp;
371         struct value_pair posval[PARSE_MAX_VP];
372         int i, all_skipped = 1;
373
374         dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name,
375                                                         o->type, ptr);
376
377         if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) {
378                 log_err("Option %s requires an argument\n", o->name);
379                 return 1;
380         }
381
382         switch (o->type) {
383         case FIO_OPT_STR:
384         case FIO_OPT_STR_MULTI: {
385                 fio_opt_str_fn *fn = o->cb;
386
387                 posval_sort(o, posval);
388
389                 ret = 1;
390                 for (i = 0; i < PARSE_MAX_VP; i++) {
391                         vp = &posval[i];
392                         if (!vp->ival || vp->ival[0] == '\0')
393                                 continue;
394                         all_skipped = 0;
395                         if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) {
396                                 ret = 0;
397                                 if (o->roff1) {
398                                         if (vp->or)
399                                                 *(unsigned int *) o->roff1 |= vp->oval;
400                                         else
401                                                 *(unsigned int *) o->roff1 = vp->oval;
402                                 } else {
403                                         if (!o->off1)
404                                                 continue;
405                                         val_store(ilp, vp->oval, o->off1, vp->or, data);
406                                 }
407                                 continue;
408                         }
409                 }
410
411                 if (ret && !all_skipped)
412                         show_option_values(o);
413                 else if (fn)
414                         ret = fn(data, ptr);
415                 break;
416         }
417         case FIO_OPT_STR_VAL_TIME:
418                 is_time = 1;
419         case FIO_OPT_INT:
420         case FIO_OPT_STR_VAL: {
421                 fio_opt_str_val_fn *fn = o->cb;
422                 char tmp[128], *p;
423
424                 strncpy(tmp, ptr, sizeof(tmp) - 1);
425                 p = strchr(tmp, ',');
426                 if (p)
427                         *p = '\0';
428
429                 if (is_time)
430                         ret = check_str_time(tmp, &ull);
431                 else
432                         ret = check_str_bytes(tmp, &ull, data);
433
434                 if (ret)
435                         break;
436
437                 if (o->maxval && ull > o->maxval) {
438                         log_err("max value out of range: %llu"
439                                         " (%u max)\n", ull, o->maxval);
440                         return 1;
441                 }
442                 if (o->minval && ull < o->minval) {
443                         log_err("min value out of range: %llu"
444                                         " (%u min)\n", ull, o->minval);
445                         return 1;
446                 }
447
448                 if (fn)
449                         ret = fn(data, &ull);
450                 else {
451                         if (o->type == FIO_OPT_INT) {
452                                 if (first) {
453                                         if (o->roff1)
454                                                 *(unsigned int *) o->roff1 = ull;
455                                         else
456                                                 val_store(ilp, ull, o->off1, 0, data);
457                                 }
458                                 if (curr == 1) {
459                                         if (o->roff2)
460                                                 *(unsigned int *) o->roff2 = ull;
461                                         else if (o->off2)
462                                                 val_store(ilp, ull, o->off2, 0, data);
463                                 }
464                                 if (curr == 2) {
465                                         if (o->roff3)
466                                                 *(unsigned int *) o->roff3 = ull;
467                                         else if (o->off3)
468                                                 val_store(ilp, ull, o->off3, 0, data);
469                                 }
470                                 if (!more) {
471                                         if (curr < 1) {
472                                                 if (o->roff2)
473                                                         *(unsigned int *) o->roff2 = ull;
474                                                 else if (o->off2)
475                                                         val_store(ilp, ull, o->off2, 0, data);
476                                         }
477                                         if (curr < 2) {
478                                                 if (o->roff3)
479                                                         *(unsigned int *) o->roff3 = ull;
480                                                 else if (o->off3)
481                                                         val_store(ilp, ull, o->off3, 0, data);
482                                         }
483                                 }
484                         } else {
485                                 if (first) {
486                                         if (o->roff1)
487                                                 *(unsigned long long *) o->roff1 = ull;
488                                         else
489                                                 val_store(ullp, ull, o->off1, 0, data);
490                                 }
491                                 if (!more) {
492                                         if (o->roff2)
493                                                 *(unsigned long long *) o->roff2 =  ull;
494                                         else if (o->off2)
495                                                 val_store(ullp, ull, o->off2, 0, data);
496                                 }
497                         }
498                 }
499                 break;
500         }
501         case FIO_OPT_FLOAT_LIST: {
502
503                 if (first) {
504                         ul2 = 1;
505                         ilp = td_var(data, o->off2);
506                         *ilp = ul2;
507                 }
508                 if (curr >= o->maxlen) {
509                         log_err("the list exceeding max length %d\n",
510                                         o->maxlen);
511                         return 1;
512                 }
513                 if (!str_to_float(ptr, &uf)) {
514                         log_err("not a floating point value: %s\n", ptr);
515                         return 1;
516                 }
517                 if (!isnan(o->maxfp) && uf > o->maxfp) {
518                         log_err("value out of range: %f"
519                                 " (range max: %f)\n", uf, o->maxfp);
520                         return 1;
521                 }
522                 if (!isnan(o->minfp) && uf < o->minfp) {
523                         log_err("value out of range: %f"
524                                 " (range min: %f)\n", uf, o->minfp);
525                         return 1;
526                 }
527
528                 flp = td_var(data, o->off1);
529                 flp[curr] = uf;
530
531                 break;
532         }
533         case FIO_OPT_STR_STORE: {
534                 fio_opt_str_fn *fn = o->cb;
535
536                 if (o->roff1 || o->off1) {
537                         if (o->roff1)
538                                 cp = (char **) o->roff1;
539                         else if (o->off1)
540                                 cp = td_var(data, o->off1);
541
542                         *cp = strdup(ptr);
543                 }
544
545                 if (fn)
546                         ret = fn(data, ptr);
547                 else if (o->posval[0].ival) {
548                         posval_sort(o, posval);
549
550                         ret = 1;
551                         for (i = 0; i < PARSE_MAX_VP; i++) {
552                                 vp = &posval[i];
553                                 if (!vp->ival || vp->ival[0] == '\0')
554                                         continue;
555                                 all_skipped = 0;
556                                 if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) {
557                                         char *rest;
558
559                                         ret = 0;
560                                         if (vp->cb)
561                                                 fn = vp->cb;
562                                         rest = strstr(*cp ?: ptr, ":");
563                                         if (rest) {
564                                                 if (*cp)
565                                                         *rest = '\0';
566                                                 ptr = rest + 1;
567                                         } else
568                                                 ptr = NULL;
569                                         break;
570                                 }
571                         }
572                 }
573
574                 if (!all_skipped) {
575                         if (ret && !*cp)
576                                 show_option_values(o);
577                         else if (ret && *cp)
578                                 ret = 0;
579                         else if (fn && ptr)
580                                 ret = fn(data, ptr);
581                 }
582
583                 break;
584         }
585         case FIO_OPT_RANGE: {
586                 char tmp[128];
587                 char *p1, *p2;
588
589                 strncpy(tmp, ptr, sizeof(tmp) - 1);
590
591                 /* Handle bsrange with separate read,write values: */
592                 p1 = strchr(tmp, ',');
593                 if (p1)
594                         *p1 = '\0';
595
596                 p1 = strchr(tmp, '-');
597                 if (!p1) {
598                         p1 = strchr(tmp, ':');
599                         if (!p1) {
600                                 ret = 1;
601                                 break;
602                         }
603                 }
604
605                 p2 = p1 + 1;
606                 *p1 = '\0';
607                 p1 = tmp;
608
609                 ret = 1;
610                 if (!check_range_bytes(p1, &ul1, data) &&
611                     !check_range_bytes(p2, &ul2, data)) {
612                         ret = 0;
613                         if (ul1 > ul2) {
614                                 unsigned long foo = ul1;
615
616                                 ul1 = ul2;
617                                 ul2 = foo;
618                         }
619
620                         if (first) {
621                                 if (o->roff1)
622                                         *(unsigned int *) o->roff1 = ul1;
623                                 else
624                                         val_store(ilp, ul1, o->off1, 0, data);
625                                 if (o->roff2)
626                                         *(unsigned int *) o->roff2 = ul2;
627                                 else
628                                         val_store(ilp, ul2, o->off2, 0, data);
629                         }
630                         if (curr == 1) {
631                                 if (o->roff3 && o->roff4) {
632                                         *(unsigned int *) o->roff3 = ul1;
633                                         *(unsigned int *) o->roff4 = ul2;
634                                 } else if (o->off3 && o->off4) {
635                                         val_store(ilp, ul1, o->off3, 0, data);
636                                         val_store(ilp, ul2, o->off4, 0, data);
637                                 }
638                         }
639                         if (curr == 2) {
640                                 if (o->roff5 && o->roff6) {
641                                         *(unsigned int *) o->roff5 = ul1;
642                                         *(unsigned int *) o->roff6 = ul2;
643                                 } else if (o->off5 && o->off6) {
644                                         val_store(ilp, ul1, o->off5, 0, data);
645                                         val_store(ilp, ul2, o->off6, 0, data);
646                                 }
647                         }
648                         if (!more) {
649                                 if (curr < 1) {
650                                         if (o->roff3 && o->roff4) {
651                                                 *(unsigned int *) o->roff3 = ul1;
652                                                 *(unsigned int *) o->roff4 = ul2;
653                                         } else if (o->off3 && o->off4) {
654                                                 val_store(ilp, ul1, o->off3, 0, data);
655                                                 val_store(ilp, ul2, o->off4, 0, data);
656                                         }
657                                 }
658                                 if (curr < 2) {
659                                         if (o->roff5 && o->roff6) {
660                                                 *(unsigned int *) o->roff5 = ul1;
661                                                 *(unsigned int *) o->roff6 = ul2;
662                                         } else if (o->off5 && o->off6) {
663                                                 val_store(ilp, ul1, o->off5, 0, data);
664                                                 val_store(ilp, ul2, o->off6, 0, data);
665                                         }
666                                 }
667                         }
668                 }
669
670                 break;
671         }
672         case FIO_OPT_BOOL:
673         case FIO_OPT_STR_SET: {
674                 fio_opt_int_fn *fn = o->cb;
675
676                 if (ptr)
677                         ret = check_int(ptr, &il);
678                 else if (o->type == FIO_OPT_BOOL)
679                         ret = 1;
680                 else
681                         il = 1;
682
683                 if (ret)
684                         break;
685
686                 if (o->maxval && il > (int) o->maxval) {
687                         log_err("max value out of range: %d (%d max)\n",
688                                                                 il, o->maxval);
689                         return 1;
690                 }
691                 if (o->minval && il < o->minval) {
692                         log_err("min value out of range: %d (%d min)\n",
693                                                                 il, o->minval);
694                         return 1;
695                 }
696
697                 if (o->neg)
698                         il = !il;
699
700                 if (fn)
701                         ret = fn(data, &il);
702                 else {
703                         if (first) {
704                                 if (o->roff1)
705                                         *(unsigned int *)o->roff1 = il;
706                                 else
707                                         val_store(ilp, il, o->off1, 0, data);
708                         }
709                         if (!more) {
710                                 if (o->roff2)
711                                         *(unsigned int *) o->roff2 = il;
712                                 else if (o->off2)
713                                         val_store(ilp, il, o->off2, 0, data);
714                         }
715                 }
716                 break;
717         }
718         case FIO_OPT_DEPRECATED:
719                 log_info("Option %s is deprecated\n", o->name);
720                 break;
721         default:
722                 log_err("Bad option type %u\n", o->type);
723                 ret = 1;
724         }
725
726         if (ret)
727                 return ret;
728
729         if (o->verify) {
730                 ret = o->verify(o, data);
731                 if (ret) {
732                         log_err("Correct format for offending option\n");
733                         log_err("%20s: %s\n", o->name, o->help);
734                         show_option_help(o, 1);
735                 }
736         }
737
738         return ret;
739 }
740
741 static int handle_option(struct fio_option *o, const char *__ptr, void *data)
742 {
743         char *o_ptr, *ptr, *ptr2;
744         int ret, done;
745
746         dprint(FD_PARSE, "handle_option=%s, ptr=%s\n", o->name, __ptr);
747
748         o_ptr = ptr = NULL;
749         if (__ptr)
750                 o_ptr = ptr = strdup(__ptr);
751
752         /*
753          * See if we have another set of parameters, hidden after a comma.
754          * Do this before parsing this round, to check if we should
755          * copy set 1 options to set 2.
756          */
757         done = 0;
758         ret = 1;
759         do {
760                 int __ret;
761
762                 ptr2 = NULL;
763                 if (ptr &&
764                     (o->type != FIO_OPT_STR_STORE) &&
765                     (o->type != FIO_OPT_STR) &&
766                     (o->type != FIO_OPT_FLOAT_LIST)) {
767                         ptr2 = strchr(ptr, ',');
768                         if (ptr2 && *(ptr2 + 1) == '\0')
769                                 *ptr2 = '\0';
770                         if (o->type != FIO_OPT_STR_MULTI && o->type != FIO_OPT_RANGE) {
771                                 if (!ptr2)
772                                         ptr2 = strchr(ptr, ':');
773                                 if (!ptr2)
774                                         ptr2 = strchr(ptr, '-');
775                         }
776                 } else if (ptr && o->type == FIO_OPT_FLOAT_LIST) {
777                         ptr2 = strchr(ptr, ':');
778                 }
779
780                 /*
781                  * Don't return early if parsing the first option fails - if
782                  * we are doing multiple arguments, we can allow the first one
783                  * being empty.
784                  */
785                 __ret = __handle_option(o, ptr, data, !done, !!ptr2, done);
786                 if (ret)
787                         ret = __ret;
788
789                 if (!ptr2)
790                         break;
791
792                 ptr = ptr2 + 1;
793                 done++;
794         } while (1);
795
796         if (o_ptr)
797                 free(o_ptr);
798         return ret;
799 }
800
801 static struct fio_option *get_option(char *opt,
802                                      struct fio_option *options, char **post)
803 {
804         struct fio_option *o;
805         char *ret;
806
807         ret = strchr(opt, '=');
808         if (ret) {
809                 *post = ret;
810                 *ret = '\0';
811                 ret = opt;
812                 (*post)++;
813                 strip_blank_end(ret);
814                 o = find_option(options, ret);
815         } else {
816                 o = find_option(options, opt);
817                 *post = NULL;
818         }
819
820         return o;
821 }
822
823 static int opt_cmp(const void *p1, const void *p2)
824 {
825         struct fio_option *o;
826         char *s, *foo;
827         int prio1, prio2;
828
829         prio1 = prio2 = 0;
830
831         if (*(char **)p1) {
832                 s = strdup(*((char **) p1));
833                 o = get_option(s, __fio_options, &foo);
834                 if (o)
835                         prio1 = o->prio;
836                 free(s);
837         }
838         if (*(char **)p2) {
839                 s = strdup(*((char **) p2));
840                 o = get_option(s, __fio_options, &foo);
841                 if (o)
842                         prio2 = o->prio;
843                 free(s);
844         }
845
846         return prio2 - prio1;
847 }
848
849 void sort_options(char **opts, struct fio_option *options, int num_opts)
850 {
851         __fio_options = options;
852         qsort(opts, num_opts, sizeof(char *), opt_cmp);
853         __fio_options = NULL;
854 }
855
856 int parse_cmd_option(const char *opt, const char *val,
857                      struct fio_option *options, void *data)
858 {
859         struct fio_option *o;
860
861         o = find_option(options, opt);
862         if (!o) {
863                 log_err("Bad option <%s>\n", opt);
864                 return 1;
865         }
866
867         if (!handle_option(o, val, data))
868                 return 0;
869
870         log_err("fio: failed parsing %s=%s\n", opt, val);
871         return 1;
872 }
873
874 int parse_option(char *opt, const char *input,
875                  struct fio_option *options, struct fio_option **o, void *data)
876 {
877         char *post;
878
879         if (!opt) {
880                 log_err("fio: failed parsing %s\n", input);
881                 *o = NULL;
882                 return 1;
883         }
884
885         *o = get_option(opt, options, &post);
886         if (!*o) {
887                 if (post) {
888                         int len = strlen(opt);
889                         if (opt + len + 1 != post)
890                                 memmove(opt + len + 1, post, strlen(post));
891                         opt[len] = '=';
892                 }
893                 return 1;
894         }
895
896         if (!handle_option(*o, post, data))
897                 return 0;
898
899         log_err("fio: failed parsing %s\n", input);
900         return 1;
901 }
902
903 /*
904  * Option match, levenshtein distance. Handy for not quite remembering what
905  * the option name is.
906  */
907 static int string_distance(const char *s1, const char *s2)
908 {
909         unsigned int s1_len = strlen(s1);
910         unsigned int s2_len = strlen(s2);
911         unsigned int *p, *q, *r;
912         unsigned int i, j;
913
914         p = malloc(sizeof(unsigned int) * (s2_len + 1));
915         q = malloc(sizeof(unsigned int) * (s2_len + 1));
916
917         p[0] = 0;
918         for (i = 1; i <= s2_len; i++)
919                 p[i] = p[i - 1] + 1;
920
921         for (i = 1; i <= s1_len; i++) {
922                 q[0] = p[0] + 1;
923                 for (j = 1; j <= s2_len; j++) {
924                         unsigned int sub = p[j - 1];
925
926                         if (s1[i - 1] != s2[j - 1])
927                                 sub++;
928
929                         q[j] = min(p[j] + 1, min(q[j - 1] + 1, sub));
930                 }
931                 r = p;
932                 p = q;
933                 q = r;
934         }
935
936         i = p[s2_len];
937         free(p);
938         free(q);
939         return i;
940 }
941
942 static struct fio_option *find_child(struct fio_option *options,
943                                      struct fio_option *o)
944 {
945         struct fio_option *__o;
946
947         for (__o = options + 1; __o->name; __o++)
948                 if (__o->parent && !strcmp(__o->parent, o->name))
949                         return __o;
950
951         return NULL;
952 }
953
954 static void __print_option(struct fio_option *o, struct fio_option *org,
955                            int level)
956 {
957         char name[256], *p;
958         int depth;
959
960         if (!o)
961                 return;
962         if (!org)
963                 org = o;
964
965         p = name;
966         depth = level;
967         while (depth--)
968                 p += sprintf(p, "%s", "  ");
969
970         sprintf(p, "%s", o->name);
971
972         log_info("%-24s: %s\n", name, o->help);
973 }
974
975 static void print_option(struct fio_option *o)
976 {
977         struct fio_option *parent;
978         struct fio_option *__o;
979         unsigned int printed;
980         unsigned int level;
981
982         __print_option(o, NULL, 0);
983         parent = o;
984         level = 0;
985         do {
986                 level++;
987                 printed = 0;
988
989                 while ((__o = find_child(o, parent)) != NULL) {
990                         __print_option(__o, o, level);
991                         o = __o;
992                         printed++;
993                 }
994
995                 parent = o;
996         } while (printed);
997 }
998
999 int show_cmd_help(struct fio_option *options, const char *name)
1000 {
1001         struct fio_option *o, *closest;
1002         unsigned int best_dist = -1U;
1003         int found = 0;
1004         int show_all = 0;
1005
1006         if (!name || !strcmp(name, "all"))
1007                 show_all = 1;
1008
1009         closest = NULL;
1010         best_dist = -1;
1011         for (o = &options[0]; o->name; o++) {
1012                 int match = 0;
1013
1014                 if (o->type == FIO_OPT_DEPRECATED)
1015                         continue;
1016                 if (!exec_profile && o->prof_name)
1017                         continue;
1018
1019                 if (name) {
1020                         if (!strcmp(name, o->name) ||
1021                             (o->alias && !strcmp(name, o->alias)))
1022                                 match = 1;
1023                         else {
1024                                 unsigned int dist;
1025
1026                                 dist = string_distance(name, o->name);
1027                                 if (dist < best_dist) {
1028                                         best_dist = dist;
1029                                         closest = o;
1030                                 }
1031                         }
1032                 }
1033
1034                 if (show_all || match) {
1035                         found = 1;
1036                         if (match)
1037                                 log_info("%20s: %s\n", o->name, o->help);
1038                         if (show_all) {
1039                                 if (!o->parent)
1040                                         print_option(o);
1041                                 continue;
1042                         }
1043                 }
1044
1045                 if (!match)
1046                         continue;
1047
1048                 show_option_help(o, 0);
1049         }
1050
1051         if (found)
1052                 return 0;
1053
1054         log_err("No such command: %s", name);
1055
1056         /*
1057          * Only print an appropriately close option, one where the edit
1058          * distance isn't too big. Otherwise we get crazy matches.
1059          */
1060         if (closest && best_dist < 3) {
1061                 log_info(" - showing closest match\n");
1062                 log_info("%20s: %s\n", closest->name, closest->help);
1063                 show_option_help(closest, 0);
1064         } else
1065                 log_info("\n");
1066
1067         return 1;
1068 }
1069
1070 /*
1071  * Handle parsing of default parameters.
1072  */
1073 void fill_default_options(void *data, struct fio_option *options)
1074 {
1075         struct fio_option *o;
1076
1077         dprint(FD_PARSE, "filling default options\n");
1078
1079         for (o = &options[0]; o->name; o++)
1080                 if (o->def)
1081                         handle_option(o, o->def, data);
1082 }
1083
1084 void option_init(struct fio_option *o)
1085 {
1086         if (o->type == FIO_OPT_DEPRECATED)
1087                 return;
1088         if (o->type == FIO_OPT_BOOL) {
1089                 o->minval = 0;
1090                 o->maxval = 1;
1091         }
1092         if (o->type == FIO_OPT_INT) {
1093                 if (!o->maxval)
1094                         o->maxval = UINT_MAX;
1095         }
1096         if (o->type == FIO_OPT_FLOAT_LIST) {
1097                 o->minfp = NAN;
1098                 o->maxfp = NAN;
1099         }
1100         if (o->type == FIO_OPT_STR_SET && o->def) {
1101                 log_err("Option %s: string set option with"
1102                                 " default will always be true\n", o->name);
1103         }
1104         if (!o->cb && (!o->off1 && !o->roff1))
1105                 log_err("Option %s: neither cb nor offset given\n", o->name);
1106         if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE ||
1107             o->type == FIO_OPT_STR_MULTI)
1108                 return;
1109         if (o->cb && ((o->off1 || o->off2 || o->off3 || o->off4) ||
1110                       (o->roff1 || o->roff2 || o->roff3 || o->roff4))) {
1111                 log_err("Option %s: both cb and offset given\n", o->name);
1112         }
1113         if (!o->category) {
1114                 log_info("Options %s: no category defined. Setting to misc\n", o->name);
1115                 o->category = FIO_OPT_C_GENERAL;
1116         }
1117 }
1118
1119 /*
1120  * Sanitize the options structure. For now it just sets min/max for bool
1121  * values and whether both callback and offsets are given.
1122  */
1123 void options_init(struct fio_option *options)
1124 {
1125         struct fio_option *o;
1126
1127         dprint(FD_PARSE, "init options\n");
1128
1129         for (o = &options[0]; o->name; o++) {
1130                 option_init(o);
1131                 if (o->inverse)
1132                         o->inv_opt = find_option(options, o->inverse);
1133         }
1134 }
1135
1136 void options_free(struct fio_option *options, void *data)
1137 {
1138         struct fio_option *o;
1139         char **ptr;
1140
1141         dprint(FD_PARSE, "free options\n");
1142
1143         for (o = &options[0]; o->name; o++) {
1144                 if (o->type != FIO_OPT_STR_STORE || !o->off1)
1145                         continue;
1146
1147                 ptr = td_var(data, o->off1);
1148                 if (*ptr) {
1149                         free(*ptr);
1150                         *ptr = NULL;
1151                 }
1152         }
1153 }