summaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorStephen M. Cameron <stephenmcameron@gmail.com>2014-09-29 12:10:49 -0600
committerJens Axboe <axboe@fb.com>2014-09-29 12:18:33 -0600
commitb470a02cade02049509d22442addfbc88d10116e (patch)
tree24cee0fe610335c4aa90ef97dee9d6a86ef31f83 /parse.c
parent423adcc7a434abbae0547f9bed78d62f0060bac9 (diff)
downloadfio-b470a02cade02049509d22442addfbc88d10116e.tar.gz
fio-b470a02cade02049509d22442addfbc88d10116e.tar.bz2
fio: allow arithmetic expressions to be used in job files
However, the arithmetic expressions must be enclosed in parentheses. That is not a hard requirement, I just did it that way to enable the old code to be used for the existing job files, to reduce risk of breaking something that previously worked. Known issues: 1) if overflow or underflow occurs during the evaluation of arithmetic expressions, it is not detected. Likewise, detection of floating point divide by zero is a bit iffy. Calculations are carried out both as long longs and as integers. If at any point, a double precision floating point value is used, floating point values are used, and for the final long long calculation the double is cast to a long long. There may be other numeric subtleties lurking as well. These kind of things are why I require the parentheses to invoke the arithmetic processing. 2) I made no effort to work this code into the autoconf system. Have no idea how to do that, esp. with lex and yacc involved in this. 3) Suffixes (k, M, GiB, etc.) do not work with expressions. It is probably not very difficult to fix this. Signed-off-by: Stephen M. Cameron <stephenmcameron@gmail.com> Modified by me to make configure auto-detect presence of yacc/lex and enable the arithmetic only if those conditions are met. Also got rid of the Makefile in exp/ and added the targets to the general Makefile, since this makes it easier to do properly. Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/parse.c b/parse.c
index 40cd4658..c2d1cc81 100644
--- a/parse.c
+++ b/parse.c
@@ -18,6 +18,10 @@
#include "minmax.h"
#include "lib/ieee754.h"
+#ifdef CONFIG_ARITHMETIC
+#include "y.tab.h"
+#endif
+
static struct fio_option *__fio_options;
static int vp_cmp(const void *p1, const void *p2)
@@ -264,12 +268,28 @@ static unsigned long long get_mult_bytes(const char *str, int len, void *data,
return __get_mult_bytes(p, data, percent);
}
+extern int evaluate_arithmetic_expression(const char *buffer, long long *ival,
+ double *dval);
+
/*
* Convert string into a floating number. Return 1 for success and 0 otherwise.
*/
int str_to_float(const char *str, double *val)
{
- return (1 == sscanf(str, "%lf", val));
+#ifdef CONFIG_ARITHMETIC
+ int rc;
+ long long ival;
+ double dval;
+
+ if (str[0] == '(') {
+ rc = evaluate_arithmetic_expression(str, &ival, &dval);
+ if (!rc) {
+ *val = dval;
+ return 1;
+ }
+ }
+#endif
+ return 1 == sscanf(str, "%lf", val);
}
/*
@@ -279,19 +299,33 @@ int str_to_decimal(const char *str, long long *val, int kilo, void *data,
int is_seconds)
{
int len, base;
+ int rc = 1;
+#ifdef CONFIG_ARITHMETIC
+ long long ival;
+ double dval;
+#endif
len = strlen(str);
if (!len)
return 1;
- if (strstr(str, "0x") || strstr(str, "0X"))
- base = 16;
- else
- base = 10;
+#ifdef CONFIG_ARITHMETIC
+ if (str[0] == '(')
+ rc = evaluate_arithmetic_expression(str, &ival, &dval);
+ if (str[0] == '(' && !rc)
+ *val = ival;
+#endif
- *val = strtoll(str, NULL, base);
- if (*val == LONG_MAX && errno == ERANGE)
- return 1;
+ if (rc == 1) {
+ if (strstr(str, "0x") || strstr(str, "0X"))
+ base = 16;
+ else
+ base = 10;
+
+ *val = strtoll(str, NULL, base);
+ if (*val == LONG_MAX && errno == ERANGE)
+ return 1;
+ }
if (kilo) {
unsigned long long mult;