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