at v5.7 2.1 kB view raw
1// SPDX-License-Identifier: GPL-2.0 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/* Caller must make sure id is allocated */ 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}