From 18722a18d75aaf487917776e077a8e61d14c8b8d Mon Sep 17 00:00:00 2001 From: "Stephen M. Cameron" Date: Mon, 29 Sep 2014 12:15:35 -0600 Subject: [PATCH] fio: support suffixes in expression parser Note that time values in expressions by default have units of microseconds Signed-off-by: Stephen M. Cameron Signed-off-by: Jens Axboe --- exp/expression-parser.l | 68 +++++++++++++++++++++++++++++++++++- exp/expression-parser.y | 12 +++++++ exp/test-expression-parser.c | 2 +- fio.1 | 7 ++-- parse.c | 8 +++-- 5 files changed, 91 insertions(+), 6 deletions(-) diff --git a/exp/expression-parser.l b/exp/expression-parser.l index 388515e2..f688da11 100644 --- a/exp/expression-parser.l +++ b/exp/expression-parser.l @@ -36,12 +36,78 @@ extern int yyerror(long long *result, double *dresult, static void __attribute__((unused)) yyunput(int c,char *buf_ptr); static int __attribute__((unused)) input(void); +#define set_suffix_value(yylval, i_val, d_val, has_d_val) \ + (yylval).v.dval = (d_val); \ + (yylval).v.ival = (i_val); \ + (yylval).v.has_dval = (has_d_val); \ + (yylval).v.has_error = 0; + %} %% -bye return BYE; +bye return BYE; +[kK]|[kK][bB] { + set_suffix_value(yylval, 1024, 1024.0, 0); + return SUFFIX; + } +[Mm]|[Mm][bB] { + set_suffix_value(yylval, 1024 * 1024, 1024.0 * 1024.0, 0); + return SUFFIX; + } +[mM][sS] { + set_suffix_value(yylval, 1000, 1000.0, 1); + return SUFFIX; + } +[uU][sS] { + set_suffix_value(yylval, 1, 1.0, 1); + return SUFFIX; + } +[gG]|[Gg][Bb] { + set_suffix_value(yylval, 1024LL * 1024 * 1024, 1024.0 * 1024.0 * 1024, 0); + return SUFFIX; + } +[tT]|[tT][bB] { + set_suffix_value(yylval, 1024LL * 1024 * 1024 * 1024, + 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024, 0); + return SUFFIX; + } +[pP]|[pP][bB] { + set_suffix_value(yylval, 1024LL * 1024 * 1024 * 1024 * 1024, + 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0, 0); + return SUFFIX; + } +[kK][iI][Bb] { + set_suffix_value(yylval, 1000LL, 1000.0, 0); + return SUFFIX; + } +[mM][Ii][bB] { + set_suffix_value(yylval, 1000000LL, 1000000.0 , 0); + return SUFFIX; + } +[gG][iI][Bb] { + set_suffix_value(yylval, 1000000000LL, 1000000000.0 , 0); + return SUFFIX; + } +[pP][iI][Bb] { + set_suffix_value(yylval, 1000000000000LL, 1000000000000.0 , 0); + return SUFFIX; + } +[sS] { + set_suffix_value(yylval, 1000000LL, 1000000.0 , 0); + return SUFFIX; + } +[dD] { + set_suffix_value(yylval, 60LL * 60LL * 24LL * 1000000LL, + 60.0 * 60.0 * 24.0 * 1000000.0, 0); + return SUFFIX; + } +[hH] { + set_suffix_value(yylval, 60LL * 60LL * 1000000LL, + 60.0 * 60.0 * 1000000.0, 0); + return SUFFIX; + } [ \t] ; /* ignore whitespace */ #.+ ; /* ignore comments */ [0-9]*[.][0-9]+ { diff --git a/exp/expression-parser.y b/exp/expression-parser.y index dbd8b6c2..1c1ebf88 100644 --- a/exp/expression-parser.y +++ b/exp/expression-parser.y @@ -55,6 +55,7 @@ extern void yyrestart(FILE *file); %token NUMBER %token BYE +%token SUFFIX %left '-' '+' %left '*' '/' %nonassoc UMINUS @@ -119,6 +120,17 @@ expression: expression '+' expression { $$.has_error = $2.has_error; } | '(' expression ')' { $$ = $2; } + | expression SUFFIX { + if (!$1.has_dval && !$2.has_dval) + $$.ival = $1.ival * $2.ival; + else + $$.ival = (long long) $1.dval * $2.dval; + if ($1.has_dval || $2.has_dval) + $$.dval = $1.dval * $2.dval; + else + $$.dval = $1.ival * $2.ival; + $$.has_error = $1.has_error || $2.has_error; + } | NUMBER { $$ = $1; } | BYE { $$ = $1; *bye = 1; }; %% diff --git a/exp/test-expression-parser.c b/exp/test-expression-parser.c index 6b4ab5dd..a9794dcb 100644 --- a/exp/test-expression-parser.c +++ b/exp/test-expression-parser.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) buffer[rc - 1] = '\0'; rc = evaluate_arithmetic_expression(buffer, &result, &dresult); if (!rc) { - printf("%lld (%lf)\n", result, dresult); + printf("%lld (%20.20lf)\n", result, dresult); } else { result = 0; dresult = 0; diff --git a/fio.1 b/fio.1 index 2fbdb00d..fb5ca46d 100644 --- a/fio.1 +++ b/fio.1 @@ -117,9 +117,12 @@ may override any parameter set in global sections. .SS Types Some parameters may take arguments of a specific type. Anywhere a numeric value is required, an arithmetic expression may be used, -provided it is surrounded by parentheses. Suffixes currently do not -work with arithmetic expressions. Supported operators are +provided it is surrounded by parentheses. +Supported operators are addition, subtraction, multiplication and division. +For time values in expressions +units are microseconds by default. This is different than for time +values not in expressions (not enclosed in parentheses). The types used are: .TP .I str diff --git a/parse.c b/parse.c index c2d1cc81..b632bf1a 100644 --- a/parse.c +++ b/parse.c @@ -312,8 +312,12 @@ int str_to_decimal(const char *str, long long *val, int kilo, void *data, #ifdef CONFIG_ARITHMETIC if (str[0] == '(') rc = evaluate_arithmetic_expression(str, &ival, &dval); - if (str[0] == '(' && !rc) - *val = ival; + if (str[0] == '(' && !rc) { + if (!kilo && is_seconds) + *val = ival / 1000000LL; + else + *val = ival; + } #endif if (rc == 1) { -- 2.25.1