xref: /openbmc/linux/tools/perf/util/expr.l (revision 2540d3c9)
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  
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  
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   */
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(&paramval, "%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  
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  
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]+)(e-?[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