0001 %option prefix="expr_"
0002 %option reentrant
0003 %option bison-bridge
0004
0005 %{
0006 #include <linux/compiler.h>
0007 #include "expr.h"
0008 #include "expr-bison.h"
0009 #include <math.h>
0010
0011 char *expr_get_text(yyscan_t yyscanner);
0012 YYSTYPE *expr_get_lval(yyscan_t yyscanner);
0013
0014 static double __value(YYSTYPE *yylval, char *str, int token)
0015 {
0016 double num;
0017
0018 errno = 0;
0019 num = strtod(str, NULL);
0020 if (errno)
0021 return EXPR_ERROR;
0022
0023 yylval->num = num;
0024 return token;
0025 }
0026
0027 static int value(yyscan_t scanner)
0028 {
0029 YYSTYPE *yylval = expr_get_lval(scanner);
0030 char *text = expr_get_text(scanner);
0031
0032 return __value(yylval, text, NUMBER);
0033 }
0034
0035 /*
0036 * Allow @ instead of / to be able to specify pmu/event/ without
0037 * conflicts with normal division.
0038 */
0039 static char *normalize(char *str, int runtime)
0040 {
0041 char *ret = str;
0042 char *dst = str;
0043
0044 while (*str) {
0045 if (*str == '\\')
0046 *dst++ = *++str;
0047 else if (*str == '?') {
0048 char *paramval;
0049 int i = 0;
0050 int size = asprintf(¶mval, "%d", runtime);
0051
0052 if (size < 0)
0053 *dst++ = '0';
0054 else {
0055 while (i < size)
0056 *dst++ = paramval[i++];
0057 free(paramval);
0058 }
0059 }
0060 else
0061 *dst++ = *str;
0062 str++;
0063 }
0064
0065 *dst = 0x0;
0066 return ret;
0067 }
0068
0069 static int str(yyscan_t scanner, int token, int runtime)
0070 {
0071 YYSTYPE *yylval = expr_get_lval(scanner);
0072 char *text = expr_get_text(scanner);
0073
0074 yylval->str = normalize(strdup(text), runtime);
0075 if (!yylval->str)
0076 return EXPR_ERROR;
0077
0078 yylval->str = normalize(yylval->str, runtime);
0079 return token;
0080 }
0081
0082 static int literal(yyscan_t scanner)
0083 {
0084 YYSTYPE *yylval = expr_get_lval(scanner);
0085
0086 yylval->num = expr__get_literal(expr_get_text(scanner));
0087 if (isnan(yylval->num))
0088 return EXPR_ERROR;
0089
0090 return LITERAL;
0091 }
0092 %}
0093
0094 number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)?
0095
0096 sch [-,=]
0097 spec \\{sch}
0098 sym [0-9a-zA-Z_\.:@?]+
0099 symbol ({spec}|{sym})+
0100 literal #[0-9a-zA-Z_\.\-]+
0101
0102 %%
0103 struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
0104
0105 d_ratio { return D_RATIO; }
0106 max { return MAX; }
0107 min { return MIN; }
0108 if { return IF; }
0109 else { return ELSE; }
0110 source_count { return SOURCE_COUNT; }
0111 {literal} { return literal(yyscanner); }
0112 {number} { return value(yyscanner); }
0113 {symbol} { return str(yyscanner, ID, sctx->runtime); }
0114 "|" { return '|'; }
0115 "^" { return '^'; }
0116 "&" { return '&'; }
0117 "<" { return '<'; }
0118 ">" { return '>'; }
0119 "-" { return '-'; }
0120 "+" { return '+'; }
0121 "*" { return '*'; }
0122 "/" { return '/'; }
0123 "%" { return '%'; }
0124 "(" { return '('; }
0125 ")" { return ')'; }
0126 "," { return ','; }
0127 . { }
0128 %%
0129
0130 int expr_wrap(void *scanner __maybe_unused)
0131 {
0132 return 1;
0133 }