162306a36Sopenharmony_ci%option prefix="expr_" 262306a36Sopenharmony_ci%option reentrant 362306a36Sopenharmony_ci%option bison-bridge 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci%{ 662306a36Sopenharmony_ci#include <linux/compiler.h> 762306a36Sopenharmony_ci#include "expr.h" 862306a36Sopenharmony_ci#include "expr-bison.h" 962306a36Sopenharmony_ci#include <math.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cichar *expr_get_text(yyscan_t yyscanner); 1262306a36Sopenharmony_ciYYSTYPE *expr_get_lval(yyscan_t yyscanner); 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_cistatic double __value(YYSTYPE *yylval, char *str, int token) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci double num; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci errno = 0; 1962306a36Sopenharmony_ci num = strtod(str, NULL); 2062306a36Sopenharmony_ci if (errno) 2162306a36Sopenharmony_ci return EXPR_ERROR; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci yylval->num = num; 2462306a36Sopenharmony_ci return token; 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic int value(yyscan_t scanner) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci YYSTYPE *yylval = expr_get_lval(scanner); 3062306a36Sopenharmony_ci char *text = expr_get_text(scanner); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci return __value(yylval, text, NUMBER); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Allow @ instead of / to be able to specify pmu/event/ without 3762306a36Sopenharmony_ci * conflicts with normal division. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_cistatic char *normalize(char *str, int runtime) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci char *ret = str; 4262306a36Sopenharmony_ci char *dst = str; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci while (*str) { 4562306a36Sopenharmony_ci if (*str == '\\') { 4662306a36Sopenharmony_ci *dst++ = *++str; 4762306a36Sopenharmony_ci if (!*str) 4862306a36Sopenharmony_ci break; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci else if (*str == '?') { 5162306a36Sopenharmony_ci char *paramval; 5262306a36Sopenharmony_ci int i = 0; 5362306a36Sopenharmony_ci int size = asprintf(¶mval, "%d", runtime); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci if (size < 0) 5662306a36Sopenharmony_ci *dst++ = '0'; 5762306a36Sopenharmony_ci else { 5862306a36Sopenharmony_ci while (i < size) 5962306a36Sopenharmony_ci *dst++ = paramval[i++]; 6062306a36Sopenharmony_ci free(paramval); 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci else 6462306a36Sopenharmony_ci *dst++ = *str; 6562306a36Sopenharmony_ci str++; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci *dst = 0x0; 6962306a36Sopenharmony_ci return ret; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic int str(yyscan_t scanner, int token, int runtime) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci YYSTYPE *yylval = expr_get_lval(scanner); 7562306a36Sopenharmony_ci char *text = expr_get_text(scanner); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci yylval->str = normalize(strdup(text), runtime); 7862306a36Sopenharmony_ci if (!yylval->str) 7962306a36Sopenharmony_ci return EXPR_ERROR; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci yylval->str = normalize(yylval->str, runtime); 8262306a36Sopenharmony_ci return token; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int literal(yyscan_t scanner, const struct expr_scanner_ctx *sctx) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci YYSTYPE *yylval = expr_get_lval(scanner); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci yylval->num = expr__get_literal(expr_get_text(scanner), sctx); 9062306a36Sopenharmony_ci if (isnan(yylval->num)) { 9162306a36Sopenharmony_ci if (!sctx->is_test) 9262306a36Sopenharmony_ci return EXPR_ERROR; 9362306a36Sopenharmony_ci yylval->num = 1; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci return LITERAL; 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci%} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cinumber ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)? 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cisch [-,=] 10262306a36Sopenharmony_cispec \\{sch} 10362306a36Sopenharmony_cisym [0-9a-zA-Z_\.:@?]+ 10462306a36Sopenharmony_cisymbol ({spec}|{sym})+ 10562306a36Sopenharmony_ciliteral #[0-9a-zA-Z_\.\-]+ 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci%% 10862306a36Sopenharmony_ci struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cid_ratio { return D_RATIO; } 11162306a36Sopenharmony_cimax { return MAX; } 11262306a36Sopenharmony_cimin { return MIN; } 11362306a36Sopenharmony_ciif { return IF; } 11462306a36Sopenharmony_cielse { return ELSE; } 11562306a36Sopenharmony_cisource_count { return SOURCE_COUNT; } 11662306a36Sopenharmony_cihas_event { return HAS_EVENT; } 11762306a36Sopenharmony_cistrcmp_cpuid_str { return STRCMP_CPUID_STR; } 11862306a36Sopenharmony_ci{literal} { return literal(yyscanner, sctx); } 11962306a36Sopenharmony_ci{number} { return value(yyscanner); } 12062306a36Sopenharmony_ci{symbol} { return str(yyscanner, ID, sctx->runtime); } 12162306a36Sopenharmony_ci"|" { return '|'; } 12262306a36Sopenharmony_ci"^" { return '^'; } 12362306a36Sopenharmony_ci"&" { return '&'; } 12462306a36Sopenharmony_ci"<" { return '<'; } 12562306a36Sopenharmony_ci">" { return '>'; } 12662306a36Sopenharmony_ci"-" { return '-'; } 12762306a36Sopenharmony_ci"+" { return '+'; } 12862306a36Sopenharmony_ci"*" { return '*'; } 12962306a36Sopenharmony_ci"/" { return '/'; } 13062306a36Sopenharmony_ci"%" { return '%'; } 13162306a36Sopenharmony_ci"(" { return '('; } 13262306a36Sopenharmony_ci")" { return ')'; } 13362306a36Sopenharmony_ci"," { return ','; } 13462306a36Sopenharmony_ci. { } 13562306a36Sopenharmony_ci%% 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ciint expr_wrap(void *scanner __maybe_unused) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci return 1; 14062306a36Sopenharmony_ci} 141