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 #include <linux/kernel.h> 8 9 #ifdef PARSER_DEBUG 10 extern int expr_debug; 11 #endif 12 13 static size_t key_hash(const void *key, void *ctx __maybe_unused) 14 { 15 const char *str = (const char *)key; 16 size_t hash = 0; 17 18 while (*str != '\0') { 19 hash *= 31; 20 hash += *str; 21 str++; 22 } 23 return hash; 24 } 25 26 static bool key_equal(const void *key1, const void *key2, 27 void *ctx __maybe_unused) 28 { 29 return !strcmp((const char *)key1, (const char *)key2); 30 } 31 32 /* Caller must make sure id is allocated */ 33 int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) 34 { 35 double *val_ptr = NULL, *old_val = NULL; 36 char *old_key = NULL; 37 int ret; 38 39 if (val != 0.0) { 40 val_ptr = malloc(sizeof(double)); 41 if (!val_ptr) 42 return -ENOMEM; 43 *val_ptr = val; 44 } 45 ret = hashmap__set(&ctx->ids, name, val_ptr, 46 (const void **)&old_key, (void **)&old_val); 47 free(old_key); 48 free(old_val); 49 return ret; 50 } 51 52 int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) 53 { 54 double *data; 55 56 if (!hashmap__find(&ctx->ids, id, (void **)&data)) 57 return -1; 58 *val_ptr = (data == NULL) ? 0.0 : *data; 59 return 0; 60 } 61 62 void expr__ctx_init(struct expr_parse_ctx *ctx) 63 { 64 hashmap__init(&ctx->ids, key_hash, key_equal, NULL); 65 } 66 67 void expr__ctx_clear(struct expr_parse_ctx *ctx) 68 { 69 struct hashmap_entry *cur; 70 size_t bkt; 71 72 hashmap__for_each_entry((&ctx->ids), cur, bkt) { 73 free((char *)cur->key); 74 free(cur->value); 75 } 76 hashmap__clear(&ctx->ids); 77 } 78 79 static int 80 __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, 81 int start, int runtime) 82 { 83 struct expr_scanner_ctx scanner_ctx = { 84 .start_token = start, 85 .runtime = runtime, 86 }; 87 YY_BUFFER_STATE buffer; 88 void *scanner; 89 int ret; 90 91 ret = expr_lex_init_extra(&scanner_ctx, &scanner); 92 if (ret) 93 return ret; 94 95 buffer = expr__scan_string(expr, scanner); 96 97 #ifdef PARSER_DEBUG 98 expr_debug = 1; 99 expr_set_debug(1, scanner); 100 #endif 101 102 ret = expr_parse(val, ctx, scanner); 103 104 expr__flush_buffer(buffer, scanner); 105 expr__delete_buffer(buffer, scanner); 106 expr_lex_destroy(scanner); 107 return ret; 108 } 109 110 int expr__parse(double *final_val, struct expr_parse_ctx *ctx, 111 const char *expr, int runtime) 112 { 113 return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0; 114 } 115 116 int expr__find_other(const char *expr, const char *one, 117 struct expr_parse_ctx *ctx, int runtime) 118 { 119 double *old_val = NULL; 120 char *old_key = NULL; 121 int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); 122 123 if (one) { 124 hashmap__delete(&ctx->ids, one, 125 (const void **)&old_key, (void **)&old_val); 126 free(old_key); 127 free(old_val); 128 } 129 130 return ret; 131 } 132