e8f777830a23fec127eb3bbfdbbe081aa98943c4
[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 *name, double val)
37 {
38         double *val_ptr = NULL, *old_val = NULL;
39         char *old_key = NULL;
40         int ret;
41
42         if (val != 0.0) {
43                 val_ptr = malloc(sizeof(double));
44                 if (!val_ptr)
45                         return -ENOMEM;
46                 *val_ptr = val;
47         }
48         ret = hashmap__set(&ctx->ids, name, val_ptr,
49                            (const void **)&old_key, (void **)&old_val);
50         free(old_key);
51         free(old_val);
52         return ret;
53 }
54
55 int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr)
56 {
57         double *data;
58
59         if (!hashmap__find(&ctx->ids, id, (void **)&data))
60                 return -1;
61         *val_ptr = (data == NULL) ?  0.0 : *data;
62         return 0;
63 }
64
65 void expr__ctx_init(struct expr_parse_ctx *ctx)
66 {
67         hashmap__init(&ctx->ids, key_hash, key_equal, NULL);
68 }
69
70 void expr__ctx_clear(struct expr_parse_ctx *ctx)
71 {
72         struct hashmap_entry *cur;
73         size_t bkt;
74
75         hashmap__for_each_entry((&ctx->ids), cur, bkt) {
76                 free((char *)cur->key);
77                 free(cur->value);
78         }
79         hashmap__clear(&ctx->ids);
80 }
81
82 static int
83 __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
84               int start, int runtime)
85 {
86         struct expr_scanner_ctx scanner_ctx = {
87                 .start_token = start,
88                 .runtime = runtime,
89         };
90         YY_BUFFER_STATE buffer;
91         void *scanner;
92         int ret;
93
94         ret = expr_lex_init_extra(&scanner_ctx, &scanner);
95         if (ret)
96                 return ret;
97
98         buffer = expr__scan_string(expr, scanner);
99
100 #ifdef PARSER_DEBUG
101         expr_debug = 1;
102         expr_set_debug(1, scanner);
103 #endif
104
105         ret = expr_parse(val, ctx, scanner);
106
107         expr__flush_buffer(buffer, scanner);
108         expr__delete_buffer(buffer, scanner);
109         expr_lex_destroy(scanner);
110         return ret;
111 }
112
113 int expr__parse(double *final_val, struct expr_parse_ctx *ctx,
114                 const char *expr, int runtime)
115 {
116         return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
117 }
118
119 int expr__find_other(const char *expr, const char *one,
120                      struct expr_parse_ctx *ctx, int runtime)
121 {
122         double *old_val = NULL;
123         char *old_key = NULL;
124         int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime);
125
126         if (one) {
127                 hashmap__delete(&ctx->ids, one,
128                                 (const void **)&old_key, (void **)&old_val);
129                 free(old_key);
130                 free(old_val);
131         }
132
133         return ret;
134 }