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(¶mval, "%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, const struct expr_scanner_ctx *sctx) 83 { 84 YYSTYPE *yylval = expr_get_lval(scanner); 85 86 yylval->num = expr__get_literal(expr_get_text(scanner), sctx); 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, sctx); } 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