]> git.ipfire.org Git - thirdparty/linux.git/blob - tools/perf/util/expr.c
Merge tag 'x86-fpu-2020-06-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
[thirdparty/linux.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 #endif
49
50 ret = expr_parse(val, ctx, scanner);
51
52 expr__flush_buffer(buffer, scanner);
53 expr__delete_buffer(buffer, scanner);
54 expr_lex_destroy(scanner);
55 return ret;
56 }
57
58 int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime)
59 {
60 return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
61 }
62
63 static bool
64 already_seen(const char *val, const char *one, const char **other,
65 int num_other)
66 {
67 int i;
68
69 if (one && !strcasecmp(one, val))
70 return true;
71 for (i = 0; i < num_other; i++)
72 if (!strcasecmp(other[i], val))
73 return true;
74 return false;
75 }
76
77 int expr__find_other(const char *expr, const char *one, const char ***other,
78 int *num_other, int runtime)
79 {
80 int err, i = 0, j = 0;
81 struct expr_parse_ctx ctx;
82
83 expr__ctx_init(&ctx);
84 err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime);
85 if (err)
86 return -1;
87
88 *other = malloc((ctx.num_ids + 1) * sizeof(char *));
89 if (!*other)
90 return -ENOMEM;
91
92 for (i = 0, j = 0; i < ctx.num_ids; i++) {
93 const char *str = ctx.ids[i].name;
94
95 if (already_seen(str, one, *other, j))
96 continue;
97
98 str = strdup(str);
99 if (!str)
100 goto out;
101 (*other)[j++] = str;
102 }
103 (*other)[j] = NULL;
104
105 out:
106 if (i != ctx.num_ids) {
107 while (--j)
108 free((char *) (*other)[i]);
109 free(*other);
110 err = -1;
111 }
112
113 *num_other = j;
114 return err;
115 }