1
2#include <stdbool.h>
3#include <assert.h>
4#include "expr.h"
5#include "expr-bison.h"
6#define YY_EXTRA_TYPE int
7#include "expr-flex.h"
8
9#ifdef PARSER_DEBUG
10extern int expr_debug;
11#endif
12
13
14void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
15{
16 int idx;
17
18 assert(ctx->num_ids < MAX_PARSE_ID);
19 idx = ctx->num_ids++;
20 ctx->ids[idx].name = name;
21 ctx->ids[idx].val = val;
22}
23
24void expr__ctx_init(struct parse_ctx *ctx)
25{
26 ctx->num_ids = 0;
27}
28
29static int
30__expr__parse(double *val, struct parse_ctx *ctx, const char *expr,
31 int start)
32{
33 YY_BUFFER_STATE buffer;
34 void *scanner;
35 int ret;
36
37 ret = expr_lex_init_extra(start, &scanner);
38 if (ret)
39 return ret;
40
41 buffer = expr__scan_string(expr, scanner);
42
43#ifdef PARSER_DEBUG
44 expr_debug = 1;
45#endif
46
47 ret = expr_parse(val, ctx, scanner);
48
49 expr__flush_buffer(buffer, scanner);
50 expr__delete_buffer(buffer, scanner);
51 expr_lex_destroy(scanner);
52 return ret;
53}
54
55int expr__parse(double *final_val, struct parse_ctx *ctx, const char *expr)
56{
57 return __expr__parse(final_val, ctx, expr, EXPR_PARSE) ? -1 : 0;
58}
59
60static bool
61already_seen(const char *val, const char *one, const char **other,
62 int num_other)
63{
64 int i;
65
66 if (one && !strcasecmp(one, val))
67 return true;
68 for (i = 0; i < num_other; i++)
69 if (!strcasecmp(other[i], val))
70 return true;
71 return false;
72}
73
74int expr__find_other(const char *expr, const char *one, const char ***other,
75 int *num_other)
76{
77 int err, i = 0, j = 0;
78 struct parse_ctx ctx;
79
80 expr__ctx_init(&ctx);
81 err = __expr__parse(NULL, &ctx, expr, EXPR_OTHER);
82 if (err)
83 return -1;
84
85 *other = malloc((ctx.num_ids + 1) * sizeof(char *));
86 if (!*other)
87 return -ENOMEM;
88
89 for (i = 0, j = 0; i < ctx.num_ids; i++) {
90 const char *str = ctx.ids[i].name;
91
92 if (already_seen(str, one, *other, j))
93 continue;
94
95 str = strdup(str);
96 if (!str)
97 goto out;
98 (*other)[j++] = str;
99 }
100 (*other)[j] = NULL;
101
102out:
103 if (i != ctx.num_ids) {
104 while (--j)
105 free((char *) (*other)[i]);
106 free(*other);
107 err = -1;
108 }
109
110 *num_other = j;
111 return err;
112}
113