perf metric: Change expr__get_id to return struct expr_id_data
[linux-2.6-microblaze.git] / tools / perf / util / expr.y
index cd17486..0d4f5d3 100644 (file)
 #include "smt.h"
 #include <string.h>
 
+static double d_ratio(double val0, double val1)
+{
+       if (val1 == 0) {
+               return 0;
+       }
+       return  val0 / val1;
+}
+
 %}
 
 %define api.pure full
 %token EXPR_PARSE EXPR_OTHER EXPR_ERROR
 %token <num> NUMBER
 %token <str> ID
-%token MIN MAX IF ELSE SMT_ON
+%destructor { free ($$); } <str>
+%token MIN MAX IF ELSE SMT_ON D_RATIO
 %left MIN MAX IF
 %left '|'
 %left '^'
 %left '&'
+%left '<' '>'
 %left '-' '+'
 %left '*' '/' '%'
 %left NEG NOT
@@ -46,19 +56,6 @@ static void expr_error(double *final_val __maybe_unused,
        pr_debug("%s\n", s);
 }
 
-static int lookup_id(struct expr_parse_ctx *ctx, char *id, double *val)
-{
-       int i;
-
-       for (i = 0; i < ctx->num_ids; i++) {
-               if (!strcasecmp(ctx->ids[i].name, id)) {
-                       *val = ctx->ids[i].val;
-                       return 0;
-               }
-       }
-       return -1;
-}
-
 %}
 %%
 
@@ -72,16 +69,12 @@ all_other: all_other other
 
 other: ID
 {
-       if (ctx->num_ids + 1 >= EXPR_MAX_OTHER) {
-               pr_err("failed: way too many variables");
-               YYABORT;
-       }
-
-       ctx->ids[ctx->num_ids++].name = $1;
+       expr__add_id(ctx, $1);
 }
 |
-MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')'
-
+MIN | MAX | IF | ELSE | SMT_ON | NUMBER | '|' | '^' | '&' | '-' | '+' | '*' | '/' | '%' | '(' | ')' | ','
+|
+'<' | '>' | D_RATIO
 
 all_expr: if_expr                      { *final_val = $1; }
        ;
@@ -92,24 +85,43 @@ if_expr:
        ;
 
 expr:    NUMBER
-       | ID                    { if (lookup_id(ctx, $1, &$$) < 0) {
-                                       pr_debug("%s not found\n", $1);
-                                       YYABORT;
-                                 }
+       | ID                    {
+                                       struct expr_id_data *data;
+
+                                       if (expr__get_id(ctx, $1, &data) || !data) {
+                                               pr_debug("%s not found\n", $1);
+                                               free($1);
+                                               YYABORT;
+                                       }
+                                       $$ = data->val;
+                                       free($1);
                                }
        | expr '|' expr         { $$ = (long)$1 | (long)$3; }
        | expr '&' expr         { $$ = (long)$1 & (long)$3; }
        | expr '^' expr         { $$ = (long)$1 ^ (long)$3; }
+       | expr '<' expr         { $$ = $1 < $3; }
+       | expr '>' expr         { $$ = $1 > $3; }
        | expr '+' expr         { $$ = $1 + $3; }
        | expr '-' expr         { $$ = $1 - $3; }
        | expr '*' expr         { $$ = $1 * $3; }
-       | expr '/' expr         { if ($3 == 0) YYABORT; $$ = $1 / $3; }
-       | expr '%' expr         { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; }
+       | expr '/' expr         { if ($3 == 0) {
+                                       pr_debug("division by zero\n");
+                                       YYABORT;
+                                 }
+                                 $$ = $1 / $3;
+                               }
+       | expr '%' expr         { if ((long)$3 == 0) {
+                                       pr_debug("division by zero\n");
+                                       YYABORT;
+                                 }
+                                 $$ = (long)$1 % (long)$3;
+                               }
        | '-' expr %prec NEG    { $$ = -$2; }
        | '(' if_expr ')'       { $$ = $2; }
        | MIN '(' expr ',' expr ')' { $$ = $3 < $5 ? $3 : $5; }
        | MAX '(' expr ',' expr ')' { $$ = $3 > $5 ? $3 : $5; }
        | SMT_ON                 { $$ = smt_on() > 0; }
+       | D_RATIO '(' expr ',' expr ')' { $$ = d_ratio($3,$5); }
        ;
 
 %%