compiler.h needs to define __must_check if not set
[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
12 #include "parse.h"
13
14 static int vp_cmp(const void *p1, const void *p2)
15 {
16         const struct value_pair *vp1 = p1;
17         const struct value_pair *vp2 = p2;
18
19         return strlen(vp2->ival) - strlen(vp1->ival);
20 }
21
22 static void posval_sort(struct fio_option *o, struct value_pair *vpmap)
23 {
24         const struct value_pair *vp;
25         int entries;
26
27         memset(vpmap, 0, PARSE_MAX_VP * sizeof(struct value_pair));
28
29         for (entries = 0; entries < PARSE_MAX_VP; entries++) {
30                 vp = &o->posval[entries];
31                 if (!vp->ival || vp->ival[0] == '\0')
32                         break;
33
34                 memcpy(&vpmap[entries], vp, sizeof(*vp));
35         }
36
37         qsort(vpmap, entries, sizeof(struct value_pair), vp_cmp);
38 }
39
40 static void show_option_range(struct fio_option *o)
41 {
42         if (!o->minval && !o->maxval)
43                 return;
44
45         printf("%20s: min=%d, max=%d\n", "range", o->minval, o->maxval);
46 }
47
48 static void show_option_values(struct fio_option *o)
49 {
50         int i = 0;
51
52         do {
53                 const struct value_pair *vp = &o->posval[i];
54
55                 if (!vp->ival)
56                         break;
57
58                 printf("%20s: %-10s", i == 0 ? "valid values" : "", vp->ival);
59                 if (vp->help)
60                         printf(" %s", vp->help);
61                 printf("\n");
62                 i++;
63         } while (i < PARSE_MAX_VP);
64
65         if (i)
66                 printf("\n");
67 }
68
69 static unsigned long get_mult_time(char c)
70 {
71         switch (c) {
72                 case 'm':
73                 case 'M':
74                         return 60;
75                 case 'h':
76                 case 'H':
77                         return 60 * 60;
78                 case 'd':
79                 case 'D':
80                         return 24 * 60 * 60;
81                 default:
82                         return 1;
83         }
84 }
85
86 static unsigned long get_mult_bytes(char c)
87 {
88         switch (c) {
89                 case 'k':
90                 case 'K':
91                         return 1024;
92                 case 'm':
93                 case 'M':
94                         return 1024 * 1024;
95                 case 'g':
96                 case 'G':
97                         return 1024 * 1024 * 1024;
98                 case 'e':
99                 case 'E':
100                         return 1024 * 1024 * 1024 * 1024UL;
101                 default:
102                         return 1;
103         }
104 }
105
106 /*
107  * convert string into decimal value, noting any size suffix
108  */
109 static int str_to_decimal(const char *str, long long *val, int kilo)
110 {
111         int len;
112
113         len = strlen(str);
114         if (!len)
115                 return 1;
116
117         *val = strtoll(str, NULL, 10);
118         if (*val == LONG_MAX && errno == ERANGE)
119                 return 1;
120
121         if (kilo)
122                 *val *= get_mult_bytes(str[len - 1]);
123         else
124                 *val *= get_mult_time(str[len - 1]);
125
126         return 0;
127 }
128
129 static int check_str_bytes(const char *p, long long *val)
130 {
131         return str_to_decimal(p, val, 1);
132 }
133
134 static int check_str_time(const char *p, long long *val)
135 {
136         return str_to_decimal(p, val, 0);
137 }
138
139 void strip_blank_front(char **p)
140 {
141         char *s = *p;
142
143         while (isspace(*s))
144                 s++;
145
146         *p = s;
147 }
148
149 void strip_blank_end(char *p)
150 {
151         char *s = p + strlen(p) - 1;
152
153         while (isspace(*s) || iscntrl(*s))
154                 s--;
155
156         *(s + 1) = '\0';
157 }
158
159 static int check_range_bytes(const char *str, long *val)
160 {
161         char suffix;
162
163         if (!strlen(str))
164                 return 1;
165
166         if (sscanf(str, "%lu%c", val, &suffix) == 2) {
167                 *val *= get_mult_bytes(suffix);
168                 return 0;
169         }
170
171         if (sscanf(str, "%lu", val) == 1)
172                 return 0;
173
174         return 1;
175 }
176
177 static int check_int(const char *p, int *val)
178 {
179         if (!strlen(p))
180                 return 1;
181         if (sscanf(p, "%u", val) == 1)
182                 return 0;
183
184         return 1;
185 }
186
187 static struct fio_option *find_option(struct fio_option *options,
188                                       const char *opt)
189 {
190         struct fio_option *o;
191
192         for (o = &options[0]; o->name; o++) {
193                 if (!strcmp(o->name, opt))
194                         return o;
195                 else if (o->alias && !strcmp(o->alias, opt))
196                         return o;
197         }
198
199         return NULL;
200 }
201
202 #define val_store(ptr, val, off, data)                  \
203         do {                                            \
204                 ptr = td_var((data), (off));            \
205                 *ptr = (val);                           \
206         } while (0)
207
208 static int __handle_option(struct fio_option *o, const char *ptr, void *data,
209                            int first, int more)
210 {
211         int il, *ilp;
212         long long ull, *ullp;
213         long ul1, ul2;
214         char **cp;
215         int ret = 0, is_time = 0;
216
217         if (!ptr && o->type != FIO_OPT_STR_SET) {
218                 fprintf(stderr, "Option %s requires an argument\n", o->name);
219                 return 1;
220         }
221
222         switch (o->type) {
223         case FIO_OPT_STR: {
224                 fio_opt_str_fn *fn = o->cb;
225                 const struct value_pair *vp;
226                 struct value_pair posval[PARSE_MAX_VP];
227                 int i;
228
229                 posval_sort(o, posval);
230
231                 for (i = 0; i < PARSE_MAX_VP; i++) {
232                         vp = &posval[i];
233                         if (!vp->ival || vp->ival[0] == '\0')
234                                 break;
235                         ret = 1;
236                         if (!strncmp(vp->ival, ptr, strlen(vp->ival))) {
237                                 ret = 0;
238                                 if (!o->off1)
239                                         break;
240                                 val_store(ilp, vp->oval, o->off1, data);
241                                 break;
242                         }
243                 }
244
245                 if (ret)
246                         show_option_values(o);
247                 else if (fn)
248                         ret = fn(data, ptr);
249                 break;
250         }
251         case FIO_OPT_STR_VAL_TIME:
252                 is_time = 1;
253         case FIO_OPT_STR_VAL:
254         case FIO_OPT_STR_VAL_INT: {
255                 fio_opt_str_val_fn *fn = o->cb;
256
257                 if (is_time)
258                         ret = check_str_time(ptr, &ull);
259                 else
260                         ret = check_str_bytes(ptr, &ull);
261
262                 if (ret)
263                         break;
264
265                 if (o->maxval && ull > o->maxval) {
266                         fprintf(stderr, "max value out of range: %lld (%d max)\n", ull, o->maxval);
267                         return 1;
268                 }
269                 if (o->minval && ull < o->minval) {
270                         fprintf(stderr, "min value out of range: %lld (%d min)\n", ull, o->minval);
271                         return 1;
272                 }
273
274                 if (fn)
275                         ret = fn(data, &ull);
276                 else {
277                         if (o->type == FIO_OPT_STR_VAL_INT) {
278                                 if (first)
279                                         val_store(ilp, ull, o->off1, data);
280                                 if (!more && o->off2)
281                                         val_store(ilp, ull, o->off2, data);
282                         } else {
283                                 if (first)
284                                         val_store(ullp, ull, o->off1, data);
285                                 if (!more && o->off2)
286                                         val_store(ullp, ull, o->off2, data);
287                         }
288                 }
289                 break;
290         }
291         case FIO_OPT_STR_STORE: {
292                 fio_opt_str_fn *fn = o->cb;
293
294                 cp = td_var(data, o->off1);
295                 *cp = strdup(ptr);
296                 if (fn) {
297                         ret = fn(data, ptr);
298                         if (ret) {
299                                 free(*cp);
300                                 *cp = NULL;
301                         }
302                 }
303                 break;
304         }
305         case FIO_OPT_RANGE: {
306                 char tmp[128];
307                 char *p1, *p2;
308
309                 strncpy(tmp, ptr, sizeof(tmp) - 1);
310
311                 p1 = strchr(tmp, '-');
312                 if (!p1) {
313                         p1 = strchr(tmp, ':');
314                         if (!p1) {
315                                 ret = 1;
316                                 break;
317                         }
318                 }
319
320                 p2 = p1 + 1;
321                 *p1 = '\0';
322                 p1 = tmp;
323
324                 ret = 1;
325                 if (!check_range_bytes(p1, &ul1) && !check_range_bytes(p2, &ul2)) {
326                         ret = 0;
327                         if (ul1 > ul2) {
328                                 unsigned long foo = ul1;
329
330                                 ul1 = ul2;
331                                 ul2 = foo;
332                         }
333
334                         if (first) {
335                                 val_store(ilp, ul1, o->off1, data);
336                                 val_store(ilp, ul2, o->off2, data);
337                         }
338                         if (!more && o->off3 && o->off4) {
339                                 val_store(ilp, ul1, o->off3, data);
340                                 val_store(ilp, ul2, o->off4, data);
341                         }
342                 }
343
344                 break;
345         }
346         case FIO_OPT_INT:
347         case FIO_OPT_BOOL: {
348                 fio_opt_int_fn *fn = o->cb;
349
350                 ret = check_int(ptr, &il);
351                 if (ret)
352                         break;
353
354                 if (o->maxval && il > (int) o->maxval) {
355                         fprintf(stderr, "max value out of range: %d (%d max)\n", il, o->maxval);
356                         return 1;
357                 }
358                 if (o->minval && il < o->minval) {
359                         fprintf(stderr, "min value out of range: %d (%d min)\n", il, o->minval);
360                         return 1;
361                 }
362
363                 if (o->neg)
364                         il = !il;
365
366                 if (fn)
367                         ret = fn(data, &il);
368                 else {
369                         if (first)
370                                 val_store(ilp, il, o->off1, data);
371                         if (!more && o->off2)
372                                 val_store(ilp, il, o->off2, data);
373                 }
374                 break;
375         }
376         case FIO_OPT_STR_SET: {
377                 fio_opt_str_set_fn *fn = o->cb;
378
379                 if (fn)
380                         ret = fn(data);
381                 else {
382                         if (first)
383                                 val_store(ilp, 1, o->off1, data);
384                         if (!more && o->off2)
385                                 val_store(ilp, 1, o->off2, data);
386                 }
387                 break;
388         }
389         default:
390                 fprintf(stderr, "Bad option type %u\n", o->type);
391                 ret = 1;
392         }
393
394         return ret;
395 }
396
397 static int handle_option(struct fio_option *o, const char *ptr, void *data)
398 {
399         const char *ptr2 = NULL;
400         int r1, r2;
401
402         /*
403          * See if we have a second set of parameters, hidden after a comma.
404          * Do this before parsing the first round, to check if we should
405          * copy set 1 options to set 2.
406          */
407         if (ptr &&
408             (o->type != FIO_OPT_STR_STORE) &&
409             (o->type != FIO_OPT_STR)) {
410                 ptr2 = strchr(ptr, ',');
411                 if (!ptr2)
412                         ptr2 = strchr(ptr, ':');
413                 if (!ptr2)
414                         ptr2 = strchr(ptr, '-');
415         }
416
417         /*
418          * Don't return early if parsing the first option fails - if
419          * we are doing multiple arguments, we can allow the first one
420          * being empty.
421          */
422         r1 = __handle_option(o, ptr, data, 1, !!ptr2);
423
424         if (!ptr2)
425                 return r1;
426
427         ptr2++;
428         r2 = __handle_option(o, ptr2, data, 0, 0);
429
430         return r1 && r2;
431 }
432
433 int parse_cmd_option(const char *opt, const char *val,
434                      struct fio_option *options, void *data)
435 {
436         struct fio_option *o;
437
438         o = find_option(options, opt);
439         if (!o) {
440                 fprintf(stderr, "Bad option %s\n", opt);
441                 return 1;
442         }
443
444         if (!handle_option(o, val, data))
445                 return 0;
446
447         fprintf(stderr, "fio: failed parsing %s=%s\n", opt, val);
448         return 1;
449 }
450
451 int parse_option(const char *opt, struct fio_option *options, void *data)
452 {
453         struct fio_option *o;
454         char *pre, *post;
455         char tmp[64];
456
457         strncpy(tmp, opt, sizeof(tmp) - 1);
458
459         pre = strchr(tmp, '=');
460         if (pre) {
461                 post = pre;
462                 *pre = '\0';
463                 pre = tmp;
464                 post++;
465                 o = find_option(options, pre);
466         } else {
467                 o = find_option(options, tmp);
468                 post = NULL;
469         }
470
471         if (!o) {
472                 fprintf(stderr, "Bad option %s\n", tmp);
473                 return 1;
474         }
475
476         if (!handle_option(o, post, data))
477                 return 0;
478
479         fprintf(stderr, "fio: failed parsing %s\n", opt);
480         return 1;
481 }
482
483 /*
484  * Option match, levenshtein distance. Handy for not quite remembering what
485  * the option name is.
486  */
487 static int string_distance(const char *s1, const char *s2)
488 {
489         unsigned int s1_len = strlen(s1);
490         unsigned int s2_len = strlen(s2);
491         unsigned int *p, *q, *r;
492         unsigned int i, j;
493
494         p = malloc(sizeof(unsigned int) * (s2_len + 1));
495         q = malloc(sizeof(unsigned int) * (s2_len + 1));
496
497         p[0] = 0;
498         for (i = 1; i <= s2_len; i++)
499                 p[i] = p[i - 1] + 1;
500
501         for (i = 1; i <= s1_len; i++) {
502                 q[0] = p[0] + 1;
503                 for (j = 1; j <= s2_len; j++) {
504                         unsigned int sub = p[j - 1];
505
506                         if (s1[i - 1] != s2[j - 1])
507                                 sub++;
508
509                         q[j] = min(p[j] + 1, min(q[j - 1] + 1, sub));
510                 }
511                 r = p;
512                 p = q;
513                 q = r;
514         }
515
516         i = p[s2_len];
517         free(p);
518         free(q);
519         return i;
520 }
521
522 static void show_option_help(struct fio_option *o)
523 {
524         const char *typehelp[] = {
525                 "string (opt=bla)",
526                 "string with possible k/m/g postfix (opt=4k)",
527                 "string with range and postfix (opt=1k-4k)",
528                 "string with time postfix (opt=10s)",
529                 "string (opt=bla)",
530                 "string with dual range (opt=1k-4k,4k-8k)",
531                 "integer value (opt=100)",
532                 "boolean value (opt=1)",
533                 "no argument (opt)",
534         };
535
536         if (o->alias)
537                 printf("%20s: %s\n", "alias", o->alias);
538
539         printf("%20s: %s\n", "type", typehelp[o->type]);
540         printf("%20s: %s\n", "default", o->def ? o->def : "no default");
541         show_option_range(o);
542         show_option_values(o);
543 }
544
545 int show_cmd_help(struct fio_option *options, const char *name)
546 {
547         struct fio_option *o, *closest;
548         unsigned int best_dist;
549         int found = 0;
550         int show_all = 0;
551
552         if (!name || !strcmp(name, "all"))
553                 show_all = 1;
554
555         closest = NULL;
556         best_dist = -1;
557         for (o = &options[0]; o->name; o++) {
558                 int match = 0;
559
560                 if (name) {
561                         if (!strcmp(name, o->name) ||
562                             (o->alias && !strcmp(name, o->alias)))
563                                 match = 1;
564                         else {
565                                 unsigned int dist;
566
567                                 dist = string_distance(name, o->name);
568                                 if (dist < best_dist) {
569                                         best_dist = dist;
570                                         closest = o;
571                                 }
572                         }
573                 }
574
575                 if (show_all || match) {
576                         found = 1;
577                         if (match)
578                                 printf("%20s: %s\n", o->name, o->help);
579                         if (show_all) {
580                                 printf("%-20s: %s\n", o->name, o->help);
581                                 continue;
582                         }
583                 }
584
585                 if (!match)
586                         continue;
587
588                 show_option_help(o);
589         }
590
591         if (found)
592                 return 0;
593
594         printf("No such command: %s", name);
595         if (closest) {
596                 printf(" - showing closest match\n");
597                 printf("%20s: %s\n", closest->name, closest->help);
598                 show_option_help(closest);
599         } else
600                 printf("\n");
601
602         return 1;
603 }
604
605 /*
606  * Handle parsing of default parameters.
607  */
608 void fill_default_options(void *data, struct fio_option *options)
609 {
610         struct fio_option *o;
611
612         for (o = &options[0]; o->name; o++)
613                 if (o->def)
614                         handle_option(o, o->def, data);
615 }
616
617 /*
618  * Sanitize the options structure. For now it just sets min/max for bool
619  * values and whether both callback and offsets are given.
620  */
621 void options_init(struct fio_option *options)
622 {
623         struct fio_option *o;
624
625         for (o = &options[0]; o->name; o++) {
626                 if (o->type == FIO_OPT_BOOL) {
627                         o->minval = 0;
628                         o->maxval = 1;
629                 }
630                 if (o->type == FIO_OPT_STR_SET && o->def)
631                         fprintf(stderr, "Option %s: string set option with default will always be true\n", o->name);
632                 if (!o->cb && !o->off1)
633                         fprintf(stderr, "Option %s: neither cb nor offset given\n", o->name);
634                 if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE)
635                         continue;
636                 if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4))
637                         fprintf(stderr, "Option %s: both cb and offset given\n", o->name);
638         }
639 }