xref: /openbmc/linux/tools/perf/util/expr.c (revision aecce63e)
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 #define YY_EXTRA_TYPE int
726226a97SJiri Olsa #include "expr-flex.h"
826226a97SJiri Olsa 
926226a97SJiri Olsa #ifdef PARSER_DEBUG
1026226a97SJiri Olsa extern int expr_debug;
1126226a97SJiri Olsa #endif
12576a65b6SJiri Olsa 
13576a65b6SJiri Olsa /* Caller must make sure id is allocated */
14aecce63eSJiri Olsa void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val)
15576a65b6SJiri Olsa {
16576a65b6SJiri Olsa 	int idx;
17576a65b6SJiri Olsa 
18576a65b6SJiri Olsa 	assert(ctx->num_ids < MAX_PARSE_ID);
19576a65b6SJiri Olsa 	idx = ctx->num_ids++;
20576a65b6SJiri Olsa 	ctx->ids[idx].name = name;
21576a65b6SJiri Olsa 	ctx->ids[idx].val = val;
22576a65b6SJiri Olsa }
23576a65b6SJiri Olsa 
24aecce63eSJiri Olsa void expr__ctx_init(struct expr_parse_ctx *ctx)
25576a65b6SJiri Olsa {
26576a65b6SJiri Olsa 	ctx->num_ids = 0;
27576a65b6SJiri Olsa }
2826226a97SJiri Olsa 
2926226a97SJiri Olsa static int
30aecce63eSJiri Olsa __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
3126226a97SJiri Olsa 	      int start)
3226226a97SJiri Olsa {
3326226a97SJiri Olsa 	YY_BUFFER_STATE buffer;
3426226a97SJiri Olsa 	void *scanner;
3526226a97SJiri Olsa 	int ret;
3626226a97SJiri Olsa 
3726226a97SJiri Olsa 	ret = expr_lex_init_extra(start, &scanner);
3826226a97SJiri Olsa 	if (ret)
3926226a97SJiri Olsa 		return ret;
4026226a97SJiri Olsa 
4126226a97SJiri Olsa 	buffer = expr__scan_string(expr, scanner);
4226226a97SJiri Olsa 
4326226a97SJiri Olsa #ifdef PARSER_DEBUG
4426226a97SJiri Olsa 	expr_debug = 1;
4526226a97SJiri Olsa #endif
4626226a97SJiri Olsa 
4726226a97SJiri Olsa 	ret = expr_parse(val, ctx, scanner);
4826226a97SJiri Olsa 
4926226a97SJiri Olsa 	expr__flush_buffer(buffer, scanner);
5026226a97SJiri Olsa 	expr__delete_buffer(buffer, scanner);
5126226a97SJiri Olsa 	expr_lex_destroy(scanner);
5226226a97SJiri Olsa 	return ret;
5326226a97SJiri Olsa }
5426226a97SJiri Olsa 
55aecce63eSJiri Olsa int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr)
5626226a97SJiri Olsa {
57d942815aSJiri Olsa 	return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0;
5826226a97SJiri Olsa }
5926226a97SJiri Olsa 
6026226a97SJiri Olsa static bool
6126226a97SJiri Olsa already_seen(const char *val, const char *one, const char **other,
6226226a97SJiri Olsa 	     int num_other)
6326226a97SJiri Olsa {
6426226a97SJiri Olsa 	int i;
6526226a97SJiri Olsa 
6626226a97SJiri Olsa 	if (one && !strcasecmp(one, val))
6726226a97SJiri Olsa 		return true;
6826226a97SJiri Olsa 	for (i = 0; i < num_other; i++)
6926226a97SJiri Olsa 		if (!strcasecmp(other[i], val))
7026226a97SJiri Olsa 			return true;
7126226a97SJiri Olsa 	return false;
7226226a97SJiri Olsa }
7326226a97SJiri Olsa 
740f9b1e12SJiri Olsa int expr__find_other(const char *expr, const char *one, const char ***other,
7526226a97SJiri Olsa 		     int *num_other)
7626226a97SJiri Olsa {
7726226a97SJiri Olsa 	int err, i = 0, j = 0;
78aecce63eSJiri Olsa 	struct expr_parse_ctx ctx;
7926226a97SJiri Olsa 
8026226a97SJiri Olsa 	expr__ctx_init(&ctx);
810f9b1e12SJiri Olsa 	err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER);
8226226a97SJiri Olsa 	if (err)
8326226a97SJiri Olsa 		return -1;
8426226a97SJiri Olsa 
8526226a97SJiri Olsa 	*other = malloc((ctx.num_ids + 1) * sizeof(char *));
8626226a97SJiri Olsa 	if (!*other)
8726226a97SJiri Olsa 		return -ENOMEM;
8826226a97SJiri Olsa 
8926226a97SJiri Olsa 	for (i = 0, j = 0; i < ctx.num_ids; i++) {
9026226a97SJiri Olsa 		const char *str = ctx.ids[i].name;
9126226a97SJiri Olsa 
9226226a97SJiri Olsa 		if (already_seen(str, one, *other, j))
9326226a97SJiri Olsa 			continue;
9426226a97SJiri Olsa 
9526226a97SJiri Olsa 		str = strdup(str);
9626226a97SJiri Olsa 		if (!str)
9726226a97SJiri Olsa 			goto out;
9826226a97SJiri Olsa 		(*other)[j++] = str;
9926226a97SJiri Olsa 	}
10026226a97SJiri Olsa 	(*other)[j] = NULL;
10126226a97SJiri Olsa 
10226226a97SJiri Olsa out:
10326226a97SJiri Olsa 	if (i != ctx.num_ids) {
10426226a97SJiri Olsa 		while (--j)
10526226a97SJiri Olsa 			free((char *) (*other)[i]);
10626226a97SJiri Olsa 		free(*other);
10726226a97SJiri Olsa 		err = -1;
10826226a97SJiri Olsa 	}
10926226a97SJiri Olsa 
11026226a97SJiri Olsa 	*num_other = j;
11126226a97SJiri Olsa 	return err;
11226226a97SJiri Olsa }
113