xref: /openbmc/linux/tools/perf/util/expr.c (revision ded80bda)
1576a65b6SJiri Olsa // SPDX-License-Identifier: GPL-2.0
226226a97SJiri Olsa #include <stdbool.h>
3576a65b6SJiri Olsa #include <assert.h>
4576a65b6SJiri Olsa #include "expr.h"
526226a97SJiri Olsa #include "expr-bison.h"
626226a97SJiri Olsa #include "expr-flex.h"
7ded80bdaSIan Rogers #include <linux/kernel.h>
826226a97SJiri Olsa 
926226a97SJiri Olsa #ifdef PARSER_DEBUG
1026226a97SJiri Olsa extern int expr_debug;
1126226a97SJiri Olsa #endif
12576a65b6SJiri Olsa 
13ded80bdaSIan Rogers static size_t key_hash(const void *key, void *ctx __maybe_unused)
14576a65b6SJiri Olsa {
15ded80bdaSIan Rogers 	const char *str = (const char *)key;
16ded80bdaSIan Rogers 	size_t hash = 0;
17576a65b6SJiri Olsa 
18ded80bdaSIan Rogers 	while (*str != '\0') {
19ded80bdaSIan Rogers 		hash *= 31;
20ded80bdaSIan Rogers 		hash += *str;
21ded80bdaSIan Rogers 		str++;
22ded80bdaSIan Rogers 	}
23ded80bdaSIan Rogers 	return hash;
24ded80bdaSIan Rogers }
25ded80bdaSIan Rogers 
26ded80bdaSIan Rogers static bool key_equal(const void *key1, const void *key2,
27ded80bdaSIan Rogers 		    void *ctx __maybe_unused)
28ded80bdaSIan Rogers {
29ded80bdaSIan Rogers 	return !strcmp((const char *)key1, (const char *)key2);
30ded80bdaSIan Rogers }
31ded80bdaSIan Rogers 
32ded80bdaSIan Rogers /* Caller must make sure id is allocated */
33ded80bdaSIan Rogers int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val)
34ded80bdaSIan Rogers {
35ded80bdaSIan Rogers 	double *val_ptr = NULL, *old_val = NULL;
36ded80bdaSIan Rogers 	char *old_key = NULL;
37ded80bdaSIan Rogers 	int ret;
38ded80bdaSIan Rogers 
39ded80bdaSIan Rogers 	if (val != 0.0) {
40ded80bdaSIan Rogers 		val_ptr = malloc(sizeof(double));
41ded80bdaSIan Rogers 		if (!val_ptr)
42ded80bdaSIan Rogers 			return -ENOMEM;
43ded80bdaSIan Rogers 		*val_ptr = val;
44ded80bdaSIan Rogers 	}
45ded80bdaSIan Rogers 	ret = hashmap__set(&ctx->ids, name, val_ptr,
46ded80bdaSIan Rogers 			   (const void **)&old_key, (void **)&old_val);
47ded80bdaSIan Rogers 	free(old_key);
48ded80bdaSIan Rogers 	free(old_val);
49ded80bdaSIan Rogers 	return ret;
50ded80bdaSIan Rogers }
51ded80bdaSIan Rogers 
52ded80bdaSIan Rogers int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr)
53ded80bdaSIan Rogers {
54ded80bdaSIan Rogers 	double *data;
55ded80bdaSIan Rogers 
56ded80bdaSIan Rogers 	if (!hashmap__find(&ctx->ids, id, (void **)&data))
57ded80bdaSIan Rogers 		return -1;
58ded80bdaSIan Rogers 	*val_ptr = (data == NULL) ?  0.0 : *data;
59ded80bdaSIan Rogers 	return 0;
60576a65b6SJiri Olsa }
61576a65b6SJiri Olsa 
62aecce63eSJiri Olsa void expr__ctx_init(struct expr_parse_ctx *ctx)
63576a65b6SJiri Olsa {
64ded80bdaSIan Rogers 	hashmap__init(&ctx->ids, key_hash, key_equal, NULL);
65ded80bdaSIan Rogers }
66ded80bdaSIan Rogers 
67ded80bdaSIan Rogers void expr__ctx_clear(struct expr_parse_ctx *ctx)
68ded80bdaSIan Rogers {
69ded80bdaSIan Rogers 	struct hashmap_entry *cur;
70ded80bdaSIan Rogers 	size_t bkt;
71ded80bdaSIan Rogers 
72ded80bdaSIan Rogers 	hashmap__for_each_entry((&ctx->ids), cur, bkt) {
73ded80bdaSIan Rogers 		free((char *)cur->key);
74ded80bdaSIan Rogers 		free(cur->value);
75ded80bdaSIan Rogers 	}
76ded80bdaSIan Rogers 	hashmap__clear(&ctx->ids);
77576a65b6SJiri Olsa }
7826226a97SJiri Olsa 
7926226a97SJiri Olsa static int
80aecce63eSJiri Olsa __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
811e1a873dSKajol Jain 	      int start, int runtime)
8226226a97SJiri Olsa {
83871f9f59SJiri Olsa 	struct expr_scanner_ctx scanner_ctx = {
84871f9f59SJiri Olsa 		.start_token = start,
851e1a873dSKajol Jain 		.runtime = runtime,
86871f9f59SJiri Olsa 	};
8726226a97SJiri Olsa 	YY_BUFFER_STATE buffer;
8826226a97SJiri Olsa 	void *scanner;
8926226a97SJiri Olsa 	int ret;
9026226a97SJiri Olsa 
91871f9f59SJiri Olsa 	ret = expr_lex_init_extra(&scanner_ctx, &scanner);
9226226a97SJiri Olsa 	if (ret)
9326226a97SJiri Olsa 		return ret;
9426226a97SJiri Olsa 
9526226a97SJiri Olsa 	buffer = expr__scan_string(expr, scanner);
9626226a97SJiri Olsa 
9726226a97SJiri Olsa #ifdef PARSER_DEBUG
9826226a97SJiri Olsa 	expr_debug = 1;
99e5e0e635SIan Rogers 	expr_set_debug(1, scanner);
10026226a97SJiri Olsa #endif
10126226a97SJiri Olsa 
10226226a97SJiri Olsa 	ret = expr_parse(val, ctx, scanner);
10326226a97SJiri Olsa 
10426226a97SJiri Olsa 	expr__flush_buffer(buffer, scanner);
10526226a97SJiri Olsa 	expr__delete_buffer(buffer, scanner);
10626226a97SJiri Olsa 	expr_lex_destroy(scanner);
10726226a97SJiri Olsa 	return ret;
10826226a97SJiri Olsa }
10926226a97SJiri Olsa 
110ded80bdaSIan Rogers int expr__parse(double *final_val, struct expr_parse_ctx *ctx,
111ded80bdaSIan Rogers 		const char *expr, int runtime)
11226226a97SJiri Olsa {
1131e1a873dSKajol Jain 	return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
11426226a97SJiri Olsa }
11526226a97SJiri Olsa 
116ded80bdaSIan Rogers int expr__find_other(const char *expr, const char *one,
117ded80bdaSIan Rogers 		     struct expr_parse_ctx *ctx, int runtime)
11826226a97SJiri Olsa {
119ded80bdaSIan Rogers 	double *old_val = NULL;
120ded80bdaSIan Rogers 	char *old_key = NULL;
121ded80bdaSIan Rogers 	int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime);
12226226a97SJiri Olsa 
123ded80bdaSIan Rogers 	if (one) {
124ded80bdaSIan Rogers 		hashmap__delete(&ctx->ids, one,
125ded80bdaSIan Rogers 				(const void **)&old_key, (void **)&old_val);
126ded80bdaSIan Rogers 		free(old_key);
127ded80bdaSIan Rogers 		free(old_val);
12826226a97SJiri Olsa 	}
12926226a97SJiri Olsa 
130ded80bdaSIan Rogers 	return ret;
13126226a97SJiri Olsa }
132