8b4ce704a68d951b6c6098088584551ae30d0daa
[linux-2.6-microblaze.git] / tools / perf / util / expr.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <stdbool.h>
3 #include <assert.h>
4 #include "expr.h"
5 #include "expr-bison.h"
6 #include "expr-flex.h"
7
8 #ifdef PARSER_DEBUG
9 extern int expr_debug;
10 #endif
11
12 /* Caller must make sure id is allocated */
13 void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val)
14 {
15         int idx;
16
17         assert(ctx->num_ids < MAX_PARSE_ID);
18         idx = ctx->num_ids++;
19         ctx->ids[idx].name = name;
20         ctx->ids[idx].val = val;
21 }
22
23 void expr__ctx_init(struct expr_parse_ctx *ctx)
24 {
25         ctx->num_ids = 0;
26 }
27
28 static int
29 __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
30               int start, int runtime)
31 {
32         struct expr_scanner_ctx scanner_ctx = {
33                 .start_token = start,
34                 .runtime = runtime,
35         };
36         YY_BUFFER_STATE buffer;
37         void *scanner;
38         int ret;
39
40         ret = expr_lex_init_extra(&scanner_ctx, &scanner);
41         if (ret)
42                 return ret;
43
44         buffer = expr__scan_string(expr, scanner);
45
46 #ifdef PARSER_DEBUG
47         expr_debug = 1;
48         expr_set_debug(1, scanner);
49 #endif
50
51         ret = expr_parse(val, ctx, scanner);
52
53         expr__flush_buffer(buffer, scanner);
54         expr__delete_buffer(buffer, scanner);
55         expr_lex_destroy(scanner);
56         return ret;
57 }
58
59 int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime)
60 {
61         return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
62 }
63
64 static bool
65 already_seen(const char *val, const char *one, const char **other,
66              int num_other)
67 {
68         int i;
69
70         if (one && !strcasecmp(one, val))
71                 return true;
72         for (i = 0; i < num_other; i++)
73                 if (!strcasecmp(other[i], val))
74                         return true;
75         return false;
76 }
77
78 int expr__find_other(const char *expr, const char *one, const char ***other,
79                      int *num_other, int runtime)
80 {
81         int err, i = 0, j = 0;
82         struct expr_parse_ctx ctx;
83
84         expr__ctx_init(&ctx);
85         err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime);
86         if (err)
87                 return -1;
88
89         *other = malloc((ctx.num_ids + 1) * sizeof(char *));
90         if (!*other)
91                 return -ENOMEM;
92
93         for (i = 0, j = 0; i < ctx.num_ids; i++) {
94                 const char *str = ctx.ids[i].name;
95
96                 if (already_seen(str, one, *other, j))
97                         continue;
98
99                 str = strdup(str);
100                 if (!str)
101                         goto out;
102                 (*other)[j++] = str;
103         }
104         (*other)[j] = NULL;
105
106 out:
107         if (i != ctx.num_ids) {
108                 while (--j)
109                         free((char *) (*other)[i]);
110                 free(*other);
111                 err = -1;
112         }
113
114         *num_other = j;
115         return err;
116 }