expr.l 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. %option prefix="expr_"
  2. %option reentrant
  3. %option bison-bridge
  4. %{
  5. #include <linux/compiler.h>
  6. #include "expr.h"
  7. #include "expr-bison.h"
  8. #include <math.h>
  9. char *expr_get_text(yyscan_t yyscanner);
  10. YYSTYPE *expr_get_lval(yyscan_t yyscanner);
  11. static double __value(YYSTYPE *yylval, char *str, int token)
  12. {
  13. double num;
  14. errno = 0;
  15. num = strtod(str, NULL);
  16. if (errno)
  17. return EXPR_ERROR;
  18. yylval->num = num;
  19. return token;
  20. }
  21. static int value(yyscan_t scanner)
  22. {
  23. YYSTYPE *yylval = expr_get_lval(scanner);
  24. char *text = expr_get_text(scanner);
  25. return __value(yylval, text, NUMBER);
  26. }
  27. /*
  28. * Allow @ instead of / to be able to specify pmu/event/ without
  29. * conflicts with normal division.
  30. */
  31. static char *normalize(char *str, int runtime)
  32. {
  33. char *ret = str;
  34. char *dst = str;
  35. while (*str) {
  36. if (*str == '\\') {
  37. *dst++ = *++str;
  38. if (!*str)
  39. break;
  40. }
  41. else if (*str == '?') {
  42. char *paramval;
  43. int i = 0;
  44. int size = asprintf(&paramval, "%d", runtime);
  45. if (size < 0)
  46. *dst++ = '0';
  47. else {
  48. while (i < size)
  49. *dst++ = paramval[i++];
  50. free(paramval);
  51. }
  52. }
  53. else
  54. *dst++ = *str;
  55. str++;
  56. }
  57. *dst = 0x0;
  58. return ret;
  59. }
  60. static int str(yyscan_t scanner, int token, int runtime)
  61. {
  62. YYSTYPE *yylval = expr_get_lval(scanner);
  63. char *text = expr_get_text(scanner);
  64. yylval->str = normalize(strdup(text), runtime);
  65. if (!yylval->str)
  66. return EXPR_ERROR;
  67. yylval->str = normalize(yylval->str, runtime);
  68. return token;
  69. }
  70. static int literal(yyscan_t scanner, const struct expr_scanner_ctx *sctx)
  71. {
  72. YYSTYPE *yylval = expr_get_lval(scanner);
  73. yylval->num = expr__get_literal(expr_get_text(scanner), sctx);
  74. if (isnan(yylval->num)) {
  75. if (!sctx->is_test)
  76. return EXPR_ERROR;
  77. yylval->num = 1;
  78. }
  79. return LITERAL;
  80. }
  81. static int nan_value(yyscan_t scanner)
  82. {
  83. YYSTYPE *yylval = expr_get_lval(scanner);
  84. yylval->num = NAN;
  85. return NUMBER;
  86. }
  87. %}
  88. number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)?
  89. sch [-,=]
  90. spec \\{sch}
  91. sym [0-9a-zA-Z_\.:@?]+
  92. symbol ({spec}|{sym})+
  93. literal #[0-9a-zA-Z_\.\-]+
  94. %%
  95. struct expr_scanner_ctx *sctx = expr_get_extra(yyscanner);
  96. d_ratio { return D_RATIO; }
  97. max { return MAX; }
  98. min { return MIN; }
  99. if { return IF; }
  100. else { return ELSE; }
  101. source_count { return SOURCE_COUNT; }
  102. has_event { return HAS_EVENT; }
  103. strcmp_cpuid_str { return STRCMP_CPUID_STR; }
  104. NaN { return nan_value(yyscanner); }
  105. {literal} { return literal(yyscanner, sctx); }
  106. {number} { return value(yyscanner); }
  107. {symbol} { return str(yyscanner, ID, sctx->runtime); }
  108. "|" { return '|'; }
  109. "^" { return '^'; }
  110. "&" { return '&'; }
  111. "<" { return '<'; }
  112. ">" { return '>'; }
  113. "-" { return '-'; }
  114. "+" { return '+'; }
  115. "*" { return '*'; }
  116. "/" { return '/'; }
  117. "%" { return '%'; }
  118. "(" { return '('; }
  119. ")" { return ')'; }
  120. "," { return ','; }
  121. . { }
  122. %%
  123. int expr_wrap(void *scanner __maybe_unused)
  124. {
  125. return 1;
  126. }