hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
kernel/tools/perf/util/expr.y
....@@ -1,65 +1,80 @@
11 /* Simple expression parser */
22 %{
3
+#define YYDEBUG 1
4
+#include <stdio.h>
35 #include "util.h"
46 #include "util/debug.h"
7
+#include <stdlib.h> // strtod()
58 #define IN_EXPR_Y 1
69 #include "expr.h"
710 #include "smt.h"
811 #include <string.h>
912
10
-#define MAXIDLEN 256
13
+static double d_ratio(double val0, double val1)
14
+{
15
+ if (val1 == 0) {
16
+ return 0;
17
+ }
18
+ return val0 / val1;
19
+}
20
+
1121 %}
1222
1323 %define api.pure full
1424
1525 %parse-param { double *final_val }
16
-%parse-param { struct parse_ctx *ctx }
17
-%parse-param { const char **pp }
18
-%lex-param { const char **pp }
26
+%parse-param { struct expr_parse_ctx *ctx }
27
+%parse-param {void *scanner}
28
+%lex-param {void* scanner}
1929
2030 %union {
21
- double num;
22
- char id[MAXIDLEN+1];
31
+ double num;
32
+ char *str;
2333 }
2434
35
+%token EXPR_PARSE EXPR_OTHER EXPR_ERROR
2536 %token <num> NUMBER
26
-%token <id> ID
27
-%token MIN MAX IF ELSE SMT_ON
37
+%token <str> ID
38
+%destructor { free ($$); } <str>
39
+%token MIN MAX IF ELSE SMT_ON D_RATIO
2840 %left MIN MAX IF
2941 %left '|'
3042 %left '^'
3143 %left '&'
44
+%left '<' '>'
3245 %left '-' '+'
3346 %left '*' '/' '%'
3447 %left NEG NOT
3548 %type <num> expr if_expr
3649
3750 %{
38
-static int expr__lex(YYSTYPE *res, const char **pp);
39
-
40
-static void expr__error(double *final_val __maybe_unused,
41
- struct parse_ctx *ctx __maybe_unused,
42
- const char **pp __maybe_unused,
51
+static void expr_error(double *final_val __maybe_unused,
52
+ struct expr_parse_ctx *ctx __maybe_unused,
53
+ void *scanner,
4354 const char *s)
4455 {
4556 pr_debug("%s\n", s);
4657 }
4758
48
-static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
49
-{
50
- int i;
51
-
52
- for (i = 0; i < ctx->num_ids; i++) {
53
- if (!strcasecmp(ctx->ids[i].name, id)) {
54
- *val = ctx->ids[i].val;
55
- return 0;
56
- }
57
- }
58
- return -1;
59
-}
60
-
6159 %}
6260 %%
61
+
62
+start:
63
+EXPR_PARSE all_expr
64
+|
65
+EXPR_OTHER all_other
66
+
67
+all_other: all_other other
68
+|
69
+
70
+other: ID
71
+{
72
+ expr__add_id(ctx, $1);
73
+}
74
+|
75
+MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ','
76
+|
77
+'<' | '>' | D_RATIO
6378
6479 all_expr: if_expr { *final_val = $1; }
6580 ;
....@@ -70,167 +85,43 @@
7085 ;
7186
7287 expr: NUMBER
73
- | ID { if (lookup_id(ctx, $1, &$$) < 0) {
74
- pr_debug("%s not found\n", $1);
75
- YYABORT;
76
- }
88
+ | ID {
89
+ struct expr_id_data *data;
90
+
91
+ if (expr__resolve_id(ctx, $1, &data)) {
92
+ free($1);
93
+ YYABORT;
94
+ }
95
+
96
+ $$ = data->val;
97
+ free($1);
7798 }
7899 | expr '|' expr { $$ = (long)$1 | (long)$3; }
79100 | expr '&' expr { $$ = (long)$1 & (long)$3; }
80101 | expr '^' expr { $$ = (long)$1 ^ (long)$3; }
102
+ | expr '<' expr { $$ = $1 < $3; }
103
+ | expr '>' expr { $$ = $1 > $3; }
81104 | expr '+' expr { $$ = $1 + $3; }
82105 | expr '-' expr { $$ = $1 - $3; }
83106 | expr '*' expr { $$ = $1 * $3; }
84
- | expr '/' expr { if ($3 == 0) YYABORT; $$ = $1 / $3; }
85
- | expr '%' expr { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; }
107
+ | expr '/' expr { if ($3 == 0) {
108
+ pr_debug("division by zero\n");
109
+ YYABORT;
110
+ }
111
+ $$ = $1 / $3;
112
+ }
113
+ | expr '%' expr { if ((long)$3 == 0) {
114
+ pr_debug("division by zero\n");
115
+ YYABORT;
116
+ }
117
+ $$ = (long)$1 % (long)$3;
118
+ }
86119 | '-' expr %prec NEG { $$ = -$2; }
87120 | '(' if_expr ')' { $$ = $2; }
88121 | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
89122 | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
90123 | SMT_ON { $$ = smt_on() > 0; }
124
+ | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); }
91125 ;
92126
93127 %%
94
-
95
-static int expr__symbol(YYSTYPE *res, const char *p, const char **pp)
96
-{
97
- char *dst = res->id;
98
- const char *s = p;
99
-
100
- if (*p == '#')
101
- *dst++ = *p++;
102
-
103
- while (isalnum(*p) || *p == '_' || *p == '.' || *p == ':' || *p == '@' || *p == '\\') {
104
- if (p - s >= MAXIDLEN)
105
- return -1;
106
- /*
107
- * Allow @ instead of / to be able to specify pmu/event/ without
108
- * conflicts with normal division.
109
- */
110
- if (*p == '@')
111
- *dst++ = '/';
112
- else if (*p == '\\')
113
- *dst++ = *++p;
114
- else
115
- *dst++ = *p;
116
- p++;
117
- }
118
- *dst = 0;
119
- *pp = p;
120
- dst = res->id;
121
- switch (dst[0]) {
122
- case 'm':
123
- if (!strcmp(dst, "min"))
124
- return MIN;
125
- if (!strcmp(dst, "max"))
126
- return MAX;
127
- break;
128
- case 'i':
129
- if (!strcmp(dst, "if"))
130
- return IF;
131
- break;
132
- case 'e':
133
- if (!strcmp(dst, "else"))
134
- return ELSE;
135
- break;
136
- case '#':
137
- if (!strcasecmp(dst, "#smt_on"))
138
- return SMT_ON;
139
- break;
140
- }
141
- return ID;
142
-}
143
-
144
-static int expr__lex(YYSTYPE *res, const char **pp)
145
-{
146
- int tok;
147
- const char *s;
148
- const char *p = *pp;
149
-
150
- while (isspace(*p))
151
- p++;
152
- s = p;
153
- switch (*p++) {
154
- case '#':
155
- case 'a' ... 'z':
156
- case 'A' ... 'Z':
157
- return expr__symbol(res, p - 1, pp);
158
- case '0' ... '9': case '.':
159
- res->num = strtod(s, (char **)&p);
160
- tok = NUMBER;
161
- break;
162
- default:
163
- tok = *s;
164
- break;
165
- }
166
- *pp = p;
167
- return tok;
168
-}
169
-
170
-/* Caller must make sure id is allocated */
171
-void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
172
-{
173
- int idx;
174
- assert(ctx->num_ids < MAX_PARSE_ID);
175
- idx = ctx->num_ids++;
176
- ctx->ids[idx].name = name;
177
- ctx->ids[idx].val = val;
178
-}
179
-
180
-void expr__ctx_init(struct parse_ctx *ctx)
181
-{
182
- ctx->num_ids = 0;
183
-}
184
-
185
-static bool already_seen(const char *val, const char *one, const char **other,
186
- int num_other)
187
-{
188
- int i;
189
-
190
- if (one && !strcasecmp(one, val))
191
- return true;
192
- for (i = 0; i < num_other; i++)
193
- if (!strcasecmp(other[i], val))
194
- return true;
195
- return false;
196
-}
197
-
198
-int expr__find_other(const char *p, const char *one, const char ***other,
199
- int *num_otherp)
200
-{
201
- const char *orig = p;
202
- int err = -1;
203
- int num_other;
204
-
205
- *other = malloc((EXPR_MAX_OTHER + 1) * sizeof(char *));
206
- if (!*other)
207
- return -1;
208
-
209
- num_other = 0;
210
- for (;;) {
211
- YYSTYPE val;
212
- int tok = expr__lex(&val, &p);
213
- if (tok == 0) {
214
- err = 0;
215
- break;
216
- }
217
- if (tok == ID && !already_seen(val.id, one, *other, num_other)) {
218
- if (num_other >= EXPR_MAX_OTHER - 1) {
219
- pr_debug("Too many extra events in %s\n", orig);
220
- break;
221
- }
222
- (*other)[num_other] = strdup(val.id);
223
- if (!(*other)[num_other])
224
- return -1;
225
- num_other++;
226
- }
227
- }
228
- (*other)[num_other] = NULL;
229
- *num_otherp = num_other;
230
- if (err) {
231
- *num_otherp = 0;
232
- free(*other);
233
- *other = NULL;
234
- }
235
- return err;
236
-}