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