Example #1
0
File: parse.c Project: CodeMonk/fio
static int __handle_option(struct fio_option *o, const char *ptr, void *data,
			   int first, int more, int curr)
{
	int il=0, *ilp;
	fio_fp64_t *flp;
	long long ull, *ullp;
	long ul1, ul2;
	double uf;
	char **cp = NULL;
	int ret = 0, is_time = 0;
	const struct value_pair *vp;
	struct value_pair posval[PARSE_MAX_VP];
	int i, all_skipped = 1;

	dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name,
							o->type, ptr);

	if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) {
		log_err("Option %s requires an argument\n", o->name);
		return 1;
	}

	switch (o->type) {
	case FIO_OPT_STR:
	case FIO_OPT_STR_MULTI: {
		fio_opt_str_fn *fn = o->cb;

		posval_sort(o, posval);

		ret = 1;
		for (i = 0; i < PARSE_MAX_VP; i++) {
			vp = &posval[i];
			if (!vp->ival || vp->ival[0] == '\0')
				continue;
			all_skipped = 0;
			if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) {
				ret = 0;
				if (o->off1)
					val_store(ilp, vp->oval, o->off1, vp->orval, data, o);
				continue;
			}
		}

		if (ret && !all_skipped)
			show_option_values(o);
		else if (fn)
			ret = fn(data, ptr);
		break;
	}
	case FIO_OPT_STR_VAL_TIME:
		is_time = 1;
	case FIO_OPT_INT:
	case FIO_OPT_STR_VAL: {
		fio_opt_str_val_fn *fn = o->cb;
		char tmp[128], *p;

		if (!is_time && o->is_time)
			is_time = o->is_time;

		tmp[sizeof(tmp) - 1] = '\0';
		strncpy(tmp, ptr, sizeof(tmp) - 1);
		p = strchr(tmp, ',');
		if (p)
			*p = '\0';

		if (is_time)
			ret = check_str_time(tmp, &ull, o->is_seconds);
		else
			ret = check_str_bytes(tmp, &ull, data);

		dprint(FD_PARSE, "  ret=%d, out=%llu\n", ret, ull);

		if (ret)
			break;

		if (o->maxval && ull > o->maxval) {
			log_err("max value out of range: %llu"
					" (%u max)\n", ull, o->maxval);
			return 1;
		}
		if (o->minval && ull < o->minval) {
			log_err("min value out of range: %llu"
					" (%u min)\n", ull, o->minval);
			return 1;
		}
		if (o->posval[0].ival) {
			posval_sort(o, posval);

			ret = 1;
			for (i = 0; i < PARSE_MAX_VP; i++) {
				vp = &posval[i];
				if (!vp->ival || vp->ival[0] == '\0')
					continue;
				if (vp->oval == ull) {
					ret = 0;
					break;
				}
			}
			if (ret) {
				log_err("fio: value %llu not allowed:\n", ull);
				show_option_values(o);
				return 1;
			}
		}

		if (fn)
			ret = fn(data, &ull);
		else {
			if (o->type == FIO_OPT_INT) {
				if (first)
					val_store(ilp, ull, o->off1, 0, data, o);
				if (curr == 1) {
					if (o->off2)
						val_store(ilp, ull, o->off2, 0, data, o);
				}
				if (curr == 2) {
					if (o->off3)
						val_store(ilp, ull, o->off3, 0, data, o);
				}
				if (!more) {
					if (curr < 1) {
						if (o->off2)
							val_store(ilp, ull, o->off2, 0, data, o);
					}
					if (curr < 2) {
						if (o->off3)
							val_store(ilp, ull, o->off3, 0, data, o);
					}
				}
			} else {
				if (first)
					val_store(ullp, ull, o->off1, 0, data, o);
				if (!more) {
					if (o->off2)
						val_store(ullp, ull, o->off2, 0, data, o);
				}
			}
		}
		break;
	}
	case FIO_OPT_FLOAT_LIST: {
		char *cp2;

		if (first) {
			/*
			** Initialize precision to 0 and zero out list
			** in case specified list is shorter than default
			*/
			if (o->off2) {
				ul2 = 0;
				ilp = td_var(data, o, o->off2);
				*ilp = ul2;
			}

			flp = td_var(data, o, o->off1);
			for(i = 0; i < o->maxlen; i++)
				flp[i].u.f = 0.0;
		}
		if (curr >= o->maxlen) {
			log_err("the list exceeding max length %d\n",
					o->maxlen);
			return 1;
		}
		if (!str_to_float(ptr, &uf, 0)) { /* this breaks if we ever have lists of times */
			log_err("not a floating point value: %s\n", ptr);
			return 1;
		}
		if (uf > o->maxfp) {
			log_err("value out of range: %f"
				" (range max: %f)\n", uf, o->maxfp);
			return 1;
		}
		if (uf < o->minfp) {
			log_err("value out of range: %f"
				" (range min: %f)\n", uf, o->minfp);
			return 1;
		}

		flp = td_var(data, o, o->off1);
		flp[curr].u.f = uf;

		dprint(FD_PARSE, "  out=%f\n", uf);

		/*
		** Calculate precision for output by counting
		** number of digits after period. Find first
		** period in entire remaining list each time
		*/
		cp2 = strchr(ptr, '.');
		if (cp2 != NULL) {
			int len = 0;

			while (*++cp2 != '\0' && *cp2 >= '0' && *cp2 <= '9')
				len++;

			if (o->off2) {
				ilp = td_var(data, o, o->off2);
				if (len > *ilp)
					*ilp = len;
			}
		}

		break;
	}
	case FIO_OPT_STR_STORE: {
		fio_opt_str_fn *fn = o->cb;

		if (!strlen(ptr))
			return 1;

		if (o->off1) {
			cp = td_var(data, o, o->off1);
			*cp = strdup(ptr);
		}

		if (fn)
			ret = fn(data, ptr);
		else if (o->posval[0].ival) {
			posval_sort(o, posval);

			ret = 1;
			for (i = 0; i < PARSE_MAX_VP; i++) {
				vp = &posval[i];
				if (!vp->ival || vp->ival[0] == '\0' || !cp)
					continue;
				all_skipped = 0;
				if (!strncmp(vp->ival, ptr, str_match_len(vp, ptr))) {
					char *rest;

					ret = 0;
					if (vp->cb)
						fn = vp->cb;
					rest = strstr(*cp ?: ptr, ":");
					if (rest) {
						if (*cp)
							*rest = '\0';
						ptr = rest + 1;
					} else
						ptr = NULL;
					break;
				}
			}
		}

		if (!all_skipped) {
			if (ret && !*cp)
				show_option_values(o);
			else if (ret && *cp)
				ret = 0;
			else if (fn && ptr)
				ret = fn(data, ptr);
		}

		break;
	}
Example #2
0
File: parse.c Project: martin21/fio
static int __handle_option(struct fio_option *o, const char *ptr, void *data,
			   int first, int more)
{
	int il, *ilp;
	long long ull, *ullp;
	long ul1, ul2;
	char **cp;
	int ret = 0, is_time = 0;

	dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name,
							o->type, ptr);

	if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) {
		fprintf(stderr, "Option %s requires an argument\n", o->name);
		return 1;
	}

	switch (o->type) {
	case FIO_OPT_STR: {
		fio_opt_str_fn *fn = o->cb;
		const struct value_pair *vp;
		struct value_pair posval[PARSE_MAX_VP];
		int i;

		posval_sort(o, posval);

		for (i = 0; i < PARSE_MAX_VP; i++) {
			vp = &posval[i];
			if (!vp->ival || vp->ival[0] == '\0')
				break;
			ret = 1;
			if (!strncmp(vp->ival, ptr, strlen(vp->ival))) {
				ret = 0;
				if (!o->off1)
					break;
				val_store(ilp, vp->oval, o->off1, data);
				break;
			}
		}

		if (ret)
			show_option_values(o);
		else if (fn)
			ret = fn(data, ptr);
		break;
	}
	case FIO_OPT_STR_VAL_TIME:
		is_time = 1;
	case FIO_OPT_INT:
	case FIO_OPT_STR_VAL: {
		fio_opt_str_val_fn *fn = o->cb;

		if (is_time)
			ret = check_str_time(ptr, &ull);
		else
			ret = check_str_bytes(ptr, &ull, data);

		if (ret)
			break;

		if (o->maxval && ull > o->maxval) {
			fprintf(stderr, "max value out of range: %lld"
					" (%d max)\n", ull, o->maxval);
			return 1;
		}
		if (o->minval && ull < o->minval) {
			fprintf(stderr, "min value out of range: %lld"
					" (%d min)\n", ull, o->minval);
			return 1;
		}

		if (fn)
			ret = fn(data, &ull);
		else {
			if (o->type == FIO_OPT_INT) {
				if (first)
					val_store(ilp, ull, o->off1, data);
				if (!more && o->off2)
					val_store(ilp, ull, o->off2, data);
			} else {
				if (first)
					val_store(ullp, ull, o->off1, data);
				if (!more && o->off2)
					val_store(ullp, ull, o->off2, data);
			}
		}
		break;
	}
	case FIO_OPT_STR_STORE: {
		fio_opt_str_fn *fn = o->cb;

		cp = td_var(data, o->off1);
		*cp = strdup(ptr);
		if (fn) {
			ret = fn(data, ptr);
			if (ret) {
				free(*cp);
				*cp = NULL;
			}
		}
		break;
	}
	case FIO_OPT_RANGE: {
		char tmp[128];
		char *p1, *p2;

		strncpy(tmp, ptr, sizeof(tmp) - 1);

		p1 = strchr(tmp, '-');
		if (!p1) {
			p1 = strchr(tmp, ':');
			if (!p1) {
				ret = 1;
				break;
			}
		}

		p2 = p1 + 1;
		*p1 = '\0';
		p1 = tmp;

		ret = 1;
		if (!check_range_bytes(p1, &ul1, data) &&
		    !check_range_bytes(p2, &ul2, data)) {
			ret = 0;
			if (ul1 > ul2) {
				unsigned long foo = ul1;

				ul1 = ul2;
				ul2 = foo;
			}

			if (first) {
				val_store(ilp, ul1, o->off1, data);
				val_store(ilp, ul2, o->off2, data);
			}
			if (o->off3 && o->off4) {
				val_store(ilp, ul1, o->off3, data);
				val_store(ilp, ul2, o->off4, data);
			}
		}

		break;
	}
	case FIO_OPT_BOOL: {
		fio_opt_int_fn *fn = o->cb;

		ret = check_int(ptr, &il);
		if (ret)
			break;

		if (o->maxval && il > (int) o->maxval) {
			fprintf(stderr, "max value out of range: %d (%d max)\n",
								il, o->maxval);
			return 1;
		}
		if (o->minval && il < o->minval) {
			fprintf(stderr, "min value out of range: %d (%d min)\n",
								il, o->minval);
			return 1;
		}

		if (o->neg)
			il = !il;

		if (fn)
			ret = fn(data, &il);
		else {
			if (first)
				val_store(ilp, il, o->off1, data);
			if (!more && o->off2)
				val_store(ilp, il, o->off2, data);
		}
		break;
	}
	case FIO_OPT_STR_SET: {
		fio_opt_str_set_fn *fn = o->cb;

		if (fn)
			ret = fn(data);
		else {
			if (first)
				val_store(ilp, 1, o->off1, data);
			if (!more && o->off2)
				val_store(ilp, 1, o->off2, data);
		}
		break;
	}
	case FIO_OPT_DEPRECATED:
		fprintf(stdout, "Option %s is deprecated\n", o->name);
		break;
	default:
		fprintf(stderr, "Bad option type %u\n", o->type);
		ret = 1;
	}

	if (ret)
		return ret;

	if (o->verify) {
		ret = o->verify(o, data);
		if (ret) {
			fprintf(stderr,"Correct format for offending option\n");
			fprintf(stderr, "%20s: %s\n", o->name, o->help);
			show_option_help(o, stderr);
		}
	}

	return ret;
}