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 10 extern int expr_debug; 11 #endif 12 13 /* Caller must make sure id is allocated */ 14 void 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 24 void expr__ctx_init(struct parse_ctx *ctx) 25 { 26 ctx->num_ids = 0; 27 } 28 29 static 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 55 int 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 60 static bool 61 already_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 74 int 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 102 out: 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