diff options
Diffstat (limited to 'contrib/bc/src/parse.c')
-rw-r--r-- | contrib/bc/src/parse.c | 152 |
1 files changed, 91 insertions, 61 deletions
diff --git a/contrib/bc/src/parse.c b/contrib/bc/src/parse.c index ea4c25e8ba10..b02a195f83bb 100644 --- a/contrib/bc/src/parse.c +++ b/contrib/bc/src/parse.c @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2018-2021 Gavin D. Howard and contributors. + * Copyright (c) 2018-2023 Gavin D. Howard and contributors. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -44,12 +44,16 @@ #include <program.h> #include <vm.h> -void bc_parse_updateFunc(BcParse *p, size_t fidx) { +void +bc_parse_updateFunc(BcParse* p, size_t fidx) +{ p->fidx = fidx; p->func = bc_vec_item(&p->prog->fns, fidx); } -inline void bc_parse_pushName(const BcParse *p, char *name, bool var) { +inline void +bc_parse_pushName(const BcParse* p, char* name, bool var) +{ bc_parse_pushIndex(p, bc_program_search(p->prog, name, var)); } @@ -60,79 +64,95 @@ inline void bc_parse_pushName(const BcParse *p, char *name, bool var) { * @param inst The instruction to push. * @param idx The index to push. */ -static void bc_parse_update(BcParse *p, uchar inst, size_t idx) { - bc_parse_updateFunc(p, p->fidx); +static inline void +bc_parse_pushInstIdx(BcParse* p, uchar inst, size_t idx) +{ bc_parse_push(p, inst); bc_parse_pushIndex(p, idx); } -void bc_parse_addString(BcParse *p) { - +void +bc_parse_addString(BcParse* p) +{ size_t idx; - BC_SIG_LOCK; - - idx = bc_program_addString(p->prog, p->l.str.v, p->fidx); + idx = bc_program_addString(p->prog, p->l.str.v); // Push the string info. - bc_parse_update(p, BC_INST_STR, p->fidx); - bc_parse_pushIndex(p, idx); - - BC_SIG_UNLOCK; + bc_parse_pushInstIdx(p, BC_INST_STR, idx); } -static void bc_parse_addNum(BcParse *p, const char *string) { - - BcVec *consts = &p->func->consts; +static void +bc_parse_addNum(BcParse* p, const char* string) +{ + BcProgram* prog = p->prog; size_t idx; - BcConst *c; - BcVec *slabs; + + // XXX: This function has an implicit assumption: that string is a valid C + // string with a nul terminator. This is because of the unchecked array + // accesses below. I can't check this with an assert() because that could + // lead to out-of-bounds access. + // + // XXX: In fact, just for safety's sake, assume that this function needs a + // non-empty string with a nul terminator, just in case bc_parse_zero or + // bc_parse_one change in the future, which I doubt. + + BC_SIG_ASSERT_LOCKED; // Special case 0. - if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) { + if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) + { bc_parse_push(p, BC_INST_ZERO); return; } // Special case 1. - if (bc_parse_one[0] == string[0] && bc_parse_one[1] == string[1]) { + if (bc_parse_one[0] == string[0] && bc_parse_one[1] == string[1]) + { bc_parse_push(p, BC_INST_ONE); return; } - // Get the index. - idx = consts->len; - - BC_SIG_LOCK; - - // Get the right slab. - slabs = p->fidx == BC_PROG_MAIN || p->fidx == BC_PROG_READ ? - &vm.main_const_slab : &vm.other_slabs; + if (bc_map_insert(&prog->const_map, string, prog->consts.len, &idx)) + { + BcConst* c; + BcId* id = bc_vec_item(&prog->const_map, idx); - // Push an empty constant. - c = bc_vec_pushEmpty(consts); + // Get the index. + idx = id->idx; - // Set the fields. - c->val = bc_slabvec_strdup(slabs, string); - c->base = BC_NUM_BIGDIG_MAX; + // Push an empty constant. + c = bc_vec_pushEmpty(&prog->consts); - // We need this to be able to tell that the number has not been allocated. - bc_num_clear(&c->num); + // Set the fields. We reuse the string in the ID (allocated by + // bc_map_insert()), because why not? + c->val = id->name; + c->base = BC_NUM_BIGDIG_MAX; - bc_parse_update(p, BC_INST_NUM, idx); + // We need this to be able to tell that the number has not been + // allocated. + bc_num_clear(&c->num); + } + else + { + BcId* id = bc_vec_item(&prog->const_map, idx); + idx = id->idx; + } - BC_SIG_UNLOCK; + bc_parse_pushInstIdx(p, BC_INST_NUM, idx); } -void bc_parse_number(BcParse *p) { - +void +bc_parse_number(BcParse* p) +{ #if BC_ENABLE_EXTRA_MATH - char *exp = strchr(p->l.str.v, 'e'); + char* exp = strchr(p->l.str.v, 'e'); size_t idx = SIZE_MAX; // Do we have a number in scientific notation? If so, add a nul byte where // the e is. - if (exp != NULL) { + if (exp != NULL) + { idx = ((size_t) (exp - p->l.str.v)); *exp = 0; } @@ -142,8 +162,8 @@ void bc_parse_number(BcParse *p) { #if BC_ENABLE_EXTRA_MATH // If we have a number in scientific notation... - if (exp != NULL) { - + if (exp != NULL) + { bool neg; // Figure out if the exponent is negative. @@ -156,19 +176,26 @@ void bc_parse_number(BcParse *p) { #endif // BC_ENABLE_EXTRA_MATH } -void bc_parse_text(BcParse *p, const char *text, bool is_stdin) { +void +bc_parse_text(BcParse* p, const char* text, BcMode mode) +{ + BC_SIG_LOCK; // Make sure the pointer isn't invalidated. p->func = bc_vec_item(&p->prog->fns, p->fidx); - bc_lex_text(&p->l, text, is_stdin); -} + bc_lex_text(&p->l, text, mode); -void bc_parse_reset(BcParse *p) { + BC_SIG_UNLOCK; +} +void +bc_parse_reset(BcParse* p) +{ BC_SIG_ASSERT_LOCKED; // Reset the function if it isn't main and switch to main. - if (p->fidx != BC_PROG_MAIN) { + if (p->fidx != BC_PROG_MAIN) + { bc_func_reset(p->func); bc_parse_updateFunc(p, BC_PROG_MAIN); } @@ -178,8 +205,8 @@ void bc_parse_reset(BcParse *p) { p->l.t = BC_LEX_EOF; #if BC_ENABLED - if (BC_IS_BC) { - + if (BC_IS_BC) + { // Get rid of the bc parser state. p->auto_part = false; bc_vec_npop(&p->flags, p->flags.len - 1); @@ -193,18 +220,20 @@ void bc_parse_reset(BcParse *p) { bc_program_reset(p->prog); // Jump if there is an error. - if (BC_ERR(vm.status)) BC_JMP; + if (BC_ERR(vm->status)) BC_JMP; } -#ifndef NDEBUG -void bc_parse_free(BcParse *p) { - +#if BC_DEBUG +void +bc_parse_free(BcParse* p) +{ BC_SIG_ASSERT_LOCKED; assert(p != NULL); #if BC_ENABLED - if (BC_IS_BC) { + if (BC_IS_BC) + { bc_vec_free(&p->flags); bc_vec_free(&p->exits); bc_vec_free(&p->conds); @@ -215,10 +244,11 @@ void bc_parse_free(BcParse *p) { bc_lex_free(&p->l); } -#endif // NDEBUG - -void bc_parse_init(BcParse *p, BcProgram *prog, size_t func) { +#endif // BC_DEBUG +void +bc_parse_init(BcParse* p, BcProgram* prog, size_t func) +{ #if BC_ENABLED uint16_t flag = 0; #endif // BC_ENABLED @@ -228,8 +258,8 @@ void bc_parse_init(BcParse *p, BcProgram *prog, size_t func) { assert(p != NULL && prog != NULL); #if BC_ENABLED - if (BC_IS_BC) { - + if (BC_IS_BC) + { // We always want at least one flag set on the flags stack. bc_vec_init(&p->flags, sizeof(uint16_t), BC_DTOR_NONE); bc_vec_push(&p->flags, &flag); |