1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 4*3aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 6*3aa99676SStefan Eßer * Copyright (c) 2018-2020 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> 41252884aeSStefan Eßer #include <vm.h> 42252884aeSStefan Eßer 43252884aeSStefan Eßer #ifndef NDEBUG 44252884aeSStefan Eßer void bc_id_free(void *id) { 45252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 46252884aeSStefan Eßer assert(id != NULL); 47252884aeSStefan Eßer free(((BcId*) id)->name); 48252884aeSStefan Eßer } 49252884aeSStefan Eßer #endif // NDEBUG 50252884aeSStefan Eßer 51252884aeSStefan Eßer void bc_string_free(void *string) { 52252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 53252884aeSStefan Eßer assert(string != NULL && (*((char**) string)) != NULL); 54252884aeSStefan Eßer if (BC_IS_BC) free(*((char**) string)); 55252884aeSStefan Eßer } 56252884aeSStefan Eßer 57252884aeSStefan Eßer void bc_const_free(void *constant) { 58252884aeSStefan Eßer BcConst *c = constant; 59252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 60252884aeSStefan Eßer assert(c->val != NULL); 61252884aeSStefan Eßer free(c->val); 62252884aeSStefan Eßer bc_num_free(&c->num); 63252884aeSStefan Eßer } 64252884aeSStefan Eßer 65252884aeSStefan Eßer #if BC_ENABLED 66252884aeSStefan Eßer void bc_func_insert(BcFunc *f, BcProgram *p, char *name, 67252884aeSStefan Eßer BcType type, size_t line) 68252884aeSStefan Eßer { 69252884aeSStefan Eßer BcLoc a; 70252884aeSStefan Eßer size_t i, idx; 71252884aeSStefan Eßer 72252884aeSStefan Eßer assert(f != NULL); 73252884aeSStefan Eßer 74252884aeSStefan Eßer idx = bc_program_search(p, name, type == BC_TYPE_VAR); 75252884aeSStefan Eßer 76252884aeSStefan Eßer for (i = 0; i < f->autos.len; ++i) { 77252884aeSStefan Eßer BcLoc *id = bc_vec_item(&f->autos, i); 78252884aeSStefan Eßer if (BC_ERR(idx == id->loc && type == (BcType) id->idx)) { 79252884aeSStefan Eßer const char *array = type == BC_TYPE_ARRAY ? "[]" : ""; 80252884aeSStefan Eßer bc_vm_error(BC_ERROR_PARSE_DUP_LOCAL, line, name, array); 81252884aeSStefan Eßer } 82252884aeSStefan Eßer } 83252884aeSStefan Eßer 84252884aeSStefan Eßer a.loc = idx; 85252884aeSStefan Eßer a.idx = type; 86252884aeSStefan Eßer 87252884aeSStefan Eßer bc_vec_push(&f->autos, &a); 88252884aeSStefan Eßer } 89252884aeSStefan Eßer #endif // BC_ENABLED 90252884aeSStefan Eßer 91252884aeSStefan Eßer void bc_func_init(BcFunc *f, const char *name) { 92252884aeSStefan Eßer 93252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 94252884aeSStefan Eßer 95252884aeSStefan Eßer assert(f != NULL && name != NULL); 96252884aeSStefan Eßer 97252884aeSStefan Eßer bc_vec_init(&f->code, sizeof(uchar), NULL); 98252884aeSStefan Eßer 99252884aeSStefan Eßer bc_vec_init(&f->consts, sizeof(BcConst), bc_const_free); 100*3aa99676SStefan Eßer 101252884aeSStefan Eßer #if BC_ENABLED 102252884aeSStefan Eßer if (BC_IS_BC) { 103*3aa99676SStefan Eßer 104*3aa99676SStefan Eßer bc_vec_init(&f->strs, sizeof(char*), bc_string_free); 105*3aa99676SStefan Eßer 106252884aeSStefan Eßer bc_vec_init(&f->autos, sizeof(BcLoc), NULL); 107252884aeSStefan Eßer bc_vec_init(&f->labels, sizeof(size_t), NULL); 108*3aa99676SStefan Eßer 109252884aeSStefan Eßer f->nparams = 0; 110252884aeSStefan Eßer f->voidfn = false; 111252884aeSStefan Eßer } 112252884aeSStefan Eßer #endif // BC_ENABLED 113*3aa99676SStefan Eßer 114252884aeSStefan Eßer f->name = name; 115252884aeSStefan Eßer } 116252884aeSStefan Eßer 117252884aeSStefan Eßer void bc_func_reset(BcFunc *f) { 118*3aa99676SStefan Eßer 119252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 120252884aeSStefan Eßer assert(f != NULL); 121*3aa99676SStefan Eßer 122252884aeSStefan Eßer bc_vec_npop(&f->code, f->code.len); 123*3aa99676SStefan Eßer 124252884aeSStefan Eßer bc_vec_npop(&f->consts, f->consts.len); 125*3aa99676SStefan Eßer 126252884aeSStefan Eßer #if BC_ENABLED 127252884aeSStefan Eßer if (BC_IS_BC) { 128*3aa99676SStefan Eßer 129*3aa99676SStefan Eßer bc_vec_npop(&f->strs, f->strs.len); 130*3aa99676SStefan Eßer 131252884aeSStefan Eßer bc_vec_npop(&f->autos, f->autos.len); 132252884aeSStefan Eßer bc_vec_npop(&f->labels, f->labels.len); 133*3aa99676SStefan Eßer 134252884aeSStefan Eßer f->nparams = 0; 135252884aeSStefan Eßer f->voidfn = false; 136252884aeSStefan Eßer } 137252884aeSStefan Eßer #endif // BC_ENABLED 138252884aeSStefan Eßer } 139252884aeSStefan Eßer 140252884aeSStefan Eßer void bc_func_free(void *func) { 141*3aa99676SStefan Eßer 142252884aeSStefan Eßer #if BC_ENABLE_FUNC_FREE 143252884aeSStefan Eßer 144252884aeSStefan Eßer BcFunc *f = (BcFunc*) func; 145*3aa99676SStefan Eßer 146252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 147252884aeSStefan Eßer assert(f != NULL); 148*3aa99676SStefan Eßer 149252884aeSStefan Eßer bc_vec_free(&f->code); 150*3aa99676SStefan Eßer 151252884aeSStefan Eßer bc_vec_free(&f->consts); 152*3aa99676SStefan Eßer 153252884aeSStefan Eßer #if BC_ENABLED 154252884aeSStefan Eßer #ifndef NDEBUG 155252884aeSStefan Eßer if (BC_IS_BC) { 156*3aa99676SStefan Eßer 157*3aa99676SStefan Eßer bc_vec_free(&f->strs); 158*3aa99676SStefan Eßer 159252884aeSStefan Eßer bc_vec_free(&f->autos); 160252884aeSStefan Eßer bc_vec_free(&f->labels); 161252884aeSStefan Eßer } 162252884aeSStefan Eßer #endif // NDEBUG 163252884aeSStefan Eßer #endif // BC_ENABLED 164252884aeSStefan Eßer 165252884aeSStefan Eßer #else // BC_ENABLE_FUNC_FREE 166252884aeSStefan Eßer BC_UNUSED(func); 167252884aeSStefan Eßer #endif // BC_ENABLE_FUNC_FREE 168252884aeSStefan Eßer } 169252884aeSStefan Eßer 170252884aeSStefan Eßer void bc_array_init(BcVec *a, bool nums) { 171252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 172252884aeSStefan Eßer if (nums) bc_vec_init(a, sizeof(BcNum), bc_num_free); 173252884aeSStefan Eßer else bc_vec_init(a, sizeof(BcVec), bc_vec_free); 174252884aeSStefan Eßer bc_array_expand(a, 1); 175252884aeSStefan Eßer } 176252884aeSStefan Eßer 177252884aeSStefan Eßer void bc_array_copy(BcVec *d, const BcVec *s) { 178252884aeSStefan Eßer 179252884aeSStefan Eßer size_t i; 180252884aeSStefan Eßer 181252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 182252884aeSStefan Eßer 183252884aeSStefan Eßer assert(d != NULL && s != NULL); 184252884aeSStefan Eßer assert(d != s && d->size == s->size && d->dtor == s->dtor); 185252884aeSStefan Eßer 186252884aeSStefan Eßer bc_vec_npop(d, d->len); 187252884aeSStefan Eßer bc_vec_expand(d, s->cap); 188252884aeSStefan Eßer d->len = s->len; 189252884aeSStefan Eßer 190252884aeSStefan Eßer for (i = 0; i < s->len; ++i) { 191252884aeSStefan Eßer BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i); 192252884aeSStefan Eßer bc_num_createCopy(dnum, snum); 193252884aeSStefan Eßer } 194252884aeSStefan Eßer } 195252884aeSStefan Eßer 196252884aeSStefan Eßer void bc_array_expand(BcVec *a, size_t len) { 197252884aeSStefan Eßer 198252884aeSStefan Eßer assert(a != NULL); 199252884aeSStefan Eßer 200252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 201252884aeSStefan Eßer 202252884aeSStefan Eßer bc_vec_expand(a, len); 203252884aeSStefan Eßer 204252884aeSStefan Eßer if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) { 205252884aeSStefan Eßer BcNum n; 206252884aeSStefan Eßer while (len > a->len) { 207252884aeSStefan Eßer bc_num_init(&n, BC_NUM_DEF_SIZE); 208252884aeSStefan Eßer bc_vec_push(a, &n); 209252884aeSStefan Eßer } 210252884aeSStefan Eßer } 211252884aeSStefan Eßer else { 212252884aeSStefan Eßer BcVec v; 213252884aeSStefan Eßer assert(a->size == sizeof(BcVec) && a->dtor == bc_vec_free); 214252884aeSStefan Eßer while (len > a->len) { 215252884aeSStefan Eßer bc_array_init(&v, true); 216252884aeSStefan Eßer bc_vec_push(a, &v); 217252884aeSStefan Eßer } 218252884aeSStefan Eßer } 219252884aeSStefan Eßer } 220252884aeSStefan Eßer 221252884aeSStefan Eßer void bc_result_clear(BcResult *r) { 222252884aeSStefan Eßer r->t = BC_RESULT_TEMP; 223252884aeSStefan Eßer bc_num_clear(&r->d.n); 224252884aeSStefan Eßer } 225252884aeSStefan Eßer 226252884aeSStefan Eßer #if DC_ENABLED 227252884aeSStefan Eßer void bc_result_copy(BcResult *d, BcResult *src) { 228252884aeSStefan Eßer 229252884aeSStefan Eßer assert(d != NULL && src != NULL); 230252884aeSStefan Eßer 231252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 232252884aeSStefan Eßer 233252884aeSStefan Eßer d->t = src->t; 234252884aeSStefan Eßer 235252884aeSStefan Eßer switch (d->t) { 236252884aeSStefan Eßer 237252884aeSStefan Eßer case BC_RESULT_TEMP: 238252884aeSStefan Eßer case BC_RESULT_IBASE: 239252884aeSStefan Eßer case BC_RESULT_SCALE: 240252884aeSStefan Eßer case BC_RESULT_OBASE: 241252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 242252884aeSStefan Eßer case BC_RESULT_SEED: 243252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 244252884aeSStefan Eßer { 245252884aeSStefan Eßer bc_num_createCopy(&d->d.n, &src->d.n); 246252884aeSStefan Eßer break; 247252884aeSStefan Eßer } 248252884aeSStefan Eßer 249252884aeSStefan Eßer case BC_RESULT_VAR: 250252884aeSStefan Eßer #if BC_ENABLED 251252884aeSStefan Eßer case BC_RESULT_ARRAY: 252252884aeSStefan Eßer #endif // BC_ENABLED 253252884aeSStefan Eßer case BC_RESULT_ARRAY_ELEM: 254252884aeSStefan Eßer { 255252884aeSStefan Eßer memcpy(&d->d.loc, &src->d.loc, sizeof(BcLoc)); 256252884aeSStefan Eßer break; 257252884aeSStefan Eßer } 258252884aeSStefan Eßer 259252884aeSStefan Eßer case BC_RESULT_STR: 260252884aeSStefan Eßer { 261252884aeSStefan Eßer memcpy(&d->d.n, &src->d.n, sizeof(BcNum)); 262252884aeSStefan Eßer break; 263252884aeSStefan Eßer } 264252884aeSStefan Eßer 265*3aa99676SStefan Eßer case BC_RESULT_ZERO: 266252884aeSStefan Eßer case BC_RESULT_ONE: 267252884aeSStefan Eßer { 268252884aeSStefan Eßer // Do nothing. 269252884aeSStefan Eßer break; 270252884aeSStefan Eßer } 271252884aeSStefan Eßer 272252884aeSStefan Eßer #if BC_ENABLED 273252884aeSStefan Eßer case BC_RESULT_VOID: 274252884aeSStefan Eßer case BC_RESULT_LAST: 275252884aeSStefan Eßer { 276252884aeSStefan Eßer #ifndef NDEBUG 277252884aeSStefan Eßer abort(); 278252884aeSStefan Eßer #endif // NDEBUG 279252884aeSStefan Eßer } 280252884aeSStefan Eßer #endif // BC_ENABLED 281252884aeSStefan Eßer } 282252884aeSStefan Eßer } 283252884aeSStefan Eßer #endif // DC_ENABLED 284252884aeSStefan Eßer 285252884aeSStefan Eßer void bc_result_free(void *result) { 286252884aeSStefan Eßer 287252884aeSStefan Eßer BcResult *r = (BcResult*) result; 288252884aeSStefan Eßer 289252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 290252884aeSStefan Eßer 291252884aeSStefan Eßer assert(r != NULL); 292252884aeSStefan Eßer 293252884aeSStefan Eßer switch (r->t) { 294252884aeSStefan Eßer 295252884aeSStefan Eßer case BC_RESULT_TEMP: 296252884aeSStefan Eßer case BC_RESULT_IBASE: 297252884aeSStefan Eßer case BC_RESULT_SCALE: 298252884aeSStefan Eßer case BC_RESULT_OBASE: 299252884aeSStefan Eßer #if BC_ENABLE_EXTRA_MATH 300252884aeSStefan Eßer case BC_RESULT_SEED: 301252884aeSStefan Eßer #endif // BC_ENABLE_EXTRA_MATH 302252884aeSStefan Eßer { 303252884aeSStefan Eßer bc_num_free(&r->d.n); 304252884aeSStefan Eßer break; 305252884aeSStefan Eßer } 306252884aeSStefan Eßer 307252884aeSStefan Eßer case BC_RESULT_VAR: 308252884aeSStefan Eßer #if BC_ENABLED 309252884aeSStefan Eßer case BC_RESULT_ARRAY: 310252884aeSStefan Eßer #endif // BC_ENABLED 311252884aeSStefan Eßer case BC_RESULT_ARRAY_ELEM: 312252884aeSStefan Eßer case BC_RESULT_STR: 313*3aa99676SStefan Eßer case BC_RESULT_ZERO: 314252884aeSStefan Eßer case BC_RESULT_ONE: 315252884aeSStefan Eßer #if BC_ENABLED 316252884aeSStefan Eßer case BC_RESULT_VOID: 317252884aeSStefan Eßer case BC_RESULT_LAST: 318252884aeSStefan Eßer #endif // BC_ENABLED 319252884aeSStefan Eßer { 320252884aeSStefan Eßer // Do nothing. 321252884aeSStefan Eßer break; 322252884aeSStefan Eßer } 323252884aeSStefan Eßer } 324252884aeSStefan Eßer } 325