4e5a6533dfce5b5c2ce8446d05e929ca19586bdb
[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 <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "expr.h"
8 #include "expr-bison.h"
9 #include "expr-flex.h"
10 #include <linux/kernel.h>
11
12 #ifdef PARSER_DEBUG
13 extern int expr_debug;
14 #endif
15
16 static size_t key_hash(const void *key, void *ctx __maybe_unused)
17 {
18         const char *str = (const char *)key;
19         size_t hash = 0;
20
21         while (*str != '\0') {
22                 hash *= 31;
23                 hash += *str;
24                 str++;
25         }
26         return hash;
27 }
28
29 static bool key_equal(const void *key1, const void *key2,
30                     void *ctx __maybe_unused)
31 {
32         return !strcmp((const char *)key1, (const char *)key2);
33 }
34
35 /* Caller must make sure id is allocated */
36 int expr__add_id(struct expr_parse_ctx *ctx, const char *id)
37 {
38         struct expr_id_data *data_ptr = NULL, *old_data = NULL;
39         char *old_key = NULL;
40         int ret;
41
42         data_ptr = malloc(sizeof(*data_ptr));
43         if (!data_ptr)
44                 return -ENOMEM;
45
46         ret = hashmap__set(&ctx->ids, id, data_ptr,
47                            (const void **)&old_key, (void **)&old_data);
48         if (ret)
49                 free(data_ptr);
50         free(old_key);
51         free(old_data);
52         return ret;
53 }
54
55 /* Caller must make sure id is allocated */
56 int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val)
57 {
58         struct expr_id_data *data_ptr = NULL, *old_data = NULL;
59         char *old_key = NULL;
60         int ret;
61
62         data_ptr = malloc(sizeof(*data_ptr));
63         if (!data_ptr)
64                 return -ENOMEM;
65         data_ptr->val = val;
66
67         ret = hashmap__set(&ctx->ids, id, data_ptr,
68                            (const void **)&old_key, (void **)&old_data);
69         if (ret)
70                 free(data_ptr);
71         free(old_key);
72         free(old_data);
73         return ret;
74 }
75
76 int expr__get_id(struct expr_parse_ctx *ctx, const char *id,
77                  struct expr_id_data **data)
78 {
79         return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1;
80 }
81
82 void expr__ctx_init(struct expr_parse_ctx *ctx)
83 {
84         hashmap__init(&ctx->ids, key_hash, key_equal, NULL);
85 }
86
87 void expr__ctx_clear(struct expr_parse_ctx *ctx)
88 {
89         struct hashmap_entry *cur;
90         size_t bkt;
91
92         hashmap__for_each_entry((&ctx->ids), cur, bkt) {
93                 free((char *)cur->key);
94                 free(cur->value);
95         }
96         hashmap__clear(&ctx->ids);
97 }
98
99 static int
100 __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
101               int start, int runtime)
102 {
103         struct expr_scanner_ctx scanner_ctx = {
104                 .start_token = start,
105                 .runtime = runtime,
106         };
107         YY_BUFFER_STATE buffer;
108         void *scanner;
109         int ret;
110
111         ret = expr_lex_init_extra(&scanner_ctx, &scanner);
112         if (ret)
113                 return ret;
114
115         buffer = expr__scan_string(expr, scanner);
116
117 #ifdef PARSER_DEBUG
118         expr_debug = 1;
119         expr_set_debug(1, scanner);
120 #endif
121
122         ret = expr_parse(val, ctx, scanner);
123
124         expr__flush_buffer(buffer, scanner);
125         expr__delete_buffer(buffer, scanner);
126         expr_lex_destroy(scanner);
127         return ret;
128 }
129
130 int expr__parse(double *final_val, struct expr_parse_ctx *ctx,
131                 const char *expr, int runtime)
132 {
133         return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
134 }
135
136 int expr__find_other(const char *expr, const char *one,
137                      struct expr_parse_ctx *ctx, int runtime)
138 {
139         struct expr_id_data *old_val = NULL;
140         char *old_key = NULL;
141         int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime);
142
143         if (one) {
144                 hashmap__delete(&ctx->ids, one,
145                                 (const void **)&old_key, (void **)&old_val);
146                 free(old_key);
147                 free(old_val);
148         }
149
150         return ret;
151 }