]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - src/lang.c
Import version 3.2.0
[FreeBSD/FreeBSD.git] / src / lang.c
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 to manipulate data structures in programs.
33  *
34  */
35
36 #include <assert.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include <lang.h>
41 #include <vm.h>
42
43 #ifndef NDEBUG
44 void bc_id_free(void *id) {
45         BC_SIG_ASSERT_LOCKED;
46         assert(id != NULL);
47         free(((BcId*) id)->name);
48 }
49 #endif // NDEBUG
50
51 void bc_string_free(void *string) {
52         BC_SIG_ASSERT_LOCKED;
53         assert(string != NULL && (*((char**) string)) != NULL);
54         if (BC_IS_BC) free(*((char**) string));
55 }
56
57 void bc_const_free(void *constant) {
58         BcConst *c = constant;
59         BC_SIG_ASSERT_LOCKED;
60         assert(c->val != NULL);
61         free(c->val);
62         bc_num_free(&c->num);
63 }
64
65 #if BC_ENABLED
66 void bc_func_insert(BcFunc *f, BcProgram *p, char *name,
67                     BcType type, size_t line)
68 {
69         BcLoc a;
70         size_t i, idx;
71
72         assert(f != NULL);
73
74         idx = bc_program_search(p, name, type == BC_TYPE_VAR);
75
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_ERR_PARSE_DUP_LOCAL, line, name, array);
81                 }
82         }
83
84         a.loc = idx;
85         a.idx = type;
86
87         bc_vec_push(&f->autos, &a);
88 }
89 #endif // BC_ENABLED
90
91 void bc_func_init(BcFunc *f, const char *name) {
92
93         BC_SIG_ASSERT_LOCKED;
94
95         assert(f != NULL && name != NULL);
96
97         bc_vec_init(&f->code, sizeof(uchar), NULL);
98
99         bc_vec_init(&f->consts, sizeof(BcConst), bc_const_free);
100
101 #if BC_ENABLED
102         if (BC_IS_BC) {
103
104                 bc_vec_init(&f->strs, sizeof(char*), bc_string_free);
105
106                 bc_vec_init(&f->autos, sizeof(BcLoc), NULL);
107                 bc_vec_init(&f->labels, sizeof(size_t), NULL);
108
109                 f->nparams = 0;
110                 f->voidfn = false;
111         }
112 #endif // BC_ENABLED
113
114         f->name = name;
115 }
116
117 void bc_func_reset(BcFunc *f) {
118
119         BC_SIG_ASSERT_LOCKED;
120         assert(f != NULL);
121
122         bc_vec_npop(&f->code, f->code.len);
123
124         bc_vec_npop(&f->consts, f->consts.len);
125
126 #if BC_ENABLED
127         if (BC_IS_BC) {
128
129                 bc_vec_npop(&f->strs, f->strs.len);
130
131                 bc_vec_npop(&f->autos, f->autos.len);
132                 bc_vec_npop(&f->labels, f->labels.len);
133
134                 f->nparams = 0;
135                 f->voidfn = false;
136         }
137 #endif // BC_ENABLED
138 }
139
140 void bc_func_free(void *func) {
141
142 #if BC_ENABLE_FUNC_FREE
143
144         BcFunc *f = (BcFunc*) func;
145
146         BC_SIG_ASSERT_LOCKED;
147         assert(f != NULL);
148
149         bc_vec_free(&f->code);
150
151         bc_vec_free(&f->consts);
152
153 #if BC_ENABLED
154 #ifndef NDEBUG
155         if (BC_IS_BC) {
156
157                 bc_vec_free(&f->strs);
158
159                 bc_vec_free(&f->autos);
160                 bc_vec_free(&f->labels);
161         }
162 #endif // NDEBUG
163 #endif // BC_ENABLED
164
165 #else // BC_ENABLE_FUNC_FREE
166         BC_UNUSED(func);
167 #endif // BC_ENABLE_FUNC_FREE
168 }
169
170 void bc_array_init(BcVec *a, bool nums) {
171         BC_SIG_ASSERT_LOCKED;
172         if (nums) bc_vec_init(a, sizeof(BcNum), bc_num_free);
173         else bc_vec_init(a, sizeof(BcVec), bc_vec_free);
174         bc_array_expand(a, 1);
175 }
176
177 void bc_array_copy(BcVec *d, const BcVec *s) {
178
179         size_t i;
180
181         BC_SIG_ASSERT_LOCKED;
182
183         assert(d != NULL && s != NULL);
184         assert(d != s && d->size == s->size && d->dtor == s->dtor);
185
186         bc_vec_npop(d, d->len);
187         bc_vec_expand(d, s->cap);
188         d->len = s->len;
189
190         for (i = 0; i < s->len; ++i) {
191                 BcNum *dnum = bc_vec_item(d, i), *snum = bc_vec_item(s, i);
192                 bc_num_createCopy(dnum, snum);
193         }
194 }
195
196 void bc_array_expand(BcVec *a, size_t len) {
197
198         assert(a != NULL);
199
200         BC_SIG_ASSERT_LOCKED;
201
202         bc_vec_expand(a, len);
203
204         if (a->size == sizeof(BcNum) && a->dtor == bc_num_free) {
205                 BcNum n;
206                 while (len > a->len) {
207                         bc_num_init(&n, BC_NUM_DEF_SIZE);
208                         bc_vec_push(a, &n);
209                 }
210         }
211         else {
212                 BcVec v;
213                 assert(a->size == sizeof(BcVec) && a->dtor == bc_vec_free);
214                 while (len > a->len) {
215                         bc_array_init(&v, true);
216                         bc_vec_push(a, &v);
217                 }
218         }
219 }
220
221 void bc_result_clear(BcResult *r) {
222         r->t = BC_RESULT_TEMP;
223         bc_num_clear(&r->d.n);
224 }
225
226 #if DC_ENABLED
227 void bc_result_copy(BcResult *d, BcResult *src) {
228
229         assert(d != NULL && src != NULL);
230
231         BC_SIG_ASSERT_LOCKED;
232
233         d->t = src->t;
234
235         switch (d->t) {
236
237                 case BC_RESULT_TEMP:
238                 case BC_RESULT_IBASE:
239                 case BC_RESULT_SCALE:
240                 case BC_RESULT_OBASE:
241 #if BC_ENABLE_EXTRA_MATH
242                 case BC_RESULT_SEED:
243 #endif // BC_ENABLE_EXTRA_MATH
244                 {
245                         bc_num_createCopy(&d->d.n, &src->d.n);
246                         break;
247                 }
248
249                 case BC_RESULT_VAR:
250 #if BC_ENABLED
251                 case BC_RESULT_ARRAY:
252 #endif // BC_ENABLED
253                 case BC_RESULT_ARRAY_ELEM:
254                 {
255                         memcpy(&d->d.loc, &src->d.loc, sizeof(BcLoc));
256                         break;
257                 }
258
259                 case BC_RESULT_STR:
260                 {
261                         memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
262                         break;
263                 }
264
265                 case BC_RESULT_ZERO:
266                 case BC_RESULT_ONE:
267                 {
268                         // Do nothing.
269                         break;
270                 }
271
272 #if BC_ENABLED
273                 case BC_RESULT_VOID:
274                 case BC_RESULT_LAST:
275                 {
276 #ifndef NDEBUG
277                         abort();
278 #endif // NDEBUG
279                 }
280 #endif // BC_ENABLED
281         }
282 }
283 #endif // DC_ENABLED
284
285 void bc_result_free(void *result) {
286
287         BcResult *r = (BcResult*) result;
288
289         BC_SIG_ASSERT_LOCKED;
290
291         assert(r != NULL);
292
293         switch (r->t) {
294
295                 case BC_RESULT_TEMP:
296                 case BC_RESULT_IBASE:
297                 case BC_RESULT_SCALE:
298                 case BC_RESULT_OBASE:
299 #if BC_ENABLE_EXTRA_MATH
300                 case BC_RESULT_SEED:
301 #endif // BC_ENABLE_EXTRA_MATH
302                 {
303                         bc_num_free(&r->d.n);
304                         break;
305                 }
306
307                 case BC_RESULT_VAR:
308 #if BC_ENABLED
309                 case BC_RESULT_ARRAY:
310 #endif // BC_ENABLED
311                 case BC_RESULT_ARRAY_ELEM:
312                 case BC_RESULT_STR:
313                 case BC_RESULT_ZERO:
314                 case BC_RESULT_ONE:
315 #if BC_ENABLED
316                 case BC_RESULT_VOID:
317                 case BC_RESULT_LAST:
318 #endif // BC_ENABLED
319                 {
320                         // Do nothing.
321                         break;
322                 }
323         }
324 }