perf probe: Fix kretprobe issue caused by GCC bug
[linux-2.6-microblaze.git] / tools / perf / util / expr.l
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
10 char *expr_get_text(yyscan_t yyscanner);
11 YYSTYPE *expr_get_lval(yyscan_t yyscanner);
12
13 static 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
26 static 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  */
38 static 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
70 static 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
84 number          ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)
85
86 sch             [-,=]
87 spec            \\{sch}
88 sym             [0-9a-zA-Z_\.:@?]+
89 symbol          ({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
103 d_ratio         { return D_RATIO; }
104 max             { return MAX; }
105 min             { return MIN; }
106 if              { return IF; }
107 else            { 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
127 int expr_wrap(void *scanner __maybe_unused)
128 {
129         return 1;
130 }