parse.c revision 0c9baf913d6d251973798048d29c60507f486ee6
1afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner/*
27c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell * This file contains the ini and command liner parser main.
37c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell */
47c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell#include <stdio.h>
57c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell#include <stdlib.h>
67c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell#include <unistd.h>
77c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell#include <ctype.h>
87c0e022c5c4be4b11e199a53f73bbdd84e34aa80John Criswell#include <string.h>
9afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include <errno.h>
10efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner#include <limits.h>
11efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner
12afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner#include "parse.h"
13afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner
14afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattnerstatic unsigned long get_mult_time(char c)
15afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner{
16e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman	switch (c) {
17afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner		case 'm':
18afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner		case 'M':
19d1a85a744cc1001c2b7fc37cf37aca266964f519Brian Gaeke			return 60;
20e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman		case 'h':
21e49603d79d220a795bd50684c8b1f503ee40f97fMisha Brukman		case 'H':
22afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner			return 60 * 60;
236520785dcd22012535934098942d57c07c7631c2Chris Lattner		case 'd':
24afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner		case 'D':
255e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			return 24 * 60 * 60;
265da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner		default:
27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer			return 1;
28551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer	}
29551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer}
30fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner
31c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattnerstatic unsigned long get_mult_bytes(char c)
32d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke{
33d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke	switch (c) {
34c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner		case 'k':
35d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke		case 'K':
36d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke			return 1024;
376db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner		case 'm':
386db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner		case 'M':
396db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner			return 1024 * 1024;
406db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner		case 'g':
4147ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner		case 'G':
4247ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner			return 1024 * 1024 * 1024;
436db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner		default:
446db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner			return 1;
45afade9294af43c6b947b9aeaa1555883d5f853e3Chris Lattner	}
466520785dcd22012535934098942d57c07c7631c2Chris Lattner}
476520785dcd22012535934098942d57c07c7631c2Chris Lattner
486520785dcd22012535934098942d57c07c7631c2Chris Lattner/*
496520785dcd22012535934098942d57c07c7631c2Chris Lattner * convert string into decimal value, noting any size suffix
506520785dcd22012535934098942d57c07c7631c2Chris Lattner */
510cc8807029f577996a442b96d24c3346ed6de091Chris Lattnerstatic int str_to_decimal(const char *str, long long *val, int kilo)
526520785dcd22012535934098942d57c07c7631c2Chris Lattner{
536520785dcd22012535934098942d57c07c7631c2Chris Lattner	int len;
546520785dcd22012535934098942d57c07c7631c2Chris Lattner
550cc8807029f577996a442b96d24c3346ed6de091Chris Lattner	len = strlen(str);
560cc8807029f577996a442b96d24c3346ed6de091Chris Lattner	if (!len)
576520785dcd22012535934098942d57c07c7631c2Chris Lattner		return 1;
586520785dcd22012535934098942d57c07c7631c2Chris Lattner
590cc8807029f577996a442b96d24c3346ed6de091Chris Lattner	*val = strtol(str, NULL, 10);
600cc8807029f577996a442b96d24c3346ed6de091Chris Lattner	if (*val == LONG_MAX && errno == ERANGE)
616520785dcd22012535934098942d57c07c7631c2Chris Lattner		return 1;
626520785dcd22012535934098942d57c07c7631c2Chris Lattner
630cc8807029f577996a442b96d24c3346ed6de091Chris Lattner	if (kilo)
646520785dcd22012535934098942d57c07c7631c2Chris Lattner		*val *= get_mult_bytes(str[len - 1]);
656520785dcd22012535934098942d57c07c7631c2Chris Lattner	else
660cc8807029f577996a442b96d24c3346ed6de091Chris Lattner		*val *= get_mult_time(str[len - 1]);
670cc8807029f577996a442b96d24c3346ed6de091Chris Lattner
686520785dcd22012535934098942d57c07c7631c2Chris Lattner	return 0;
696520785dcd22012535934098942d57c07c7631c2Chris Lattner}
700cc8807029f577996a442b96d24c3346ed6de091Chris Lattner
710cc8807029f577996a442b96d24c3346ed6de091Chris Lattnerstatic int check_str_bytes(const char *p, long long *val)
726520785dcd22012535934098942d57c07c7631c2Chris Lattner{
736520785dcd22012535934098942d57c07c7631c2Chris Lattner	return str_to_decimal(p, val, 1);
740cc8807029f577996a442b96d24c3346ed6de091Chris Lattner}
756520785dcd22012535934098942d57c07c7631c2Chris Lattner
7644be25716628941b4cccccf56a28ee0ba2606850Chris Lattnerstatic int check_str_time(const char *p, long long *val)
776520785dcd22012535934098942d57c07c7631c2Chris Lattner{
785da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner	return str_to_decimal(p, val, 0);
795da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner}
805da69c79f9c4490c6657c207430dfeb1060fc4ddChris Lattner
81efdc0b505712d1ca4460def27e51c430f033d58dChris Lattnervoid strip_blank_front(char **p)
82efdc0b505712d1ca4460def27e51c430f033d58dChris Lattner{
836db70ef879916e6115ac97eb76e4fea973652e2cChris Lattner	char *s = *p;
846520785dcd22012535934098942d57c07c7631c2Chris Lattner
8547ae4a1cee5eec5767a11403c0fac7c91ec45461Chris Lattner	while (isspace(*s))
866520785dcd22012535934098942d57c07c7631c2Chris Lattner		s++;
8710f22cb1a0f2755050218cd0e07221a0985c6b63Chris Lattner}
8810f22cb1a0f2755050218cd0e07221a0985c6b63Chris Lattner
896520785dcd22012535934098942d57c07c7631c2Chris Lattnervoid strip_blank_end(char *p)
906520785dcd22012535934098942d57c07c7631c2Chris Lattner{
916520785dcd22012535934098942d57c07c7631c2Chris Lattner	char *s = p + strlen(p) - 1;
92ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner
93fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner	while (isspace(*s) || iscntrl(*s))
94fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner		s--;
95fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner
96fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner	*(s + 1) = '\0';
97fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner}
98fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner
99ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattnerstatic int check_range_bytes(const char *str, long *val)
100ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner{
101ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner	char suffix;
102ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner
103fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner	if (!strlen(str))
10428b8ed90c75ce6c271500fa778fef252f267a5ffChris Lattner		return 1;
10528b8ed90c75ce6c271500fa778fef252f267a5ffChris Lattner
10628b8ed90c75ce6c271500fa778fef252f267a5ffChris Lattner	if (sscanf(str, "%lu%c", val, &suffix) == 2) {
107dbe48dcaec69ff78e39e2d5faf4323ade6fffb04Chris Lattner		*val *= get_mult_bytes(suffix);
108fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner		return 0;
109fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner	}
110fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner
111fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner	if (sscanf(str, "%lu", val) == 1)
112fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner		return 0;
113c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner
114c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner	return 1;
115c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner}
116c6b519d64ef55d39e66a49510d4703a49bf228ccChris Lattner
117fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattnerstatic int check_int(const char *p, int *val)
118a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner{
119a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner	if (!strlen(p))
1207546c3884a400b72d10fc19f120c6798b294a39dChris Lattner		return 1;
121fcb6ec0c7e37c2d15ddb04878f05cbd69d1da036Chris Lattner	if (sscanf(p, "%u", val) == 1)
122a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner		return 0;
123a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner
124ba386d943f4a83095d9c625cb0d46c1afe45ed1fChris Lattner	return 1;
125be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner}
126be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner
1277546c3884a400b72d10fc19f120c6798b294a39dChris Lattnerstatic struct fio_option *find_option(struct fio_option *options,
1287546c3884a400b72d10fc19f120c6798b294a39dChris Lattner				      const char *opt)
1297546c3884a400b72d10fc19f120c6798b294a39dChris Lattner{
1307546c3884a400b72d10fc19f120c6798b294a39dChris Lattner	struct fio_option *o;
1317546c3884a400b72d10fc19f120c6798b294a39dChris Lattner
1327546c3884a400b72d10fc19f120c6798b294a39dChris Lattner	for (o = &options[0]; o->name; o++) {
1337546c3884a400b72d10fc19f120c6798b294a39dChris Lattner		if (!strcmp(o->name, opt))
134a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner			return o;
135a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner		else if (o->alias && !strcmp(o->alias, opt))
136a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner			return o;
137a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner	}
138a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner
139a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner	return NULL;
140a1cf1c8c87f10f12343ff6ae75f332390e7205abChris Lattner}
1417546c3884a400b72d10fc19f120c6798b294a39dChris Lattner
1427546c3884a400b72d10fc19f120c6798b294a39dChris Lattner#define val_store(ptr, val, off, data)			\
143a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner	do {						\
144a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner		ptr = td_var((data), (off));		\
145a269ec7b0a83d3b20730fd2d9f7c3ed5a552da90Chris Lattner		*ptr = (val);				\
146a269ec7b0a83d3b20730fd2d9f7c3ed5a552da90Chris Lattner	} while (0)
147a269ec7b0a83d3b20730fd2d9f7c3ed5a552da90Chris Lattner
14890c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattnerstatic int __handle_option(struct fio_option *o, const char *ptr, void *data,
149a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner			   int first, int more)
150a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner{
15190c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner	int il, *ilp;
15290c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner	long long ull, *ullp;
15390c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner	long ul1, ul2;
15490c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner	char **cp;
15590c18c5c69d9c451e5fdca1e4b4b95e8ed13291aChris Lattner	int ret = 0, is_time = 0;
156a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner
157a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner	if (!ptr && o->type != FIO_OPT_STR_SET) {
158a75766a6c14b364b74b30546802e26d4b4b36a9bChris Lattner		fprintf(stderr, "Option %s requires an argument\n", o->name);
1597546c3884a400b72d10fc19f120c6798b294a39dChris Lattner		return 1;
1607546c3884a400b72d10fc19f120c6798b294a39dChris Lattner	}
1617546c3884a400b72d10fc19f120c6798b294a39dChris Lattner
162be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	switch (o->type) {
163be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	case FIO_OPT_STR: {
164be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		fio_opt_str_fn *fn = o->cb;
165be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner
166be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		ret = fn(data, ptr);
167be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		break;
168be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	}
169be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	case FIO_OPT_STR_VAL_TIME:
170be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		is_time = 1;
171be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	case FIO_OPT_STR_VAL:
172be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	case FIO_OPT_STR_VAL_INT: {
173be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		fio_opt_str_val_fn *fn = o->cb;
1745eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner
1755eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner		if (is_time)
1765eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner			ret = check_str_time(ptr, &ull);
1775eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner		else
1785eda1f2f65941a24ef9a5a85addf4d90eb13fa9dChris Lattner			ret = check_str_bytes(ptr, &ull);
179be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner
180be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		if (ret)
181be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			break;
182be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner
183be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		if (o->maxval && ull > o->maxval) {
184be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			fprintf(stderr, "max value out of range: %lld (%d max)\n", ull, o->maxval);
185be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			return 1;
186be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		}
187be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		if (o->minval && ull < o->minval) {
188be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			fprintf(stderr, "min value out of range: %lld (%d min)\n", ull, o->minval);
189be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			return 1;
190be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		}
191be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner
192be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		if (fn)
193be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			ret = fn(data, &ull);
194be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		else {
195fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner			if (o->type == FIO_OPT_STR_VAL_INT) {
196be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner				if (first)
197fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner					val_store(ilp, ull, o->off1, data);
198be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner				if (!more && o->off2)
199be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner					val_store(ilp, ull, o->off2, data);
200be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner			} else {
201be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner				if (first)
202be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner					val_store(ullp, ull, o->off1, data);
203be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner				if (!more && o->off2)
204be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner					val_store(ullp, ull, o->off2, data);
205fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner			}
206fb4b96e77e2930bf3d0c148f1c3685b6a4434666Chris Lattner		}
207be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner		break;
208be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	}
209be21ca54e08339ede5dd4bbb882182d22e274988Chris Lattner	case FIO_OPT_STR_STORE:
2105e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		cp = td_var(data, o->off1);
2115e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		*cp = strdup(ptr);
2125e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		break;
2135e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner	case FIO_OPT_RANGE: {
2145e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		char tmp[128];
2155e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		char *p1, *p2;
2165e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2175e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		strncpy(tmp, ptr, sizeof(tmp) - 1);
2185e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2195e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		p1 = strchr(tmp, '-');
2205e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		if (!p1) {
221b12914bfc0f76a7a48357162d5f4c39a1343e69bChris Lattner			p1 = strchr(tmp, ':');
222b12914bfc0f76a7a48357162d5f4c39a1343e69bChris Lattner			if (!p1) {
2235e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				ret = 1;
2245e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				break;
2255e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			}
2265e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		}
2275e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
228b12914bfc0f76a7a48357162d5f4c39a1343e69bChris Lattner		p2 = p1 + 1;
2295e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		*p1 = '\0';
2305e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		p1 = tmp;
2315e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2325e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		ret = 1;
2335e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		if (!check_range_bytes(p1, &ul1) && !check_range_bytes(p2, &ul2)) {
2345e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			ret = 0;
2355e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			if (ul1 > ul2) {
2365e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				unsigned long foo = ul1;
2375e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2385e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				ul1 = ul2;
2395e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				ul2 = foo;
2405e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			}
2415e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2425e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			if (first) {
2435e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				val_store(ilp, ul1, o->off1, data);
2445e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				val_store(ilp, ul2, o->off2, data);
2455e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			}
2465e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			if (!more && o->off3 && o->off4) {
2475e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				val_store(ilp, ul1, o->off3, data);
2485e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				val_store(ilp, ul2, o->off4, data);
2495e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			}
2505e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		}
2515e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2525e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		break;
2535e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner	}
2545e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner	case FIO_OPT_INT:
2555e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner	case FIO_OPT_BOOL: {
2565e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		fio_opt_int_fn *fn = o->cb;
2575e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2585e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		ret = check_int(ptr, &il);
2595e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		if (ret)
2605e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			break;
2615e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2625e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		if (o->maxval && il > (int) o->maxval) {
2635e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			fprintf(stderr, "max value out of range: %d (%d max)\n", il, o->maxval);
2645e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			return 1;
2655e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		}
2665e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		if (o->minval && il < o->minval) {
2675e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			fprintf(stderr, "min value out of range: %d (%d min)\n", il, o->minval);
2685e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			return 1;
2695e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		}
2705e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
2715e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner		if (o->neg)
272891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner			il = !il;
2735e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner
274891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner		if (fn)
275891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner			ret = fn(data, &il);
276891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner		else {
277891150f0b2a124a75c9f31516182ce864ae69ef8Chris Lattner			if (first)
2785e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner				val_store(ilp, il, o->off1, data);
2795e783ab0b5fc3407ec59f1a598fdb9ef3b96b287Chris Lattner			if (!more && o->off2)
280				val_store(ilp, il, o->off2, data);
281		}
282		break;
283	}
284	case FIO_OPT_STR_SET: {
285		fio_opt_str_set_fn *fn = o->cb;
286
287		if (fn)
288			ret = fn(data);
289		else {
290			if (first)
291				val_store(ilp, 1, o->off1, data);
292			if (!more && o->off2)
293				val_store(ilp, 1, o->off2, data);
294		}
295		break;
296	}
297	default:
298		fprintf(stderr, "Bad option type %u\n", o->type);
299		ret = 1;
300	}
301
302	return ret;
303}
304
305static int handle_option(struct fio_option *o, const char *ptr, void *data)
306{
307	const char *ptr2 = NULL;
308	int r1, r2;
309
310	/*
311	 * See if we have a second set of parameters, hidden after a comma.
312	 * Do this before parsing the first round, to check if we should
313	 * copy set 1 options to set 2.
314	 */
315	if (ptr) {
316		ptr2 = strchr(ptr, ',');
317		if (!ptr2)
318			ptr2 = strchr(ptr, ':');
319	}
320
321	/*
322	 * Don't return early if parsing the first option fails - if
323	 * we are doing multiple arguments, we can allow the first one
324	 * being empty.
325	 */
326	r1 = __handle_option(o, ptr, data, 1, !!ptr2);
327
328	if (!ptr2)
329		return r1;
330
331	ptr2++;
332	r2 = __handle_option(o, ptr2, data, 0, 0);
333
334	return r1 && r2;
335}
336
337int parse_cmd_option(const char *opt, const char *val,
338		     struct fio_option *options, void *data)
339{
340	struct fio_option *o;
341
342	o = find_option(options, opt);
343	if (!o) {
344		fprintf(stderr, "Bad option %s\n", opt);
345		return 1;
346	}
347
348	if (!handle_option(o, val, data))
349		return 0;
350
351	fprintf(stderr, "fio: failed parsing %s=%s\n", opt, val);
352	return 1;
353}
354
355int parse_option(const char *opt, struct fio_option *options, void *data)
356{
357	struct fio_option *o;
358	char *pre, *post;
359	char tmp[64];
360
361	strncpy(tmp, opt, sizeof(tmp) - 1);
362
363	pre = strchr(tmp, '=');
364	if (pre) {
365		post = pre;
366		*pre = '\0';
367		pre = tmp;
368		post++;
369		o = find_option(options, pre);
370	} else {
371		o = find_option(options, tmp);
372		post = NULL;
373	}
374
375	if (!o) {
376		fprintf(stderr, "Bad option %s\n", tmp);
377		return 1;
378	}
379
380	if (!handle_option(o, post, data))
381		return 0;
382
383	fprintf(stderr, "fio: failed parsing %s\n", opt);
384	return 1;
385}
386
387static void show_option_range(struct fio_option *o)
388{
389	if (!o->minval && !o->maxval)
390		return;
391
392	printf("%16s: min=%d, max=%d\n", "range", o->minval, o->maxval);
393}
394
395static void show_option_values(struct fio_option *o)
396{
397	const char *msg;
398	int i = 0;
399
400	if (!o->posval)
401		return;
402
403	do {
404		msg = o->posval[i];
405		if (!msg)
406			break;
407
408		if (!i)
409			printf("%16s: ", "valid values");
410
411		printf("%s,", msg);
412		i++;
413	} while (1);
414
415	if (i)
416		printf("\n");
417}
418
419int show_cmd_help(struct fio_option *options, const char *name)
420{
421	int show_all = !strcmp(name, "all");
422	const char *typehelp[] = {
423		"string (opt=bla)",
424		"string with possible k/m/g postfix (opt=4k)",
425		"string with range and postfix (opt=1k-4k)",
426		"string with time postfix (opt=10s)",
427		"string (opt=bla)",
428		"string with dual range (opt=1k-4k,4k-8k)",
429		"integer value (opt=100)",
430		"boolean value (opt=1)",
431		"no argument (opt)",
432	};
433	struct fio_option *o;
434	int found = 0;
435
436	for (o = &options[0]; o->name; o++) {
437		int match = !strcmp(name, o->name);
438
439		if (show_all || match) {
440			found = 1;
441			printf("%16s: %s\n", o->name, o->help);
442			if (show_all)
443				continue;
444		}
445
446		if (!match)
447			continue;
448
449		printf("%16s: %s\n", "type", typehelp[o->type]);
450		printf("%16s: %s\n", "default", o->def ? o->def : "no default");
451		show_option_range(o);
452		show_option_values(o);
453	}
454
455	if (found)
456		return 0;
457
458	printf("No such command: %s\n", name);
459	return 1;
460}
461
462/*
463 * Handle parsing of default parameters.
464 */
465void fill_default_options(void *data, struct fio_option *options)
466{
467	struct fio_option *o;
468
469	for (o = &options[0]; o->name; o++)
470		if (o->def)
471			handle_option(o, o->def, data);
472}
473
474/*
475 * Sanitize the options structure. For now it just sets min/max for bool
476 * values and whether both callback and offsets are given.
477 */
478void options_init(struct fio_option *options)
479{
480	struct fio_option *o;
481
482	for (o = &options[0]; o->name; o++) {
483		if (o->type == FIO_OPT_BOOL) {
484			o->minval = 0;
485			o->maxval = 1;
486		}
487		if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4))
488			fprintf(stderr, "Option %s: both cb and offset given\n", o->name);
489	}
490}
491