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