1 %option prefix="expr_"
2 %option reentrant
3 %option bison-bridge
4
5 %{
6 #include <linux/compiler.h>
7 #include "expr.h"
8 #include "expr-bison.h"
9 #include <math.h>
10
11 char *expr_get_text(yyscan_t yyscanner);
12 YYSTYPE *expr_get_lval(yyscan_t yyscanner);
13
__value(YYSTYPE * yylval,char * str,int token)14 static double __value(YYSTYPE *yylval, char *str, int token)
15 {
16 double num;
17
18 errno = 0;
19 num = strtod(str, NULL);
20 if (errno)
21 return EXPR_ERROR;
22
23 yylval->num = num;
24 return token;
25 }
26
value(yyscan_t scanner)27 static int value(yyscan_t scanner)
28 {
29 YYSTYPE *yylval = expr_get_lval(scanner);
30 char *text = expr_get_text(scanner);
31
32 return __value(yylval, text, NUMBER);
33 }
34
35 /*
36 * Allow @ instead of / to be able to specify pmu/event/ without
37 * conflicts with normal division.
38 */
normalize(char * str,int runtime)39 static char *normalize(char *str, int runtime)
40 {
41 char *ret = str;
42 char *dst = str;
43
44 while (*str) {
45 if (*str == '\\')
46 *dst++ = *++str;
47 else if (*str == '?') {
48 char *paramval;
49 int i = 0;
50 int size = asprintf(¶mval, "%d", runtime);
51
52 if (size < 0)
53 *dst++ = '0';
54 else {
55 while (i < size)
56 *dst++ = paramval[i++];
57 free(paramval);
58 }
59 }
60 else
61 *dst++ = *str;
62 str++;
63 }
64
65 *dst = 0x0;
66 return ret;
67 }
68
str(yyscan_t scanner,int token,int runtime)69 static int str(yyscan_t scanner, int token, int runtime)
70 {
71 YYSTYPE *yylval = expr_get_lval(scanner);
72 char *text = expr_get_text(scanner);
73
74 yylval->str = normalize(strdup(text), runtime);
75 if (!yylval->str)
76 return EXPR_ERROR;
77
78 yylval->str = normalize(yylval->str, runtime);
79 return token;
80 }
81
literal(yyscan_t scanner)82 static int literal(yyscan_t scanner)
83 {
84 YYSTYPE *yylval = expr_get_lval(scanner);
85
86 yylval->num = expr__get_literal(expr_get_text(scanner));
87 if (isnan(yylval->num))
88 return EXPR_ERROR;
89
90 return LITERAL;
91 }
92 %}
93
94 number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)
95
96 sch [-,=]
97 spec \\{sch}
98 sym [0-9a-zA-Z_\.:@?]+
99 symbol ({spec}|{sym})+
100 literal #[0-9a-zA-Z_\.\-]+
101
102 %%
103 struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
104
105 d_ratio { return D_RATIO; }
106 max { return MAX; }
107 min { return MIN; }
108 if { return IF; }
109 else { return ELSE; }
110 source_count { return SOURCE_COUNT; }
111 {literal} { return literal(yyscanner); }
112 {number} { return value(yyscanner); }
113 {symbol} { return str(yyscanner, ID, sctx->runtime); }
114 "|" { return '|'; }
115 "^" { return '^'; }
116 "&" { return '&'; }
117 "<" { return '<'; }
118 ">" { return '>'; }
119 "-" { return '-'; }
120 "+" { return '+'; }
121 "*" { return '*'; }
122 "/" { return '/'; }
123 "%" { return '%'; }
124 "(" { return '('; }
125 ")" { return ')'; }
126 "," { return ','; }
127 . { }
128 %%
129
130 int expr_wrap(void *scanner __maybe_unused)
131 {
132 return 1;
133 }
134