2 * *****************************************************************************
4 * Copyright (c) 2018-2020 Gavin D. Howard and contributors.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
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.
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.
30 * *****************************************************************************
32 * Code to manipulate data structures in programs.
44 void bc_id_free(void *id) {
47 free(((BcId*) id)->name);
51 void bc_string_free(void *string) {
53 assert(string != NULL && (*((char**) string)) != NULL);
54 if (BC_IS_BC) free(*((char**) string));
57 void bc_const_free(void *constant) {
58 BcConst *c = constant;
60 assert(c->val != NULL);
66 void bc_func_insert(BcFunc *f, BcProgram *p, char *name,
67 BcType type, size_t line)
74 idx = bc_program_search(p, name, type == BC_TYPE_VAR);
76 for (i = 0; i < f->autos.len; ++i) {
77 BcLoc *id = bc_vec_item(&f->autos, i);
78 if (BC_ERR(idx == id->loc && type == (BcType) id->idx)) {
79 const char *array = type == BC_TYPE_ARRAY ? "[]" : "";
80 bc_vm_error(BC_ERROR_PARSE_DUP_LOCAL, line, name, array);
87 bc_vec_push(&f->autos, &a);
91 void bc_func_init(BcFunc *f, const char *name) {
95 assert(f != NULL && name != NULL);
97 bc_vec_init(&f->code, sizeof(uchar), NULL);
99 // This is necessary for not allocating memory where it isn't used.
100 // dc does not use strings except in the main function. The else part
101 // is necessary to stop uninitiazed data errors in valgrind.
102 if (BC_IS_BC || !strcmp(name, bc_func_main))
103 bc_vec_init(&f->strs, sizeof(char*), bc_string_free);
104 #if BC_ENABLE_FUNC_FREE
105 else bc_vec_clear(&f->strs);
106 #endif // BC_ENABLE_FUNC_FREE
108 bc_vec_init(&f->consts, sizeof(BcConst), bc_const_free);
111 bc_vec_init(&f->autos, sizeof(BcLoc), NULL);
112 bc_vec_init(&f->labels, sizeof(size_t), NULL);
120 void bc_func_reset(BcFunc *f) {
121 BC_SIG_ASSERT_LOCKED;
123 bc_vec_npop(&f->code, f->code.len);
124 bc_vec_npop(&f->strs, f->strs.len);
125 bc_vec_npop(&f->consts, f->consts.len);
128 bc_vec_npop(&f->autos, f->autos.len);
129 bc_vec_npop(&f->labels, f->labels.len);
136 void bc_func_free(void *func) {
137 #if BC_ENABLE_FUNC_FREE
139 BcFunc *f = (BcFunc*) func;
140 BC_SIG_ASSERT_LOCKED;
142 bc_vec_free(&f->code);
143 bc_vec_free(&f->strs);
144 bc_vec_free(&f->consts);
148 bc_vec_free(&f->autos);
149 bc_vec_free(&f->labels);
154 #else // BC_ENABLE_FUNC_FREE
156 #endif // BC_ENABLE_FUNC_FREE
159 void bc_array_init(BcVec *a, bool nums) {
160 BC_SIG_ASSERT_LOCKED;
161 if (nums) bc_vec_init(a, sizeof(BcNum), bc_num_free);
162 else bc_vec_init(a, sizeof(BcVec), bc_vec_free);
163 bc_array_expand(a, 1);
166 void bc_array_copy(BcVec *d, const BcVec *s) {
170 BC_SIG_ASSERT_LOCKED;
172 assert(d != NULL && s != NULL);
173 assert(d != s && d->size == s->size && d->dtor == s->dtor);
175 bc_vec_npop(d, d->len);
176 bc_vec_expand(d, s->cap);
179 for (i = 0; i < s->len; ++i) {
180 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
181 bc_num_createCopy(dnum, snum);
185 void bc_array_expand(BcVec *a, size_t len) {
189 BC_SIG_ASSERT_LOCKED;
191 bc_vec_expand(a, len);
193 if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) {
195 while (len > a->len) {
196 bc_num_init(&n, BC_NUM_DEF_SIZE);
202 assert(a->size == sizeof(BcVec) && a->dtor == bc_vec_free);
203 while (len > a->len) {
204 bc_array_init(&v, true);
210 void bc_result_clear(BcResult *r) {
211 r->t = BC_RESULT_TEMP;
212 bc_num_clear(&r->d.n);
216 void bc_result_copy(BcResult *d, BcResult *src) {
218 assert(d != NULL && src != NULL);
220 BC_SIG_ASSERT_LOCKED;
227 case BC_RESULT_IBASE:
228 case BC_RESULT_SCALE:
229 case BC_RESULT_OBASE:
230 #if BC_ENABLE_EXTRA_MATH
232 #endif // BC_ENABLE_EXTRA_MATH
234 bc_num_createCopy(&d->d.n, &src->d.n);
240 case BC_RESULT_ARRAY:
242 case BC_RESULT_ARRAY_ELEM:
244 memcpy(&d->d.loc, &src->d.loc, sizeof(BcLoc));
248 case BC_RESULT_CONSTANT:
251 memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
274 void bc_result_free(void *result) {
276 BcResult *r = (BcResult*) result;
278 BC_SIG_ASSERT_LOCKED;
285 case BC_RESULT_IBASE:
286 case BC_RESULT_SCALE:
287 case BC_RESULT_OBASE:
288 #if BC_ENABLE_EXTRA_MATH
290 #endif // BC_ENABLE_EXTRA_MATH
292 bc_num_free(&r->d.n);
298 case BC_RESULT_ARRAY:
300 case BC_RESULT_ARRAY_ELEM:
302 case BC_RESULT_CONSTANT: