X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=exp%2Fexpression-parser.y;h=d664b8edd310d3ab36c8b5880158ded0c5507c32;hb=14a74557d9f7737a7b2427aef151475d5ce3937c;hp=1c1ebf88492028c25a91ab935b08c486a916b5ff;hpb=18722a18d75aaf487917776e077a8e61d14c8b8d;p=fio.git diff --git a/exp/expression-parser.y b/exp/expression-parser.y index 1c1ebf88..d664b8ed 100644 --- a/exp/expression-parser.y +++ b/exp/expression-parser.y @@ -20,6 +20,7 @@ #include #include +#include struct parser_value_type { double dval; @@ -37,10 +38,12 @@ typedef union valtype { int yyerror(__attribute__((unused)) long long *result, __attribute__((unused)) double *dresult, __attribute__((unused)) int *has_error, - __attribute__((unused)) int *bye, const char *msg); + __attribute__((unused)) int *units_specified, + __attribute__((unused)) const char *msg); extern int yylex(void); extern void yyrestart(FILE *file); +extern int lexer_value_is_time; %} @@ -57,12 +60,15 @@ extern void yyrestart(FILE *file); %token BYE %token SUFFIX %left '-' '+' +%right SUFFIX %left '*' '/' +%right '^' +%left '%' %nonassoc UMINUS %parse-param { long long *result } %parse-param { double *dresult } %parse-param { int *has_error } -%parse-param { int *bye } +%parse-param { int *units_specified } %type expression %% @@ -130,9 +136,51 @@ expression: expression '+' expression { else $$.dval = $1.ival * $2.ival; $$.has_error = $1.has_error || $2.has_error; + *units_specified = 1; } - | NUMBER { $$ = $1; } - | BYE { $$ = $1; *bye = 1; }; + | expression '%' expression { + if ($1.has_dval || $3.has_dval) + yyerror(0, 0, 0, 0, "modulo on floats"); + if ($3.ival == 0) + yyerror(0, 0, 0, 0, "divide by zero"); + else { + $$.ival = $1.ival % $3.ival; + $$.dval = $$.ival; + } + $$.has_error = $1.has_error || $3.has_error; + } + | expression '^' expression { + $$.has_error = $1.has_error || $3.has_error; + if (!$1.has_dval && !$3.has_dval) { + int i; + + if ($3.ival == 0) { + $$.ival = 1; + } else if ($3.ival > 0) { + long long tmp = $1.ival; + $$.ival = 1.0; + for (i = 0; i < $3.ival; i++) + $$.ival *= tmp; + } else { + /* integers, 2^-3, ok, we now have doubles */ + double tmp; + if ($1.ival == 0 && $3.ival == 0) { + tmp = 1.0; + $$.has_error = 1; + } else { + double x = (double) $1.ival; + double y = (double) $3.ival; + tmp = pow(x, y); + } + $$.ival = (long long) tmp; + } + $$.dval = pow($1.dval, $3.dval); + } else { + $$.dval = pow($1.dval, $3.dval); + $$.ival = (long long) $$.dval; + } + } + | NUMBER { $$ = $1; }; %% #include @@ -140,7 +188,7 @@ expression: expression '+' expression { static int lexer_read_offset = 0; static char lexer_input_buffer[1000]; -int lexer_input(char* buffer, int *bytes_read, int bytes_requested) +int lexer_input(char* buffer, unsigned int *bytes_read, int bytes_requested) { int bytes_left = strlen(lexer_input_buffer) - lexer_read_offset; @@ -166,27 +214,34 @@ static void setup_to_parse_string(const char *string) lexer_read_offset = 0; } -int evaluate_arithmetic_expression(const char *buffer, long long *ival, double *dval) +int evaluate_arithmetic_expression(const char *buffer, long long *ival, double *dval, + double implied_units, int is_time) { - int rc, bye = 0, has_error = 0; + int rc, units_specified = 0, has_error = 0; + lexer_value_is_time = is_time; setup_to_parse_string(buffer); - rc = yyparse(ival, dval, &has_error, &bye); + rc = yyparse(ival, dval, &has_error, &units_specified); yyrestart(NULL); - if (rc || bye || has_error) { + if (rc || has_error) { *ival = 0; *dval = 0; has_error = 1; } + if (!units_specified) { + *ival = (int) ((double) *ival * implied_units); + *dval = *dval * implied_units; + } return has_error; } int yyerror(__attribute__((unused)) long long *result, __attribute__((unused)) double *dresult, __attribute__((unused)) int *has_error, - __attribute__((unused)) int *bye, const char *msg) + __attribute__((unused)) int *units_specified, + __attribute__((unused)) const char *msg) { - fprintf(stderr, "%s\n", msg); + /* We do not need to do anything here. */ return 0; }