blob: 8b4ce704a68d951b6c6098088584551ae30d0daa [file] [log] [blame]
Jiri Olsa576a65b2020-02-28 10:36:12 +01001// SPDX-License-Identifier: GPL-2.0
Jiri Olsa26226a92020-02-28 10:36:13 +01002#include <stdbool.h>
Jiri Olsa576a65b2020-02-28 10:36:12 +01003#include <assert.h>
4#include "expr.h"
Jiri Olsa26226a92020-02-28 10:36:13 +01005#include "expr-bison.h"
Jiri Olsa26226a92020-02-28 10:36:13 +01006#include "expr-flex.h"
7
8#ifdef PARSER_DEBUG
9extern int expr_debug;
10#endif
Jiri Olsa576a65b2020-02-28 10:36:12 +010011
12/* Caller must make sure id is allocated */
Jiri Olsaaecce632020-04-02 02:03:34 +053013void expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val)
Jiri Olsa576a65b2020-02-28 10:36:12 +010014{
15 int idx;
16
17 assert(ctx->num_ids < MAX_PARSE_ID);
18 idx = ctx->num_ids++;
19 ctx->ids[idx].name = name;
20 ctx->ids[idx].val = val;
21}
22
Jiri Olsaaecce632020-04-02 02:03:34 +053023void expr__ctx_init(struct expr_parse_ctx *ctx)
Jiri Olsa576a65b2020-02-28 10:36:12 +010024{
25 ctx->num_ids = 0;
26}
Jiri Olsa26226a92020-02-28 10:36:13 +010027
28static int
Jiri Olsaaecce632020-04-02 02:03:34 +053029__expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,
Kajol Jain1e1a8732020-04-02 02:03:37 +053030 int start, int runtime)
Jiri Olsa26226a92020-02-28 10:36:13 +010031{
Jiri Olsa871f9f52020-04-02 02:03:35 +053032 struct expr_scanner_ctx scanner_ctx = {
33 .start_token = start,
Kajol Jain1e1a8732020-04-02 02:03:37 +053034 .runtime = runtime,
Jiri Olsa871f9f52020-04-02 02:03:35 +053035 };
Jiri Olsa26226a92020-02-28 10:36:13 +010036 YY_BUFFER_STATE buffer;
37 void *scanner;
38 int ret;
39
Jiri Olsa871f9f52020-04-02 02:03:35 +053040 ret = expr_lex_init_extra(&scanner_ctx, &scanner);
Jiri Olsa26226a92020-02-28 10:36:13 +010041 if (ret)
42 return ret;
43
44 buffer = expr__scan_string(expr, scanner);
45
46#ifdef PARSER_DEBUG
47 expr_debug = 1;
Ian Rogerse5e0e632020-05-01 10:33:28 -070048 expr_set_debug(1, scanner);
Jiri Olsa26226a92020-02-28 10:36:13 +010049#endif
50
51 ret = expr_parse(val, ctx, scanner);
52
53 expr__flush_buffer(buffer, scanner);
54 expr__delete_buffer(buffer, scanner);
55 expr_lex_destroy(scanner);
56 return ret;
57}
58
Kajol Jain1e1a8732020-04-02 02:03:37 +053059int expr__parse(double *final_val, struct expr_parse_ctx *ctx, const char *expr, int runtime)
Jiri Olsa26226a92020-02-28 10:36:13 +010060{
Kajol Jain1e1a8732020-04-02 02:03:37 +053061 return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0;
Jiri Olsa26226a92020-02-28 10:36:13 +010062}
63
64static bool
65already_seen(const char *val, const char *one, const char **other,
66 int num_other)
67{
68 int i;
69
70 if (one && !strcasecmp(one, val))
71 return true;
72 for (i = 0; i < num_other; i++)
73 if (!strcasecmp(other[i], val))
74 return true;
75 return false;
76}
77
Jiri Olsa0f9b1e12020-02-28 10:36:15 +010078int expr__find_other(const char *expr, const char *one, const char ***other,
Kajol Jain1e1a8732020-04-02 02:03:37 +053079 int *num_other, int runtime)
Jiri Olsa26226a92020-02-28 10:36:13 +010080{
81 int err, i = 0, j = 0;
Jiri Olsaaecce632020-04-02 02:03:34 +053082 struct expr_parse_ctx ctx;
Jiri Olsa26226a92020-02-28 10:36:13 +010083
84 expr__ctx_init(&ctx);
Kajol Jain1e1a8732020-04-02 02:03:37 +053085 err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER, runtime);
Jiri Olsa26226a92020-02-28 10:36:13 +010086 if (err)
87 return -1;
88
89 *other = malloc((ctx.num_ids + 1) * sizeof(char *));
90 if (!*other)
91 return -ENOMEM;
92
93 for (i = 0, j = 0; i < ctx.num_ids; i++) {
94 const char *str = ctx.ids[i].name;
95
96 if (already_seen(str, one, *other, j))
97 continue;
98
99 str = strdup(str);
100 if (!str)
101 goto out;
102 (*other)[j++] = str;
103 }
104 (*other)[j] = NULL;
105
106out:
107 if (i != ctx.num_ids) {
108 while (--j)
109 free((char *) (*other)[i]);
110 free(*other);
111 err = -1;
112 }
113
114 *num_other = j;
115 return err;
116}