1 /* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2018-2020 Gavin D. Howard and contributors. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * ***************************************************************************** 31 * 32 * Code common to the parsers. 33 * 34 */ 35 36 #include <assert.h> 37 #include <stddef.h> 38 #include <stdlib.h> 39 #include <string.h> 40 41 #include <limits.h> 42 43 #include <parse.h> 44 #include <program.h> 45 #include <vm.h> 46 47 void bc_parse_updateFunc(BcParse *p, size_t fidx) { 48 p->fidx = fidx; 49 p->func = bc_vec_item(&p->prog->fns, fidx); 50 } 51 52 inline void bc_parse_pushName(const BcParse *p, char *name, bool var) { 53 bc_parse_pushIndex(p, bc_program_search(p->prog, name, var)); 54 } 55 56 static void bc_parse_update(BcParse *p, uchar inst, size_t idx) { 57 bc_parse_updateFunc(p, p->fidx); 58 bc_parse_push(p, inst); 59 bc_parse_pushIndex(p, idx); 60 } 61 62 void bc_parse_addString(BcParse *p) { 63 64 BcVec *strs = BC_IS_BC ? &p->func->strs : p->prog->strs; 65 size_t idx; 66 67 BC_SIG_LOCK; 68 69 if (BC_IS_BC) { 70 const char *str = bc_vm_strdup(p->l.str.v); 71 idx = strs->len; 72 bc_vec_push(strs, &str); 73 } 74 #if DC_ENABLED 75 else idx = bc_program_insertFunc(p->prog, p->l.str.v) - BC_PROG_REQ_FUNCS; 76 #endif // DC_ENABLED 77 78 bc_parse_update(p, BC_INST_STR, idx); 79 80 BC_SIG_UNLOCK; 81 } 82 83 static void bc_parse_addNum(BcParse *p, const char *string) { 84 85 BcVec *consts = &p->func->consts; 86 size_t idx; 87 BcConst c; 88 89 if (bc_parse_zero[0] == string[0] && bc_parse_zero[1] == string[1]) { 90 bc_parse_push(p, BC_INST_ZERO); 91 return; 92 } 93 if (bc_parse_one[0] == string[0] && bc_parse_one[1] == string[1]) { 94 bc_parse_push(p, BC_INST_ONE); 95 return; 96 } 97 98 idx = consts->len; 99 100 BC_SIG_LOCK; 101 102 c.val = bc_vm_strdup(string); 103 c.base = BC_NUM_BIGDIG_MAX; 104 105 bc_num_clear(&c.num); 106 bc_vec_push(consts, &c); 107 108 bc_parse_update(p, BC_INST_NUM, idx); 109 110 BC_SIG_UNLOCK; 111 } 112 113 void bc_parse_number(BcParse *p) { 114 115 #if BC_ENABLE_EXTRA_MATH 116 char *exp = strchr(p->l.str.v, 'e'); 117 size_t idx = SIZE_MAX; 118 119 if (exp != NULL) { 120 idx = ((size_t) (exp - p->l.str.v)); 121 *exp = 0; 122 } 123 #endif // BC_ENABLE_EXTRA_MATH 124 125 bc_parse_addNum(p, p->l.str.v); 126 127 #if BC_ENABLE_EXTRA_MATH 128 if (exp != NULL) { 129 130 bool neg; 131 132 neg = (*((char*) bc_vec_item(&p->l.str, idx + 1)) == BC_LEX_NEG_CHAR); 133 134 bc_parse_addNum(p, bc_vec_item(&p->l.str, idx + 1 + neg)); 135 bc_parse_push(p, BC_INST_LSHIFT + neg); 136 } 137 #endif // BC_ENABLE_EXTRA_MATH 138 } 139 140 void bc_parse_text(BcParse *p, const char *text) { 141 // Make sure the pointer isn't invalidated. 142 p->func = bc_vec_item(&p->prog->fns, p->fidx); 143 bc_lex_text(&p->l, text); 144 } 145 146 void bc_parse_reset(BcParse *p) { 147 148 BC_SIG_ASSERT_LOCKED; 149 150 if (p->fidx != BC_PROG_MAIN) { 151 bc_func_reset(p->func); 152 bc_parse_updateFunc(p, BC_PROG_MAIN); 153 } 154 155 p->l.i = p->l.len; 156 p->l.t = BC_LEX_EOF; 157 p->auto_part = false; 158 159 #if BC_ENABLED 160 if (BC_IS_BC) { 161 bc_vec_npop(&p->flags, p->flags.len - 1); 162 bc_vec_npop(&p->exits, p->exits.len); 163 bc_vec_npop(&p->conds, p->conds.len); 164 bc_vec_npop(&p->ops, p->ops.len); 165 } 166 #endif // BC_ENABLED 167 168 bc_program_reset(p->prog); 169 170 if (BC_ERR(vm.status)) BC_VM_JMP; 171 } 172 173 void bc_parse_free(BcParse *p) { 174 175 BC_SIG_ASSERT_LOCKED; 176 177 assert(p != NULL); 178 179 #if BC_ENABLED 180 if (BC_IS_BC) { 181 bc_vec_free(&p->flags); 182 bc_vec_free(&p->exits); 183 bc_vec_free(&p->conds); 184 bc_vec_free(&p->ops); 185 bc_vec_free(&p->buf); 186 } 187 #endif // BC_ENABLED 188 189 bc_lex_free(&p->l); 190 } 191 192 void bc_parse_init(BcParse *p, BcProgram *prog, size_t func) { 193 194 #if BC_ENABLED 195 uint16_t flag = 0; 196 #endif // BC_ENABLED 197 198 BC_SIG_ASSERT_LOCKED; 199 200 assert(p != NULL && prog != NULL); 201 202 #if BC_ENABLED 203 if (BC_IS_BC) { 204 bc_vec_init(&p->flags, sizeof(uint16_t), NULL); 205 bc_vec_push(&p->flags, &flag); 206 bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); 207 bc_vec_init(&p->conds, sizeof(size_t), NULL); 208 bc_vec_init(&p->ops, sizeof(BcLexType), NULL); 209 bc_vec_init(&p->buf, sizeof(char), NULL); 210 } 211 #endif // BC_ENABLED 212 213 bc_lex_init(&p->l); 214 215 p->prog = prog; 216 p->auto_part = false; 217 bc_parse_updateFunc(p, func); 218 } 219