126226a97SJiri Olsa %option prefix="expr_" 226226a97SJiri Olsa %option reentrant 326226a97SJiri Olsa %option bison-bridge 426226a97SJiri Olsa 526226a97SJiri Olsa %{ 626226a97SJiri Olsa #include <linux/compiler.h> 726226a97SJiri Olsa #include "expr.h" 826226a97SJiri Olsa #include "expr-bison.h" 93613f6c1SIan Rogers #include <math.h> 1026226a97SJiri Olsa 1126226a97SJiri Olsa char *expr_get_text(yyscan_t yyscanner); 1226226a97SJiri Olsa YYSTYPE *expr_get_lval(yyscan_t yyscanner); 1326226a97SJiri Olsa 147db2fd0bSIan Rogers static double __value(YYSTYPE *yylval, char *str, int token) 1526226a97SJiri Olsa { 167db2fd0bSIan Rogers double num; 1726226a97SJiri Olsa 1826226a97SJiri Olsa errno = 0; 197db2fd0bSIan Rogers num = strtod(str, NULL); 2026226a97SJiri Olsa if (errno) 2126226a97SJiri Olsa return EXPR_ERROR; 2226226a97SJiri Olsa 2326226a97SJiri Olsa yylval->num = num; 2426226a97SJiri Olsa return token; 2526226a97SJiri Olsa } 2626226a97SJiri Olsa 277db2fd0bSIan Rogers static int value(yyscan_t scanner) 2826226a97SJiri Olsa { 2926226a97SJiri Olsa YYSTYPE *yylval = expr_get_lval(scanner); 3026226a97SJiri Olsa char *text = expr_get_text(scanner); 3126226a97SJiri Olsa 327db2fd0bSIan Rogers return __value(yylval, text, NUMBER); 3326226a97SJiri Olsa } 3426226a97SJiri Olsa 3526226a97SJiri Olsa /* 3626226a97SJiri Olsa * Allow @ instead of / to be able to specify pmu/event/ without 3726226a97SJiri Olsa * conflicts with normal division. 3826226a97SJiri Olsa */ 391e1a873dSKajol Jain static char *normalize(char *str, int runtime) 4026226a97SJiri Olsa { 4126226a97SJiri Olsa char *ret = str; 4226226a97SJiri Olsa char *dst = str; 4326226a97SJiri Olsa 4426226a97SJiri Olsa while (*str) { 4585c44913SSohom Datta if (*str == '\\') { 4626226a97SJiri Olsa *dst++ = *++str; 4785c44913SSohom Datta if (!*str) 4885c44913SSohom Datta break; 4985c44913SSohom Datta } 501e1a873dSKajol Jain else if (*str == '?') { 511e1a873dSKajol Jain char *paramval; 521e1a873dSKajol Jain int i = 0; 531e1a873dSKajol Jain int size = asprintf(¶mval, "%d", runtime); 541e1a873dSKajol Jain 551e1a873dSKajol Jain if (size < 0) 561e1a873dSKajol Jain *dst++ = '0'; 571e1a873dSKajol Jain else { 581e1a873dSKajol Jain while (i < size) 591e1a873dSKajol Jain *dst++ = paramval[i++]; 601e1a873dSKajol Jain free(paramval); 611e1a873dSKajol Jain } 621e1a873dSKajol Jain } 6326226a97SJiri Olsa else 6426226a97SJiri Olsa *dst++ = *str; 6526226a97SJiri Olsa str++; 6626226a97SJiri Olsa } 6726226a97SJiri Olsa 6826226a97SJiri Olsa *dst = 0x0; 6926226a97SJiri Olsa return ret; 7026226a97SJiri Olsa } 7126226a97SJiri Olsa 721e1a873dSKajol Jain static int str(yyscan_t scanner, int token, int runtime) 7326226a97SJiri Olsa { 7426226a97SJiri Olsa YYSTYPE *yylval = expr_get_lval(scanner); 7526226a97SJiri Olsa char *text = expr_get_text(scanner); 7626226a97SJiri Olsa 771e1a873dSKajol Jain yylval->str = normalize(strdup(text), runtime); 7826226a97SJiri Olsa if (!yylval->str) 7926226a97SJiri Olsa return EXPR_ERROR; 8026226a97SJiri Olsa 811e1a873dSKajol Jain yylval->str = normalize(yylval->str, runtime); 8226226a97SJiri Olsa return token; 8326226a97SJiri Olsa } 843613f6c1SIan Rogers 851725e9cdSIan Rogers static int literal(yyscan_t scanner, const struct expr_scanner_ctx *sctx) 863613f6c1SIan Rogers { 873613f6c1SIan Rogers YYSTYPE *yylval = expr_get_lval(scanner); 883613f6c1SIan Rogers 891725e9cdSIan Rogers yylval->num = expr__get_literal(expr_get_text(scanner), sctx); 903340a083SIan Rogers if (isnan(yylval->num)) { 913340a083SIan Rogers if (!sctx->is_test) 923613f6c1SIan Rogers return EXPR_ERROR; 933340a083SIan Rogers yylval->num = 1; 943340a083SIan Rogers } 953613f6c1SIan Rogers return LITERAL; 963613f6c1SIan Rogers } 9726226a97SJiri Olsa %} 9826226a97SJiri Olsa 99e5287e6dSIan Rogers number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)? 10026226a97SJiri Olsa 10126226a97SJiri Olsa sch [-,=] 10226226a97SJiri Olsa spec \\{sch} 1031e1a873dSKajol Jain sym [0-9a-zA-Z_\.:@?]+ 1045b3141d0SIan Rogers symbol ({spec}|{sym})+ 1053613f6c1SIan Rogers literal #[0-9a-zA-Z_\.\-]+ 10626226a97SJiri Olsa 10726226a97SJiri Olsa %% 108871f9f59SJiri Olsa struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); 109871f9f59SJiri Olsa 1103e21a28aSIan Rogers d_ratio { return D_RATIO; } 11126226a97SJiri Olsa max { return MAX; } 11226226a97SJiri Olsa min { return MIN; } 11326226a97SJiri Olsa if { return IF; } 11426226a97SJiri Olsa else { return ELSE; } 1159aba0adaSIan Rogers source_count { return SOURCE_COUNT; } 1164a4a9bf9SIan Rogers has_event { return HAS_EVENT; } 117*9d5da30eSJames Clark strcmp_cpuid_str { return STRCMP_CPUID_STR; } 1181725e9cdSIan Rogers {literal} { return literal(yyscanner, sctx); } 1197db2fd0bSIan Rogers {number} { return value(yyscanner); } 1201e1a873dSKajol Jain {symbol} { return str(yyscanner, ID, sctx->runtime); } 12126226a97SJiri Olsa "|" { return '|'; } 12226226a97SJiri Olsa "^" { return '^'; } 12326226a97SJiri Olsa "&" { return '&'; } 124ff1a12f9SIan Rogers "<" { return '<'; } 125ff1a12f9SIan Rogers ">" { return '>'; } 12626226a97SJiri Olsa "-" { return '-'; } 12726226a97SJiri Olsa "+" { return '+'; } 12826226a97SJiri Olsa "*" { return '*'; } 12926226a97SJiri Olsa "/" { return '/'; } 13026226a97SJiri Olsa "%" { return '%'; } 13126226a97SJiri Olsa "(" { return '('; } 13226226a97SJiri Olsa ")" { return ')'; } 13326226a97SJiri Olsa "," { return ','; } 13426226a97SJiri Olsa . { } 13526226a97SJiri Olsa %% 13626226a97SJiri Olsa 13726226a97SJiri Olsa int expr_wrap(void *scanner __maybe_unused) 13826226a97SJiri Olsa { 13926226a97SJiri Olsa return 1; 14026226a97SJiri Olsa } 141