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
__value(YYSTYPE * yylval,char * str,int token)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
value(yyscan_t scanner)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 */
normalize(char * str,int runtime)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
str(yyscan_t scanner,int token,int runtime)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
literal(yyscan_t scanner,const struct expr_scanner_ctx * sctx)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