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) { 45ec5c5b3dSIan Rogers if (*str == '\\') 4626226a97SJiri Olsa *dst++ = *++str; 471e1a873dSKajol Jain else if (*str == '?') { 481e1a873dSKajol Jain char *paramval; 491e1a873dSKajol Jain int i = 0; 501e1a873dSKajol Jain int size = asprintf(¶mval, "%d", runtime); 511e1a873dSKajol Jain 521e1a873dSKajol Jain if (size < 0) 531e1a873dSKajol Jain *dst++ = '0'; 541e1a873dSKajol Jain else { 551e1a873dSKajol Jain while (i < size) 561e1a873dSKajol Jain *dst++ = paramval[i++]; 571e1a873dSKajol Jain free(paramval); 581e1a873dSKajol Jain } 591e1a873dSKajol Jain } 6026226a97SJiri Olsa else 6126226a97SJiri Olsa *dst++ = *str; 6226226a97SJiri Olsa str++; 6326226a97SJiri Olsa } 6426226a97SJiri Olsa 6526226a97SJiri Olsa *dst = 0x0; 6626226a97SJiri Olsa return ret; 6726226a97SJiri Olsa } 6826226a97SJiri Olsa 691e1a873dSKajol Jain static int str(yyscan_t scanner, int token, int runtime) 7026226a97SJiri Olsa { 7126226a97SJiri Olsa YYSTYPE *yylval = expr_get_lval(scanner); 7226226a97SJiri Olsa char *text = expr_get_text(scanner); 7326226a97SJiri Olsa 741e1a873dSKajol Jain yylval->str = normalize(strdup(text), runtime); 7526226a97SJiri Olsa if (!yylval->str) 7626226a97SJiri Olsa return EXPR_ERROR; 7726226a97SJiri Olsa 781e1a873dSKajol Jain yylval->str = normalize(yylval->str, runtime); 7926226a97SJiri Olsa return token; 8026226a97SJiri Olsa } 813613f6c1SIan Rogers 823613f6c1SIan Rogers static int literal(yyscan_t scanner) 833613f6c1SIan Rogers { 843613f6c1SIan Rogers YYSTYPE *yylval = expr_get_lval(scanner); 853613f6c1SIan Rogers 863613f6c1SIan Rogers yylval->num = expr__get_literal(expr_get_text(scanner)); 873613f6c1SIan Rogers if (isnan(yylval->num)) 883613f6c1SIan Rogers return EXPR_ERROR; 893613f6c1SIan Rogers 903613f6c1SIan Rogers return LITERAL; 913613f6c1SIan Rogers } 9226226a97SJiri Olsa %} 9326226a97SJiri Olsa 94a45badc7SIan Rogers number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+) 9526226a97SJiri Olsa 9626226a97SJiri Olsa sch [-,=] 9726226a97SJiri Olsa spec \\{sch} 981e1a873dSKajol Jain sym [0-9a-zA-Z_\.:@?]+ 995b3141d0SIan Rogers symbol ({spec}|{sym})+ 1003613f6c1SIan Rogers literal #[0-9a-zA-Z_\.\-]+ 10126226a97SJiri Olsa 10226226a97SJiri Olsa %% 103871f9f59SJiri Olsa struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); 104871f9f59SJiri Olsa 1053e21a28aSIan Rogers d_ratio { return D_RATIO; } 10626226a97SJiri Olsa max { return MAX; } 10726226a97SJiri Olsa min { return MIN; } 10826226a97SJiri Olsa if { return IF; } 10926226a97SJiri Olsa else { return ELSE; } 110*9aba0adaSIan Rogers source_count { return SOURCE_COUNT; } 1113613f6c1SIan Rogers {literal} { return literal(yyscanner); } 1127db2fd0bSIan Rogers {number} { return value(yyscanner); } 1131e1a873dSKajol Jain {symbol} { return str(yyscanner, ID, sctx->runtime); } 11426226a97SJiri Olsa "|" { return '|'; } 11526226a97SJiri Olsa "^" { return '^'; } 11626226a97SJiri Olsa "&" { return '&'; } 117ff1a12f9SIan Rogers "<" { return '<'; } 118ff1a12f9SIan Rogers ">" { return '>'; } 11926226a97SJiri Olsa "-" { return '-'; } 12026226a97SJiri Olsa "+" { return '+'; } 12126226a97SJiri Olsa "*" { return '*'; } 12226226a97SJiri Olsa "/" { return '/'; } 12326226a97SJiri Olsa "%" { return '%'; } 12426226a97SJiri Olsa "(" { return '('; } 12526226a97SJiri Olsa ")" { return ')'; } 12626226a97SJiri Olsa "," { return ','; } 12726226a97SJiri Olsa . { } 12826226a97SJiri Olsa %% 12926226a97SJiri Olsa 13026226a97SJiri Olsa int expr_wrap(void *scanner __maybe_unused) 13126226a97SJiri Olsa { 13226226a97SJiri Olsa return 1; 13326226a97SJiri Olsa } 134