xref: /linux-6.15/tools/perf/util/expr.l (revision 1e1a873d)
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"
926226a97SJiri Olsa 
1026226a97SJiri Olsa char *expr_get_text(yyscan_t yyscanner);
1126226a97SJiri Olsa YYSTYPE *expr_get_lval(yyscan_t yyscanner);
1226226a97SJiri Olsa 
1326226a97SJiri Olsa static int __value(YYSTYPE *yylval, char *str, int base, int token)
1426226a97SJiri Olsa {
1526226a97SJiri Olsa 	u64 num;
1626226a97SJiri Olsa 
1726226a97SJiri Olsa 	errno = 0;
1826226a97SJiri Olsa 	num = strtoull(str, NULL, base);
1926226a97SJiri Olsa 	if (errno)
2026226a97SJiri Olsa 		return EXPR_ERROR;
2126226a97SJiri Olsa 
2226226a97SJiri Olsa 	yylval->num = num;
2326226a97SJiri Olsa 	return token;
2426226a97SJiri Olsa }
2526226a97SJiri Olsa 
2626226a97SJiri Olsa static int value(yyscan_t scanner, int base)
2726226a97SJiri Olsa {
2826226a97SJiri Olsa 	YYSTYPE *yylval = expr_get_lval(scanner);
2926226a97SJiri Olsa 	char *text = expr_get_text(scanner);
3026226a97SJiri Olsa 
3126226a97SJiri Olsa 	return __value(yylval, text, base, NUMBER);
3226226a97SJiri Olsa }
3326226a97SJiri Olsa 
3426226a97SJiri Olsa /*
3526226a97SJiri Olsa  * Allow @ instead of / to be able to specify pmu/event/ without
3626226a97SJiri Olsa  * conflicts with normal division.
3726226a97SJiri Olsa  */
38*1e1a873dSKajol Jain static char *normalize(char *str, int runtime)
3926226a97SJiri Olsa {
4026226a97SJiri Olsa 	char *ret = str;
4126226a97SJiri Olsa 	char *dst = str;
4226226a97SJiri Olsa 
4326226a97SJiri Olsa 	while (*str) {
4426226a97SJiri Olsa 		if (*str == '@')
4526226a97SJiri Olsa 			*dst++ = '/';
4626226a97SJiri Olsa 		else if (*str == '\\')
4726226a97SJiri Olsa 			*dst++ = *++str;
48*1e1a873dSKajol Jain 		 else if (*str == '?') {
49*1e1a873dSKajol Jain 			char *paramval;
50*1e1a873dSKajol Jain 			int i = 0;
51*1e1a873dSKajol Jain 			int size = asprintf(&paramval, "%d", runtime);
52*1e1a873dSKajol Jain 
53*1e1a873dSKajol Jain 			if (size < 0)
54*1e1a873dSKajol Jain 				*dst++ = '0';
55*1e1a873dSKajol Jain 			else {
56*1e1a873dSKajol Jain 				while (i < size)
57*1e1a873dSKajol Jain 					*dst++ = paramval[i++];
58*1e1a873dSKajol Jain 				free(paramval);
59*1e1a873dSKajol Jain 			}
60*1e1a873dSKajol Jain 		}
6126226a97SJiri Olsa 		else
6226226a97SJiri Olsa 			*dst++ = *str;
6326226a97SJiri Olsa 		str++;
6426226a97SJiri Olsa 	}
6526226a97SJiri Olsa 
6626226a97SJiri Olsa 	*dst = 0x0;
6726226a97SJiri Olsa 	return ret;
6826226a97SJiri Olsa }
6926226a97SJiri Olsa 
70*1e1a873dSKajol Jain static int str(yyscan_t scanner, int token, int runtime)
7126226a97SJiri Olsa {
7226226a97SJiri Olsa 	YYSTYPE *yylval = expr_get_lval(scanner);
7326226a97SJiri Olsa 	char *text = expr_get_text(scanner);
7426226a97SJiri Olsa 
75*1e1a873dSKajol Jain 	yylval->str = normalize(strdup(text), runtime);
7626226a97SJiri Olsa 	if (!yylval->str)
7726226a97SJiri Olsa 		return EXPR_ERROR;
7826226a97SJiri Olsa 
79*1e1a873dSKajol Jain 	yylval->str = normalize(yylval->str, runtime);
8026226a97SJiri Olsa 	return token;
8126226a97SJiri Olsa }
8226226a97SJiri Olsa %}
8326226a97SJiri Olsa 
8426226a97SJiri Olsa number		[0-9]+
8526226a97SJiri Olsa 
8626226a97SJiri Olsa sch		[-,=]
8726226a97SJiri Olsa spec		\\{sch}
88*1e1a873dSKajol Jain sym		[0-9a-zA-Z_\.:@?]+
89*1e1a873dSKajol Jain symbol		{spec}*{sym}*{spec}*{sym}*{spec}*{sym}
9026226a97SJiri Olsa 
9126226a97SJiri Olsa %%
92871f9f59SJiri Olsa 	struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
93871f9f59SJiri Olsa 
9426226a97SJiri Olsa 	{
95871f9f59SJiri Olsa 		int start_token = sctx->start_token;
9626226a97SJiri Olsa 
97871f9f59SJiri Olsa 		if (sctx->start_token) {
98871f9f59SJiri Olsa 			sctx->start_token = 0;
9926226a97SJiri Olsa 			return start_token;
10026226a97SJiri Olsa 		}
10126226a97SJiri Olsa 	}
10226226a97SJiri Olsa 
10326226a97SJiri Olsa max		{ return MAX; }
10426226a97SJiri Olsa min		{ return MIN; }
10526226a97SJiri Olsa if		{ return IF; }
10626226a97SJiri Olsa else		{ return ELSE; }
10726226a97SJiri Olsa #smt_on		{ return SMT_ON; }
10826226a97SJiri Olsa {number}	{ return value(yyscanner, 10); }
109*1e1a873dSKajol Jain {symbol}	{ return str(yyscanner, ID, sctx->runtime); }
11026226a97SJiri Olsa "|"		{ return '|'; }
11126226a97SJiri Olsa "^"		{ return '^'; }
11226226a97SJiri Olsa "&"		{ return '&'; }
11326226a97SJiri Olsa "-"		{ return '-'; }
11426226a97SJiri Olsa "+"		{ return '+'; }
11526226a97SJiri Olsa "*"		{ return '*'; }
11626226a97SJiri Olsa "/"		{ return '/'; }
11726226a97SJiri Olsa "%"		{ return '%'; }
11826226a97SJiri Olsa "("		{ return '('; }
11926226a97SJiri Olsa ")"		{ return ')'; }
12026226a97SJiri Olsa ","		{ return ','; }
12126226a97SJiri Olsa .		{ }
12226226a97SJiri Olsa %%
12326226a97SJiri Olsa 
12426226a97SJiri Olsa int expr_wrap(void *scanner __maybe_unused)
12526226a97SJiri Olsa {
12626226a97SJiri Olsa 	return 1;
12726226a97SJiri Olsa }
128