mirror of
https://github.com/torvalds/linux.git
synced 2024-12-20 10:01:56 +00:00
29396cd573
This patch resolves some undefined behavior where variables in expr_id_data were accessed (for debugging) without being defined. To better enforce the tagged union behavior, the struct is moved into expr.c and accessors provided. Tag values (kinds) are explicitly identified. Signed-off-by: Ian Rogers <irogers@google.com> Reviewed-By: Kajol Jain<kjain@linux.ibm.com> Acked-by: Jiri Olsa <jolsa@redhat.com> Link: https://lore.kernel.org/r/20200826153055.2067780-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
128 lines
2.4 KiB
Plaintext
128 lines
2.4 KiB
Plaintext
/* Simple expression parser */
|
|
%{
|
|
#define YYDEBUG 1
|
|
#include <stdio.h>
|
|
#include "util.h"
|
|
#include "util/debug.h"
|
|
#include <stdlib.h> // strtod()
|
|
#define IN_EXPR_Y 1
|
|
#include "expr.h"
|
|
#include "smt.h"
|
|
#include <string.h>
|
|
|
|
static double d_ratio(double val0, double val1)
|
|
{
|
|
if (val1 == 0) {
|
|
return 0;
|
|
}
|
|
return val0 / val1;
|
|
}
|
|
|
|
%}
|
|
|
|
%define api.pure full
|
|
|
|
%parse-param { double *final_val }
|
|
%parse-param { struct expr_parse_ctx *ctx }
|
|
%parse-param {void *scanner}
|
|
%lex-param {void* scanner}
|
|
|
|
%union {
|
|
double num;
|
|
char *str;
|
|
}
|
|
|
|
%token EXPR_PARSE EXPR_OTHER EXPR_ERROR
|
|
%token <num> NUMBER
|
|
%token <str> ID
|
|
%destructor { free ($$); } <str>
|
|
%token MIN MAX IF ELSE SMT_ON D_RATIO
|
|
%left MIN MAX IF
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left '<' '>'
|
|
%left '-' '+'
|
|
%left '*' '/' '%'
|
|
%left NEG NOT
|
|
%type <num> expr if_expr
|
|
|
|
%{
|
|
static void expr_error(double *final_val __maybe_unused,
|
|
struct expr_parse_ctx *ctx __maybe_unused,
|
|
void *scanner,
|
|
const char *s)
|
|
{
|
|
pr_debug("%s\n", s);
|
|
}
|
|
|
|
%}
|
|
%%
|
|
|
|
start:
|
|
EXPR_PARSE all_expr
|
|
|
|
|
EXPR_OTHER all_other
|
|
|
|
all_other: all_other other
|
|
|
|
|
|
|
other: ID
|
|
{
|
|
expr__add_id(ctx, $1);
|
|
}
|
|
|
|
|
MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ','
|
|
|
|
|
'<' | '>' | D_RATIO
|
|
|
|
all_expr: if_expr { *final_val = $1; }
|
|
;
|
|
|
|
if_expr:
|
|
expr IF expr ELSE expr { $$ = $3 ? $1 : $5; }
|
|
| expr
|
|
;
|
|
|
|
expr: NUMBER
|
|
| ID {
|
|
struct expr_id_data *data;
|
|
|
|
if (expr__resolve_id(ctx, $1, &data)) {
|
|
free($1);
|
|
YYABORT;
|
|
}
|
|
|
|
$$ = expr_id_data__value(data);
|
|
free($1);
|
|
}
|
|
| expr '|' expr { $$ = (long)$1 | (long)$3; }
|
|
| expr '&' expr { $$ = (long)$1 & (long)$3; }
|
|
| expr '^' expr { $$ = (long)$1 ^ (long)$3; }
|
|
| expr '<' expr { $$ = $1 < $3; }
|
|
| expr '>' expr { $$ = $1 > $3; }
|
|
| expr '+' expr { $$ = $1 + $3; }
|
|
| expr '-' expr { $$ = $1 - $3; }
|
|
| expr '*' expr { $$ = $1 * $3; }
|
|
| expr '/' expr { if ($3 == 0) {
|
|
pr_debug("division by zero\n");
|
|
YYABORT;
|
|
}
|
|
$$ = $1 / $3;
|
|
}
|
|
| expr '%' expr { if ((long)$3 == 0) {
|
|
pr_debug("division by zero\n");
|
|
YYABORT;
|
|
}
|
|
$$ = (long)$1 % (long)$3;
|
|
}
|
|
| '-' expr %prec NEG { $$ = -$2; }
|
|
| '(' if_expr ')' { $$ = $2; }
|
|
| MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
|
|
| MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
|
|
| SMT_ON { $$ = smt_on() > 0; }
|
|
| D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); }
|
|
;
|
|
|
|
%%
|