1576a65b6SJiri Olsa // SPDX-License-Identifier: GPL-2.0 226226a97SJiri Olsa #include <stdbool.h> 3576a65b6SJiri Olsa #include <assert.h> 43744ca1eSArnaldo Carvalho de Melo #include <errno.h> 53744ca1eSArnaldo Carvalho de Melo #include <stdlib.h> 63744ca1eSArnaldo Carvalho de Melo #include <string.h> 7576a65b6SJiri Olsa #include "expr.h" 826226a97SJiri Olsa #include "expr-bison.h" 926226a97SJiri Olsa #include "expr-flex.h" 10ded80bdaSIan Rogers #include <linux/kernel.h> 1126226a97SJiri Olsa 1226226a97SJiri Olsa #ifdef PARSER_DEBUG 1326226a97SJiri Olsa extern int expr_debug; 1426226a97SJiri Olsa #endif 15576a65b6SJiri Olsa 16ded80bdaSIan Rogers static size_t key_hash(const void *key, void *ctx __maybe_unused) 17576a65b6SJiri Olsa { 18ded80bdaSIan Rogers const char *str = (const char *)key; 19ded80bdaSIan Rogers size_t hash = 0; 20576a65b6SJiri Olsa 21ded80bdaSIan Rogers while (*str != '\0') { 22ded80bdaSIan Rogers hash *= 31; 23ded80bdaSIan Rogers hash += *str; 24ded80bdaSIan Rogers str++; 25ded80bdaSIan Rogers } 26ded80bdaSIan Rogers return hash; 27ded80bdaSIan Rogers } 28ded80bdaSIan Rogers 29ded80bdaSIan Rogers static bool key_equal(const void *key1, const void *key2, 30ded80bdaSIan Rogers void *ctx __maybe_unused) 31ded80bdaSIan Rogers { 32ded80bdaSIan Rogers return !strcmp((const char *)key1, (const char *)key2); 33ded80bdaSIan Rogers } 34ded80bdaSIan Rogers 35ded80bdaSIan Rogers /* Caller must make sure id is allocated */ 36332603c2SJiri Olsa int expr__add_id(struct expr_parse_ctx *ctx, const char *id) 37332603c2SJiri Olsa { 38332603c2SJiri Olsa struct expr_id_data *data_ptr = NULL, *old_data = NULL; 39332603c2SJiri Olsa char *old_key = NULL; 40332603c2SJiri Olsa int ret; 41332603c2SJiri Olsa 42332603c2SJiri Olsa data_ptr = malloc(sizeof(*data_ptr)); 43332603c2SJiri Olsa if (!data_ptr) 44332603c2SJiri Olsa return -ENOMEM; 45332603c2SJiri Olsa 46332603c2SJiri Olsa ret = hashmap__set(&ctx->ids, id, data_ptr, 47332603c2SJiri Olsa (const void **)&old_key, (void **)&old_data); 48332603c2SJiri Olsa if (ret) 49332603c2SJiri Olsa free(data_ptr); 50332603c2SJiri Olsa free(old_key); 51332603c2SJiri Olsa free(old_data); 52332603c2SJiri Olsa return ret; 53332603c2SJiri Olsa } 54332603c2SJiri Olsa 55332603c2SJiri Olsa /* Caller must make sure id is allocated */ 56070b3b5aSJiri Olsa int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) 57ded80bdaSIan Rogers { 58070b3b5aSJiri Olsa struct expr_id_data *data_ptr = NULL, *old_data = NULL; 59ded80bdaSIan Rogers char *old_key = NULL; 60ded80bdaSIan Rogers int ret; 61ded80bdaSIan Rogers 62070b3b5aSJiri Olsa data_ptr = malloc(sizeof(*data_ptr)); 63070b3b5aSJiri Olsa if (!data_ptr) 64ded80bdaSIan Rogers return -ENOMEM; 65070b3b5aSJiri Olsa data_ptr->val = val; 66332603c2SJiri Olsa 67070b3b5aSJiri Olsa ret = hashmap__set(&ctx->ids, id, data_ptr, 68070b3b5aSJiri Olsa (const void **)&old_key, (void **)&old_data); 6960e10c00SJiri Olsa if (ret) 7060e10c00SJiri Olsa free(data_ptr); 71ded80bdaSIan Rogers free(old_key); 72070b3b5aSJiri Olsa free(old_data); 73ded80bdaSIan Rogers return ret; 74ded80bdaSIan Rogers } 75ded80bdaSIan Rogers 765c5f5e83SJiri Olsa int expr__get_id(struct expr_parse_ctx *ctx, const char *id, 775c5f5e83SJiri Olsa struct expr_id_data **data) 78ded80bdaSIan Rogers { 795c5f5e83SJiri Olsa return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1; 80576a65b6SJiri Olsa } 81576a65b6SJiri Olsa 823fd29fa6SJiri Olsa void expr__del_id(struct expr_parse_ctx *ctx, const char *id) 833fd29fa6SJiri Olsa { 843fd29fa6SJiri Olsa struct expr_id_data *old_val = NULL; 853fd29fa6SJiri Olsa char *old_key = NULL; 863fd29fa6SJiri Olsa 873fd29fa6SJiri Olsa hashmap__delete(&ctx->ids, id, 883fd29fa6SJiri Olsa (const void **)&old_key, (void **)&old_val); 893fd29fa6SJiri Olsa free(old_key); 903fd29fa6SJiri Olsa free(old_val); 913fd29fa6SJiri Olsa } 923fd29fa6SJiri Olsa 93aecce63eSJiri Olsa void expr__ctx_init(struct expr_parse_ctx *ctx) 94576a65b6SJiri Olsa { 95ded80bdaSIan Rogers hashmap__init(&ctx->ids, key_hash, key_equal, NULL); 96ded80bdaSIan Rogers } 97ded80bdaSIan Rogers 98ded80bdaSIan Rogers void expr__ctx_clear(struct expr_parse_ctx *ctx) 99ded80bdaSIan Rogers { 100ded80bdaSIan Rogers struct hashmap_entry *cur; 101ded80bdaSIan Rogers size_t bkt; 102ded80bdaSIan Rogers 103ded80bdaSIan Rogers hashmap__for_each_entry((&ctx->ids), cur, bkt) { 104ded80bdaSIan Rogers free((char *)cur->key); 105ded80bdaSIan Rogers free(cur->value); 106ded80bdaSIan Rogers } 107ded80bdaSIan Rogers hashmap__clear(&ctx->ids); 108576a65b6SJiri Olsa } 10926226a97SJiri Olsa 11026226a97SJiri Olsa static int 111aecce63eSJiri Olsa __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr, 1121e1a873dSKajol Jain int start, int runtime) 11326226a97SJiri Olsa { 114871f9f59SJiri Olsa struct expr_scanner_ctx scanner_ctx = { 115871f9f59SJiri Olsa .start_token = start, 1161e1a873dSKajol Jain .runtime = runtime, 117871f9f59SJiri Olsa }; 11826226a97SJiri Olsa YY_BUFFER_STATE buffer; 11926226a97SJiri Olsa void *scanner; 12026226a97SJiri Olsa int ret; 12126226a97SJiri Olsa 122871f9f59SJiri Olsa ret = expr_lex_init_extra(&scanner_ctx, &scanner); 12326226a97SJiri Olsa if (ret) 12426226a97SJiri Olsa return ret; 12526226a97SJiri Olsa 12626226a97SJiri Olsa buffer = expr__scan_string(expr, scanner); 12726226a97SJiri Olsa 12826226a97SJiri Olsa #ifdef PARSER_DEBUG 12926226a97SJiri Olsa expr_debug = 1; 130e5e0e635SIan Rogers expr_set_debug(1, scanner); 13126226a97SJiri Olsa #endif 13226226a97SJiri Olsa 13326226a97SJiri Olsa ret = expr_parse(val, ctx, scanner); 13426226a97SJiri Olsa 13526226a97SJiri Olsa expr__flush_buffer(buffer, scanner); 13626226a97SJiri Olsa expr__delete_buffer(buffer, scanner); 13726226a97SJiri Olsa expr_lex_destroy(scanner); 13826226a97SJiri Olsa return ret; 13926226a97SJiri Olsa } 14026226a97SJiri Olsa 141ded80bdaSIan Rogers int expr__parse(double *final_val, struct expr_parse_ctx *ctx, 142ded80bdaSIan Rogers const char *expr, int runtime) 14326226a97SJiri Olsa { 1441e1a873dSKajol Jain return __expr__parse(final_val, ctx, expr, EXPR_PARSE, runtime) ? -1 : 0; 14526226a97SJiri Olsa } 14626226a97SJiri Olsa 147ded80bdaSIan Rogers int expr__find_other(const char *expr, const char *one, 148ded80bdaSIan Rogers struct expr_parse_ctx *ctx, int runtime) 14926226a97SJiri Olsa { 150ded80bdaSIan Rogers int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); 15126226a97SJiri Olsa 1523fd29fa6SJiri Olsa if (one) 1533fd29fa6SJiri Olsa expr__del_id(ctx, one); 15426226a97SJiri Olsa 155ded80bdaSIan Rogers return ret; 15626226a97SJiri Olsa } 157