xref: /openbmc/linux/tools/perf/util/expr.c (revision 3fd29fa6)
1576a65b6SJiri Olsa // SPDX-License-Identifier: GPL-2.0
226226a97SJiri Olsa #include <stdbool.h>
3576a65b6SJiri Olsa #include <assert.h>
43744ca1eSArnaldo Carvalho de Melo #include <errno.h>
53744ca1eSArnaldo Carvalho de Melo #include <stdlib.h>
63744ca1eSArnaldo Carvalho de Melo #include <string.h>
7576a65b6SJiri Olsa #include "expr.h"
826226a97SJiri Olsa #include "expr-bison.h"
926226a97SJiri Olsa #include "expr-flex.h"
10ded80bdaSIan Rogers #include <linux/kernel.h>
1126226a97SJiri Olsa 
1226226a97SJiri Olsa #ifdef PARSER_DEBUG
1326226a97SJiri Olsa extern int expr_debug;
1426226a97SJiri Olsa #endif
15576a65b6SJiri Olsa 
16ded80bdaSIan Rogers static size_t key_hash(const void *key, void *ctx __maybe_unused)
17576a65b6SJiri Olsa {
18ded80bdaSIan Rogers 	const char *str = (const char *)key;
19ded80bdaSIan Rogers 	size_t hash = 0;
20576a65b6SJiri Olsa 
21ded80bdaSIan Rogers 	while (*str != '\0') {
22ded80bdaSIan Rogers 		hash *= 31;
23ded80bdaSIan Rogers 		hash += *str;
24ded80bdaSIan Rogers 		str++;
25ded80bdaSIan Rogers 	}
26ded80bdaSIan Rogers 	return hash;
27ded80bdaSIan Rogers }
28ded80bdaSIan Rogers 
29ded80bdaSIan Rogers static bool key_equal(const void *key1, const void *key2,
30ded80bdaSIan Rogers 		    void *ctx __maybe_unused)
31ded80bdaSIan Rogers {
32ded80bdaSIan Rogers 	return !strcmp((const char *)key1, (const char *)key2);
33ded80bdaSIan Rogers }
34ded80bdaSIan Rogers 
35ded80bdaSIan Rogers /* Caller must make sure id is allocated */
36332603c2SJiri Olsa int expr__add_id(struct expr_parse_ctx *ctx, const char *id)
37332603c2SJiri Olsa {
38332603c2SJiri Olsa 	struct expr_id_data *data_ptr = NULL, *old_data = NULL;
39332603c2SJiri Olsa 	char *old_key = NULL;
40332603c2SJiri Olsa 	int ret;
41332603c2SJiri Olsa 
42332603c2SJiri Olsa 	data_ptr = malloc(sizeof(*data_ptr));
43332603c2SJiri Olsa 	if (!data_ptr)
44332603c2SJiri Olsa 		return -ENOMEM;
45332603c2SJiri Olsa 
46332603c2SJiri Olsa 	ret = hashmap__set(&ctx->ids, id, data_ptr,
47332603c2SJiri Olsa 			   (const void **)&old_key, (void **)&old_data);
48332603c2SJiri Olsa 	if (ret)
49332603c2SJiri Olsa 		free(data_ptr);
50332603c2SJiri Olsa 	free(old_key);
51332603c2SJiri Olsa 	free(old_data);
52332603c2SJiri Olsa 	return ret;
53332603c2SJiri Olsa }
54332603c2SJiri Olsa 
55332603c2SJiri Olsa /* Caller must make sure id is allocated */
56070b3b5aSJiri Olsa int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val)
57ded80bdaSIan Rogers {
58070b3b5aSJiri Olsa 	struct expr_id_data *data_ptr = NULL, *old_data = NULL;
59ded80bdaSIan Rogers 	char *old_key = NULL;
60ded80bdaSIan Rogers 	int ret;
61ded80bdaSIan Rogers 
62070b3b5aSJiri Olsa 	data_ptr = malloc(sizeof(*data_ptr));
63070b3b5aSJiri Olsa 	if (!data_ptr)
64ded80bdaSIan Rogers 		return -ENOMEM;
65070b3b5aSJiri Olsa 	data_ptr->val = val;
66332603c2SJiri Olsa 
67070b3b5aSJiri Olsa 	ret = hashmap__set(&ctx->ids, id, data_ptr,
68070b3b5aSJiri Olsa 			   (const void **)&old_key, (void **)&old_data);
6960e10c00SJiri Olsa 	if (ret)
7060e10c00SJiri Olsa 		free(data_ptr);
71ded80bdaSIan Rogers 	free(old_key);
72070b3b5aSJiri Olsa 	free(old_data);
73ded80bdaSIan Rogers 	return ret;
74ded80bdaSIan Rogers }
75ded80bdaSIan Rogers 
765c5f5e83SJiri Olsa int expr__get_id(struct expr_parse_ctx *ctx, const char *id,
775c5f5e83SJiri Olsa 		 struct expr_id_data **data)
78ded80bdaSIan Rogers {
795c5f5e83SJiri Olsa 	return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1;
80576a65b6SJiri Olsa }
81576a65b6SJiri Olsa 
823fd29fa6SJiri Olsa void expr__del_id(struct expr_parse_ctx *ctx, const char *id)
833fd29fa6SJiri Olsa {
843fd29fa6SJiri Olsa 	struct expr_id_data *old_val = NULL;
853fd29fa6SJiri Olsa 	char *old_key = NULL;
863fd29fa6SJiri Olsa 
873fd29fa6SJiri Olsa 	hashmap__delete(&ctx->ids, id,
883fd29fa6SJiri Olsa 			(const void **)&old_key, (void **)&old_val);
893fd29fa6SJiri Olsa 	free(old_key);
903fd29fa6SJiri Olsa 	free(old_val);
913fd29fa6SJiri Olsa }
923fd29fa6SJiri Olsa 
93aecce63eSJiri Olsa void expr__ctx_init(struct expr_parse_ctx *ctx)
94576a65b6SJiri Olsa {
95ded80bdaSIan Rogers 	hashmap__init(&ctx->ids, key_hash, key_equal, NULL);
96ded80bdaSIan Rogers }
97ded80bdaSIan Rogers 
98ded80bdaSIan Rogers void expr__ctx_clear(struct expr_parse_ctx *ctx)
99ded80bdaSIan Rogers {
100ded80bdaSIan Rogers 	struct hashmap_entry *cur;
101ded80bdaSIan Rogers 	size_t bkt;
102ded80bdaSIan Rogers 
103ded80bdaSIan Rogers 	hashmap__for_each_entry((&ctx->ids), cur, bkt) {
104ded80bdaSIan Rogers 		free((char *)cur->key);
105ded80bdaSIan Rogers 		free(cur->value);
106ded80bdaSIan Rogers 	}
107ded80bdaSIan Rogers 	hashmap__clear(&ctx->ids);
108576a65b6SJiri Olsa }
10926226a97SJiri Olsa 
11026226a97SJiri Olsa static int
111aecce63eSJiri Olsa __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
1121e1a873dSKajol Jain 	      int start, int runtime)
11326226a97SJiri Olsa {
114871f9f59SJiri Olsa 	struct expr_scanner_ctx scanner_ctx = {
115871f9f59SJiri Olsa 		.start_token = start,
1161e1a873dSKajol Jain 		.runtime = runtime,
117871f9f59SJiri Olsa 	};
11826226a97SJiri Olsa 	YY_BUFFER_STATE buffer;
11926226a97SJiri Olsa 	void *scanner;
12026226a97SJiri Olsa 	int ret;
12126226a97SJiri Olsa 
122871f9f59SJiri Olsa 	ret = expr_lex_init_extra(&scanner_ctx, &scanner);
12326226a97SJiri Olsa 	if (ret)
12426226a97SJiri Olsa 		return ret;
12526226a97SJiri Olsa 
12626226a97SJiri Olsa 	buffer = expr__scan_string(expr, scanner);
12726226a97SJiri Olsa 
12826226a97SJiri Olsa #ifdef PARSER_DEBUG
12926226a97SJiri Olsa 	expr_debug = 1;
130e5e0e635SIan Rogers 	expr_set_debug(1, scanner);
13126226a97SJiri Olsa #endif
13226226a97SJiri Olsa 
13326226a97SJiri Olsa 	ret = expr_parse(val, ctx, scanner);
13426226a97SJiri Olsa 
13526226a97SJiri Olsa 	expr__flush_buffer(buffer, scanner);
13626226a97SJiri Olsa 	expr__delete_buffer(buffer, scanner);
13726226a97SJiri Olsa 	expr_lex_destroy(scanner);
13826226a97SJiri Olsa 	return ret;
13926226a97SJiri Olsa }
14026226a97SJiri Olsa 
141ded80bdaSIan Rogers int expr__parse(double *final_val, struct expr_parse_ctx *ctx,
142ded80bdaSIan Rogers 		const char *expr, int runtime)
14326226a97SJiri Olsa {
1441e1a873dSKajol Jain 	return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
14526226a97SJiri Olsa }
14626226a97SJiri Olsa 
147ded80bdaSIan Rogers int expr__find_other(const char *expr, const char *one,
148ded80bdaSIan Rogers 		     struct expr_parse_ctx *ctx, int runtime)
14926226a97SJiri Olsa {
150ded80bdaSIan Rogers 	int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime);
15126226a97SJiri Olsa 
1523fd29fa6SJiri Olsa 	if (one)
1533fd29fa6SJiri Olsa 		expr__del_id(ctx, one);
15426226a97SJiri Olsa 
155ded80bdaSIan Rogers 	return ret;
15626226a97SJiri Olsa }
157