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