1576a65b6SJiri Olsa // SPDX-License-Identifier: GPL-2.0 226226a97SJiri Olsa #include <stdbool.h> 3576a65b6SJiri Olsa #include <assert.h> 4576a65b6SJiri Olsa #include "expr.h" 526226a97SJiri Olsa #include "expr-bison.h" 626226a97SJiri Olsa #include "expr-flex.h" 7ded80bdaSIan Rogers #include <linux/kernel.h> 826226a97SJiri Olsa 926226a97SJiri Olsa #ifdef PARSER_DEBUG 1026226a97SJiri Olsa extern int expr_debug; 1126226a97SJiri Olsa #endif 12576a65b6SJiri Olsa 13ded80bdaSIan Rogers static size_t key_hash(const void *key, void *ctx __maybe_unused) 14576a65b6SJiri Olsa { 15ded80bdaSIan Rogers const char *str = (const char *)key; 16ded80bdaSIan Rogers size_t hash = 0; 17576a65b6SJiri Olsa 18ded80bdaSIan Rogers while (*str != '\0') { 19ded80bdaSIan Rogers hash *= 31; 20ded80bdaSIan Rogers hash += *str; 21ded80bdaSIan Rogers str++; 22ded80bdaSIan Rogers } 23ded80bdaSIan Rogers return hash; 24ded80bdaSIan Rogers } 25ded80bdaSIan Rogers 26ded80bdaSIan Rogers static bool key_equal(const void *key1, const void *key2, 27ded80bdaSIan Rogers void *ctx __maybe_unused) 28ded80bdaSIan Rogers { 29ded80bdaSIan Rogers return !strcmp((const char *)key1, (const char *)key2); 30ded80bdaSIan Rogers } 31ded80bdaSIan Rogers 32ded80bdaSIan Rogers /* Caller must make sure id is allocated */ 33ded80bdaSIan Rogers int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) 34ded80bdaSIan Rogers { 35ded80bdaSIan Rogers double *val_ptr = NULL, *old_val = NULL; 36ded80bdaSIan Rogers char *old_key = NULL; 37ded80bdaSIan Rogers int ret; 38ded80bdaSIan Rogers 39ded80bdaSIan Rogers if (val != 0.0) { 40ded80bdaSIan Rogers val_ptr = malloc(sizeof(double)); 41ded80bdaSIan Rogers if (!val_ptr) 42ded80bdaSIan Rogers return -ENOMEM; 43ded80bdaSIan Rogers *val_ptr = val; 44ded80bdaSIan Rogers } 45ded80bdaSIan Rogers ret = hashmap__set(&ctx->ids, name, val_ptr, 46ded80bdaSIan Rogers (const void **)&old_key, (void **)&old_val); 47ded80bdaSIan Rogers free(old_key); 48ded80bdaSIan Rogers free(old_val); 49ded80bdaSIan Rogers return ret; 50ded80bdaSIan Rogers } 51ded80bdaSIan Rogers 52ded80bdaSIan Rogers int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) 53ded80bdaSIan Rogers { 54ded80bdaSIan Rogers double *data; 55ded80bdaSIan Rogers 56ded80bdaSIan Rogers if (!hashmap__find(&ctx->ids, id, (void **)&data)) 57ded80bdaSIan Rogers return -1; 58ded80bdaSIan Rogers *val_ptr = (data == NULL) ? 0.0 : *data; 59ded80bdaSIan Rogers return 0; 60576a65b6SJiri Olsa } 61576a65b6SJiri Olsa 62aecce63eSJiri Olsa void expr__ctx_init(struct expr_parse_ctx *ctx) 63576a65b6SJiri Olsa { 64ded80bdaSIan Rogers hashmap__init(&ctx->ids, key_hash, key_equal, NULL); 65ded80bdaSIan Rogers } 66ded80bdaSIan Rogers 67ded80bdaSIan Rogers void expr__ctx_clear(struct expr_parse_ctx *ctx) 68ded80bdaSIan Rogers { 69ded80bdaSIan Rogers struct hashmap_entry *cur; 70ded80bdaSIan Rogers size_t bkt; 71ded80bdaSIan Rogers 72ded80bdaSIan Rogers hashmap__for_each_entry((&ctx->ids), cur, bkt) { 73ded80bdaSIan Rogers free((char *)cur->key); 74ded80bdaSIan Rogers free(cur->value); 75ded80bdaSIan Rogers } 76ded80bdaSIan Rogers hashmap__clear(&ctx->ids); 77576a65b6SJiri Olsa } 7826226a97SJiri Olsa 7926226a97SJiri Olsa static int 80aecce63eSJiri Olsa __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, 811e1a873dSKajol Jain int start, int runtime) 8226226a97SJiri Olsa { 83871f9f59SJiri Olsa struct expr_scanner_ctx scanner_ctx = { 84871f9f59SJiri Olsa .start_token = start, 851e1a873dSKajol Jain .runtime = runtime, 86871f9f59SJiri Olsa }; 8726226a97SJiri Olsa YY_BUFFER_STATE buffer; 8826226a97SJiri Olsa void *scanner; 8926226a97SJiri Olsa int ret; 9026226a97SJiri Olsa 91871f9f59SJiri Olsa ret = expr_lex_init_extra(&scanner_ctx, &scanner); 9226226a97SJiri Olsa if (ret) 9326226a97SJiri Olsa return ret; 9426226a97SJiri Olsa 9526226a97SJiri Olsa buffer = expr__scan_string(expr, scanner); 9626226a97SJiri Olsa 9726226a97SJiri Olsa #ifdef PARSER_DEBUG 9826226a97SJiri Olsa expr_debug = 1; 99e5e0e635SIan Rogers expr_set_debug(1, scanner); 10026226a97SJiri Olsa #endif 10126226a97SJiri Olsa 10226226a97SJiri Olsa ret = expr_parse(val, ctx, scanner); 10326226a97SJiri Olsa 10426226a97SJiri Olsa expr__flush_buffer(buffer, scanner); 10526226a97SJiri Olsa expr__delete_buffer(buffer, scanner); 10626226a97SJiri Olsa expr_lex_destroy(scanner); 10726226a97SJiri Olsa return ret; 10826226a97SJiri Olsa } 10926226a97SJiri Olsa 110ded80bdaSIan Rogers int expr__parse(double *final_val, struct expr_parse_ctx *ctx, 111ded80bdaSIan Rogers const char *expr, int runtime) 11226226a97SJiri Olsa { 1131e1a873dSKajol Jain return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0; 11426226a97SJiri Olsa } 11526226a97SJiri Olsa 116ded80bdaSIan Rogers int expr__find_other(const char *expr, const char *one, 117ded80bdaSIan Rogers struct expr_parse_ctx *ctx, int runtime) 11826226a97SJiri Olsa { 119ded80bdaSIan Rogers double *old_val = NULL; 120ded80bdaSIan Rogers char *old_key = NULL; 121ded80bdaSIan Rogers int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); 12226226a97SJiri Olsa 123ded80bdaSIan Rogers if (one) { 124ded80bdaSIan Rogers hashmap__delete(&ctx->ids, one, 125ded80bdaSIan Rogers (const void **)&old_key, (void **)&old_val); 126ded80bdaSIan Rogers free(old_key); 127ded80bdaSIan Rogers free(old_val); 12826226a97SJiri Olsa } 12926226a97SJiri Olsa 130ded80bdaSIan Rogers return ret; 13126226a97SJiri Olsa } 132