9228f60e2a2067697ec1873e105e1ab847d32c56
[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, double *val_ptr)
77 {
78         struct expr_id_data *data;
79
80         if (!hashmap__find(&ctx->ids, id, (void **)&data))
81                 return -1;
82         *val_ptr = (data == NULL) ?  0.0 : data->val;
83         return 0;
84 }
85
86 void expr__ctx_init(struct expr_parse_ctx *ctx)
87 {
88         hashmap__init(&ctx->ids, key_hash, key_equal, NULL);
89 }
90
91 void expr__ctx_clear(struct expr_parse_ctx *ctx)
92 {
93         struct hashmap_entry *cur;
94         size_t bkt;
95
96         hashmap__for_each_entry((&ctx->ids), cur, bkt) {
97                 free((char *)cur->key);
98                 free(cur->value);
99         }
100         hashmap__clear(&ctx->ids);
101 }
102
103 static int
104 __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
105               int start, int runtime)
106 {
107         struct expr_scanner_ctx scanner_ctx = {
108                 .start_token = start,
109                 .runtime = runtime,
110         };
111         YY_BUFFER_STATE buffer;
112         void *scanner;
113         int ret;
114
115         ret = expr_lex_init_extra(&scanner_ctx, &scanner);
116         if (ret)
117                 return ret;
118
119         buffer = expr__scan_string(expr, scanner);
120
121 #ifdef PARSER_DEBUG
122         expr_debug = 1;
123         expr_set_debug(1, scanner);
124 #endif
125
126         ret = expr_parse(val, ctx, scanner);
127
128         expr__flush_buffer(buffer, scanner);
129         expr__delete_buffer(buffer, scanner);
130         expr_lex_destroy(scanner);
131         return ret;
132 }
133
134 int expr__parse(double *final_val, struct expr_parse_ctx *ctx,
135                 const char *expr, int runtime)
136 {
137         return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
138 }
139
140 int expr__find_other(const char *expr, const char *one,
141                      struct expr_parse_ctx *ctx, int runtime)
142 {
143         struct expr_id_data *old_val = NULL;
144         char *old_key = NULL;
145         int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime);
146
147         if (one) {
148                 hashmap__delete(&ctx->ids, one,
149                                 (const void **)&old_key, (void **)&old_val);
150                 free(old_key);
151                 free(old_val);
152         }
153
154         return ret;
155 }