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 11char *expr_get_text(yyscan_t yyscanner); 12YYSTYPE *expr_get_lval(yyscan_t yyscanner); 13 14static 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 27static 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 */ 39static 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 if (!*str) 48 break; 49 } 50 else if (*str == '?') { 51 char *paramval; 52 int i = 0; 53 int size = asprintf(¶mval, "%d", runtime); 54 55 if (size < 0) 56 *dst++ = '0'; 57 else { 58 while (i < size) 59 *dst++ = paramval[i++]; 60 free(paramval); 61 } 62 } 63 else 64 *dst++ = *str; 65 str++; 66 } 67 68 *dst = 0x0; 69 return ret; 70} 71 72static int str(yyscan_t scanner, int token, int runtime) 73{ 74 YYSTYPE *yylval = expr_get_lval(scanner); 75 char *text = expr_get_text(scanner); 76 77 yylval->str = normalize(strdup(text), runtime); 78 if (!yylval->str) 79 return EXPR_ERROR; 80 81 yylval->str = normalize(yylval->str, runtime); 82 return token; 83} 84 85static int literal(yyscan_t scanner, const struct expr_scanner_ctx *sctx) 86{ 87 YYSTYPE *yylval = expr_get_lval(scanner); 88 89 yylval->num = expr__get_literal(expr_get_text(scanner), sctx); 90 if (isnan(yylval->num)) { 91 if (!sctx->is_test) 92 return EXPR_ERROR; 93 yylval->num = 1; 94 } 95 return LITERAL; 96} 97 98static int nan_value(yyscan_t scanner) 99{ 100 YYSTYPE *yylval = expr_get_lval(scanner); 101 102 yylval->num = NAN; 103 return NUMBER; 104} 105%} 106 107number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)? 108 109sch [-,=] 110spec \\{sch} 111sym [0-9a-zA-Z_\.:@?]+ 112symbol ({spec}|{sym})+ 113literal #[0-9a-zA-Z_\.\-]+ 114 115%% 116 struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); 117 118d_ratio { return D_RATIO; } 119max { return MAX; } 120min { return MIN; } 121if { return IF; } 122else { return ELSE; } 123source_count { return SOURCE_COUNT; } 124has_event { return HAS_EVENT; } 125strcmp_cpuid_str { return STRCMP_CPUID_STR; } 126NaN { return nan_value(yyscanner); } 127{literal} { return literal(yyscanner, sctx); } 128{number} { return value(yyscanner); } 129{symbol} { return str(yyscanner, ID, sctx->runtime); } 130"|" { return '|'; } 131"^" { return '^'; } 132"&" { return '&'; } 133"<" { return '<'; } 134">" { return '>'; } 135"-" { return '-'; } 136"+" { return '+'; } 137"*" { return '*'; } 138"/" { return '/'; } 139"%" { return '%'; } 140"(" { return '('; } 141")" { return ')'; } 142"," { return ','; } 143. { } 144%% 145 146int expr_wrap(void *scanner __maybe_unused) 147{ 148 return 1; 149} 150