1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 610328f8bSStefan Eßer * Copyright (c) 2018-2021 Gavin D. Howard and contributors. 7252884aeSStefan Eßer * 8252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 9252884aeSStefan Eßer * modification, are permitted provided that the following conditions are met: 10252884aeSStefan Eßer * 11252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 12252884aeSStefan Eßer * list of conditions and the following disclaimer. 13252884aeSStefan Eßer * 14252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 15252884aeSStefan Eßer * this list of conditions and the following disclaimer in the documentation 16252884aeSStefan Eßer * and/or other materials provided with the distribution. 17252884aeSStefan Eßer * 18252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19252884aeSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20252884aeSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21252884aeSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22252884aeSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23252884aeSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24252884aeSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25252884aeSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26252884aeSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27252884aeSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28252884aeSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 29252884aeSStefan Eßer * 30252884aeSStefan Eßer * ***************************************************************************** 31252884aeSStefan Eßer * 32252884aeSStefan Eßer * Code to manipulate data structures in programs. 33252884aeSStefan Eßer * 34252884aeSStefan Eßer */ 35252884aeSStefan Eßer 36252884aeSStefan Eßer #include <assert.h> 37252884aeSStefan Eßer #include <stdlib.h> 38252884aeSStefan Eßer #include <string.h> 39252884aeSStefan Eßer 40252884aeSStefan Eßer #include <lang.h> 41*44d4804dSStefan Eßer #include <program.h> 42252884aeSStefan Eßer #include <vm.h> 43252884aeSStefan Eßer 44252884aeSStefan Eßer void bc_const_free(void *constant) { 45*44d4804dSStefan Eßer 46252884aeSStefan Eßer BcConst *c = constant; 47*44d4804dSStefan Eßer 48252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 49*44d4804dSStefan Eßer 50252884aeSStefan Eßer assert(c->val != NULL); 51*44d4804dSStefan Eßer 52252884aeSStefan Eßer bc_num_free(&c->num); 53252884aeSStefan Eßer } 54252884aeSStefan Eßer 55252884aeSStefan Eßer #if BC_ENABLED 56252884aeSStefan Eßer void bc_func_insert(BcFunc *f, BcProgram *p, char *name, 57252884aeSStefan Eßer BcType type, size_t line) 58252884aeSStefan Eßer { 59*44d4804dSStefan Eßer BcAuto a; 60252884aeSStefan Eßer size_t i, idx; 61252884aeSStefan Eßer 62*44d4804dSStefan Eßer // The function must *always* be valid. 63252884aeSStefan Eßer assert(f != NULL); 64252884aeSStefan Eßer 65*44d4804dSStefan Eßer // Get the index of the variable. 66252884aeSStefan Eßer idx = bc_program_search(p, name, type == BC_TYPE_VAR); 67252884aeSStefan Eßer 68*44d4804dSStefan Eßer // Search through all of the other autos/parameters. 69252884aeSStefan Eßer for (i = 0; i < f->autos.len; ++i) { 70*44d4804dSStefan Eßer 71*44d4804dSStefan Eßer // Get the auto. 72*44d4804dSStefan Eßer BcAuto *aptr = bc_vec_item(&f->autos, i); 73*44d4804dSStefan Eßer 74*44d4804dSStefan Eßer // If they match, barf. 75*44d4804dSStefan Eßer if (BC_ERR(idx == aptr->idx && type == aptr->type)) { 76*44d4804dSStefan Eßer 77252884aeSStefan Eßer const char *array = type == BC_TYPE_ARRAY ? "[]" : ""; 78*44d4804dSStefan Eßer 79*44d4804dSStefan Eßer bc_error(BC_ERR_PARSE_DUP_LOCAL, line, name, array); 80252884aeSStefan Eßer } 81252884aeSStefan Eßer } 82252884aeSStefan Eßer 83*44d4804dSStefan Eßer // Set the auto. 84*44d4804dSStefan Eßer a.idx = idx; 85*44d4804dSStefan Eßer a.type = type; 86252884aeSStefan Eßer 87*44d4804dSStefan Eßer // Push it. 88252884aeSStefan Eßer bc_vec_push(&f->autos, &a); 89252884aeSStefan Eßer } 90252884aeSStefan Eßer #endif // BC_ENABLED 91252884aeSStefan Eßer 92252884aeSStefan Eßer void bc_func_init(BcFunc *f, const char *name) { 93252884aeSStefan Eßer 94252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 95252884aeSStefan Eßer 96252884aeSStefan Eßer assert(f != NULL && name != NULL); 97252884aeSStefan Eßer 98*44d4804dSStefan Eßer bc_vec_init(&f->code, sizeof(uchar), BC_DTOR_NONE); 99252884aeSStefan Eßer 100*44d4804dSStefan Eßer bc_vec_init(&f->consts, sizeof(BcConst), BC_DTOR_CONST); 101*44d4804dSStefan Eßer 102*44d4804dSStefan Eßer bc_vec_init(&f->strs, sizeof(char*), BC_DTOR_NONE); 1033aa99676SStefan Eßer 104252884aeSStefan Eßer #if BC_ENABLED 105*44d4804dSStefan Eßer 106*44d4804dSStefan Eßer // Only bc needs these things. 107252884aeSStefan Eßer if (BC_IS_BC) { 1083aa99676SStefan Eßer 109*44d4804dSStefan Eßer bc_vec_init(&f->autos, sizeof(BcAuto), BC_DTOR_NONE); 110*44d4804dSStefan Eßer bc_vec_init(&f->labels, sizeof(size_t), BC_DTOR_NONE); 1113aa99676SStefan Eßer 112252884aeSStefan Eßer f->nparams = 0; 113252884aeSStefan Eßer f->voidfn = false; 114252884aeSStefan Eßer } 115*44d4804dSStefan Eßer 116252884aeSStefan Eßer #endif // BC_ENABLED 1173aa99676SStefan Eßer 118252884aeSStefan Eßer f->name = name; 119252884aeSStefan Eßer } 120252884aeSStefan Eßer 121252884aeSStefan Eßer void bc_func_reset(BcFunc *f) { 1223aa99676SStefan Eßer 123252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 124252884aeSStefan Eßer assert(f != NULL); 1253aa99676SStefan Eßer 12610328f8bSStefan Eßer bc_vec_popAll(&f->code); 1273aa99676SStefan Eßer 12810328f8bSStefan Eßer bc_vec_popAll(&f->consts); 1293aa99676SStefan Eßer 130*44d4804dSStefan Eßer bc_vec_popAll(&f->strs); 131*44d4804dSStefan Eßer 132252884aeSStefan Eßer #if BC_ENABLED 133252884aeSStefan Eßer if (BC_IS_BC) { 1343aa99676SStefan Eßer 13510328f8bSStefan Eßer bc_vec_popAll(&f->autos); 13610328f8bSStefan Eßer bc_vec_popAll(&f->labels); 1373aa99676SStefan Eßer 138252884aeSStefan Eßer f->nparams = 0; 139252884aeSStefan Eßer f->voidfn = false; 140252884aeSStefan Eßer } 141252884aeSStefan Eßer #endif // BC_ENABLED 142252884aeSStefan Eßer } 143252884aeSStefan Eßer 144*44d4804dSStefan Eßer #ifndef NDEBUG 145252884aeSStefan Eßer void bc_func_free(void *func) { 1463aa99676SStefan Eßer 147252884aeSStefan Eßer BcFunc *f = (BcFunc*) func; 1483aa99676SStefan Eßer 149252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 150252884aeSStefan Eßer assert(f != NULL); 1513aa99676SStefan Eßer 152252884aeSStefan Eßer bc_vec_free(&f->code); 1533aa99676SStefan Eßer 154252884aeSStefan Eßer bc_vec_free(&f->consts); 1553aa99676SStefan Eßer 1563aa99676SStefan Eßer bc_vec_free(&f->strs); 1573aa99676SStefan Eßer 158*44d4804dSStefan Eßer #if BC_ENABLED 159*44d4804dSStefan Eßer if (BC_IS_BC) { 160*44d4804dSStefan Eßer 161252884aeSStefan Eßer bc_vec_free(&f->autos); 162252884aeSStefan Eßer bc_vec_free(&f->labels); 163252884aeSStefan Eßer } 164252884aeSStefan Eßer #endif // BC_ENABLED 165252884aeSStefan Eßer } 166*44d4804dSStefan Eßer #endif // NDEBUG 167252884aeSStefan Eßer 168252884aeSStefan Eßer void bc_array_init(BcVec *a, bool nums) { 169*44d4804dSStefan Eßer 170252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 171*44d4804dSStefan Eßer 172*44d4804dSStefan Eßer // Set the proper vector. 173*44d4804dSStefan Eßer if (nums) bc_vec_init(a, sizeof(BcNum), BC_DTOR_NUM); 174*44d4804dSStefan Eßer else bc_vec_init(a, sizeof(BcVec), BC_DTOR_VEC); 175*44d4804dSStefan Eßer 176*44d4804dSStefan Eßer // We always want at least one item in the array. 177252884aeSStefan Eßer bc_array_expand(a, 1); 178252884aeSStefan Eßer } 179252884aeSStefan Eßer 180252884aeSStefan Eßer void bc_array_copy(BcVec *d, const BcVec *s) { 181252884aeSStefan Eßer 182252884aeSStefan Eßer size_t i; 183252884aeSStefan Eßer 184252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 185252884aeSStefan Eßer 186252884aeSStefan Eßer assert(d != NULL && s != NULL); 187252884aeSStefan Eßer assert(d != s && d->size == s->size && d->dtor == s->dtor); 188252884aeSStefan Eßer 189*44d4804dSStefan Eßer // Make sure to destroy everything currently in d. This will put a lot of 190*44d4804dSStefan Eßer // temps on the reuse list, so allocating later is not going to be as 191*44d4804dSStefan Eßer // expensive as it seems. Also, it makes it easier to copy numbers that are 192*44d4804dSStefan Eßer // strings. 19310328f8bSStefan Eßer bc_vec_popAll(d); 194*44d4804dSStefan Eßer 195*44d4804dSStefan Eßer // Preexpand. 196252884aeSStefan Eßer bc_vec_expand(d, s->cap); 197252884aeSStefan Eßer d->len = s->len; 198252884aeSStefan Eßer 199252884aeSStefan Eßer for (i = 0; i < s->len; ++i) { 200*44d4804dSStefan Eßer 201*44d4804dSStefan Eßer BcNum *dnum, *snum; 202*44d4804dSStefan Eßer 203*44d4804dSStefan Eßer dnum = bc_vec_item(d, i); 204*44d4804dSStefan Eßer snum = bc_vec_item(s, i); 205*44d4804dSStefan Eßer 206*44d4804dSStefan Eßer // We have to create a copy of the number as well. 207*44d4804dSStefan Eßer if (BC_PROG_STR(snum)) memcpy(dnum, snum, sizeof(BcNum)); 208*44d4804dSStefan Eßer else bc_num_createCopy(dnum, snum); 209252884aeSStefan Eßer } 210252884aeSStefan Eßer } 211252884aeSStefan Eßer 212252884aeSStefan Eßer void bc_array_expand(BcVec *a, size_t len) { 213252884aeSStefan Eßer 214252884aeSStefan Eßer assert(a != NULL); 215252884aeSStefan Eßer 216252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 217252884aeSStefan Eßer 218252884aeSStefan Eßer bc_vec_expand(a, len); 219252884aeSStefan Eßer 220*44d4804dSStefan Eßer // If this is true, then we have a num array. 221*44d4804dSStefan Eßer if (a->size == sizeof(BcNum) && a->dtor == BC_DTOR_NUM) { 222*44d4804dSStefan Eßer 223*44d4804dSStefan Eßer // Initialize numbers until we reach the target. 224252884aeSStefan Eßer while (len > a->len) { 225*44d4804dSStefan Eßer BcNum *n = bc_vec_pushEmpty(a); 226*44d4804dSStefan Eßer bc_num_init(n, BC_NUM_DEF_SIZE); 227252884aeSStefan Eßer } 228252884aeSStefan Eßer } 229252884aeSStefan Eßer else { 230*44d4804dSStefan Eßer 231*44d4804dSStefan Eßer assert(a->size == sizeof(BcVec) && a->dtor == BC_DTOR_VEC); 232*44d4804dSStefan Eßer 233*44d4804dSStefan Eßer // Recursively initialize arrays until we reach the target. Having the 234*44d4804dSStefan Eßer // second argument of bc_array_init() be true will activate the base 235*44d4804dSStefan Eßer // case, so we're safe. 236252884aeSStefan Eßer while (len > a->len) { 237*44d4804dSStefan Eßer BcVec *v = bc_vec_pushEmpty(a); 238*44d4804dSStefan Eßer bc_array_init(v, true); 239252884aeSStefan Eßer } 240252884aeSStefan Eßer } 241252884aeSStefan Eßer } 242252884aeSStefan Eßer 243252884aeSStefan Eßer void bc_result_clear(BcResult *r) { 244252884aeSStefan Eßer r->t = BC_RESULT_TEMP; 245252884aeSStefan Eßer bc_num_clear(&r->d.n); 246252884aeSStefan Eßer } 247252884aeSStefan Eßer 248252884aeSStefan Eßer #if DC_ENABLED 249252884aeSStefan Eßer void bc_result_copy(BcResult *d, BcResult *src) { 250252884aeSStefan Eßer 251252884aeSStefan Eßer assert(d != NULL && src != NULL); 252252884aeSStefan Eßer 253252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 254252884aeSStefan Eßer 255*44d4804dSStefan Eßer // d is assumed to not be valid yet. 256252884aeSStefan Eßer d->t = src->t; 257252884aeSStefan Eßer 258*44d4804dSStefan Eßer // Yes, it depends on what type. 259252884aeSStefan Eßer switch (d->t) { 260252884aeSStefan Eßer 261252884aeSStefan Eßer case BC_RESULT_TEMP: 262252884aeSStefan Eßer case BC_RESULT_IBASE: 263252884aeSStefan Eßer case BC_RESULT_SCALE: 264252884aeSStefan Eßer case BC_RESULT_OBASE: 265252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 266252884aeSStefan Eßer case BC_RESULT_SEED: 267252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 268252884aeSStefan Eßer { 269252884aeSStefan Eßer bc_num_createCopy(&d->d.n, &src->d.n); 270252884aeSStefan Eßer break; 271252884aeSStefan Eßer } 272252884aeSStefan Eßer 273252884aeSStefan Eßer case BC_RESULT_VAR: 274252884aeSStefan Eßer case BC_RESULT_ARRAY: 275252884aeSStefan Eßer case BC_RESULT_ARRAY_ELEM: 276252884aeSStefan Eßer { 277252884aeSStefan Eßer memcpy(&d->d.loc, &src->d.loc, sizeof(BcLoc)); 278252884aeSStefan Eßer break; 279252884aeSStefan Eßer } 280252884aeSStefan Eßer 281252884aeSStefan Eßer case BC_RESULT_STR: 282252884aeSStefan Eßer { 283252884aeSStefan Eßer memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); 284252884aeSStefan Eßer break; 285252884aeSStefan Eßer } 286252884aeSStefan Eßer 2873aa99676SStefan Eßer case BC_RESULT_ZERO: 288252884aeSStefan Eßer case BC_RESULT_ONE: 289252884aeSStefan Eßer { 290252884aeSStefan Eßer // Do nothing. 291252884aeSStefan Eßer break; 292252884aeSStefan Eßer } 293252884aeSStefan Eßer 294252884aeSStefan Eßer #if BC_ENABLED 295252884aeSStefan Eßer case BC_RESULT_VOID: 296252884aeSStefan Eßer case BC_RESULT_LAST: 297252884aeSStefan Eßer { 298252884aeSStefan Eßer #ifndef NDEBUG 299*44d4804dSStefan Eßer // We should *never* try copying either of these. 300252884aeSStefan Eßer abort(); 301252884aeSStefan Eßer #endif // NDEBUG 302252884aeSStefan Eßer } 303252884aeSStefan Eßer #endif // BC_ENABLED 304252884aeSStefan Eßer } 305252884aeSStefan Eßer } 306252884aeSStefan Eßer #endif // DC_ENABLED 307252884aeSStefan Eßer 308252884aeSStefan Eßer void bc_result_free(void *result) { 309252884aeSStefan Eßer 310252884aeSStefan Eßer BcResult *r = (BcResult*) result; 311252884aeSStefan Eßer 312252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 313252884aeSStefan Eßer 314252884aeSStefan Eßer assert(r != NULL); 315252884aeSStefan Eßer 316252884aeSStefan Eßer switch (r->t) { 317252884aeSStefan Eßer 318252884aeSStefan Eßer case BC_RESULT_TEMP: 319252884aeSStefan Eßer case BC_RESULT_IBASE: 320252884aeSStefan Eßer case BC_RESULT_SCALE: 321252884aeSStefan Eßer case BC_RESULT_OBASE: 322252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 323252884aeSStefan Eßer case BC_RESULT_SEED: 324252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 325252884aeSStefan Eßer { 326252884aeSStefan Eßer bc_num_free(&r->d.n); 327252884aeSStefan Eßer break; 328252884aeSStefan Eßer } 329252884aeSStefan Eßer 330252884aeSStefan Eßer case BC_RESULT_VAR: 331252884aeSStefan Eßer case BC_RESULT_ARRAY: 332252884aeSStefan Eßer case BC_RESULT_ARRAY_ELEM: 333252884aeSStefan Eßer case BC_RESULT_STR: 3343aa99676SStefan Eßer case BC_RESULT_ZERO: 335252884aeSStefan Eßer case BC_RESULT_ONE: 336252884aeSStefan Eßer #if BC_ENABLED 337252884aeSStefan Eßer case BC_RESULT_VOID: 338252884aeSStefan Eßer case BC_RESULT_LAST: 339252884aeSStefan Eßer #endif // BC_ENABLED 340252884aeSStefan Eßer { 341252884aeSStefan Eßer // Do nothing. 342252884aeSStefan Eßer break; 343252884aeSStefan Eßer } 344252884aeSStefan Eßer } 345252884aeSStefan Eßer } 346