Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bc/src/lang.c
39534 views
1
/*
2
* *****************************************************************************
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 2018-2025 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 <program.h>
42
#include <vm.h>
43
44
void
45
bc_const_free(void* constant)
46
{
47
BcConst* c = constant;
48
49
BC_SIG_ASSERT_LOCKED;
50
51
assert(c->val != NULL);
52
53
bc_num_free(&c->num);
54
}
55
56
#if BC_ENABLED
57
void
58
bc_func_insert(BcFunc* f, BcProgram* p, char* name, BcType type, size_t line)
59
{
60
BcAuto a;
61
size_t i, idx;
62
63
// The function must *always* be valid.
64
assert(f != NULL);
65
66
// Get the index of the variable.
67
idx = bc_program_search(p, name, type == BC_TYPE_VAR);
68
69
// Search through all of the other autos/parameters.
70
for (i = 0; i < f->autos.len; ++i)
71
{
72
// Get the auto.
73
BcAuto* aptr = bc_vec_item(&f->autos, i);
74
75
// If they match, barf.
76
if (BC_ERR(idx == aptr->idx &&
77
BC_IS_ARRAY(type) == BC_IS_ARRAY(aptr->type)))
78
{
79
const char* array = BC_IS_ARRAY(type) ? "[]" : "";
80
81
bc_error(BC_ERR_PARSE_DUP_LOCAL, line, name, array);
82
}
83
}
84
85
// Set the auto.
86
a.idx = idx;
87
a.type = type;
88
89
// Push it.
90
bc_vec_push(&f->autos, &a);
91
}
92
#endif // BC_ENABLED
93
94
void
95
bc_func_init(BcFunc* f, const char* name)
96
{
97
BC_SIG_ASSERT_LOCKED;
98
99
assert(f != NULL && name != NULL);
100
101
bc_vec_init(&f->code, sizeof(uchar), BC_DTOR_NONE);
102
103
#if BC_ENABLED
104
105
// Only bc needs these things.
106
if (BC_IS_BC)
107
{
108
bc_vec_init(&f->autos, sizeof(BcAuto), BC_DTOR_NONE);
109
bc_vec_init(&f->labels, sizeof(size_t), BC_DTOR_NONE);
110
111
f->nparams = 0;
112
f->voidfn = false;
113
}
114
115
#endif // BC_ENABLED
116
117
f->name = name;
118
}
119
120
void
121
bc_func_reset(BcFunc* f)
122
{
123
BC_SIG_ASSERT_LOCKED;
124
assert(f != NULL);
125
126
bc_vec_popAll(&f->code);
127
128
#if BC_ENABLED
129
if (BC_IS_BC)
130
{
131
bc_vec_popAll(&f->autos);
132
bc_vec_popAll(&f->labels);
133
134
f->nparams = 0;
135
f->voidfn = false;
136
}
137
#endif // BC_ENABLED
138
}
139
140
#if BC_DEBUG || BC_ENABLE_MEMCHECK
141
void
142
bc_func_free(void* func)
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
#if BC_ENABLED
152
if (BC_IS_BC)
153
{
154
bc_vec_free(&f->autos);
155
bc_vec_free(&f->labels);
156
}
157
#endif // BC_ENABLED
158
}
159
#endif // BC_DEBUG || BC_ENABLE_MEMCHECK
160
161
void
162
bc_array_init(BcVec* a, bool nums)
163
{
164
BC_SIG_ASSERT_LOCKED;
165
166
// Set the proper vector.
167
if (nums) bc_vec_init(a, sizeof(BcNum), BC_DTOR_NUM);
168
else bc_vec_init(a, sizeof(BcVec), BC_DTOR_VEC);
169
170
// We always want at least one item in the array.
171
bc_array_expand(a, 1);
172
}
173
174
void
175
bc_array_copy(BcVec* d, const BcVec* s)
176
{
177
size_t i;
178
179
BC_SIG_ASSERT_LOCKED;
180
181
assert(d != NULL && s != NULL);
182
assert(d != s && d->size == s->size && d->dtor == s->dtor);
183
184
// Make sure to destroy everything currently in d. This will put a lot of
185
// temps on the reuse list, so allocating later is not going to be as
186
// expensive as it seems. Also, it makes it easier to copy numbers that are
187
// strings.
188
bc_vec_popAll(d);
189
190
// Preexpand.
191
bc_vec_expand(d, s->cap);
192
d->len = s->len;
193
194
for (i = 0; i < s->len; ++i)
195
{
196
BcNum* dnum;
197
BcNum* snum;
198
199
dnum = bc_vec_item(d, i);
200
snum = bc_vec_item(s, i);
201
202
// We have to create a copy of the number as well.
203
if (BC_PROG_STR(snum))
204
{
205
// NOLINTNEXTLINE
206
memcpy(dnum, snum, sizeof(BcNum));
207
}
208
else bc_num_createCopy(dnum, snum);
209
}
210
}
211
212
void
213
bc_array_expand(BcVec* a, size_t len)
214
{
215
assert(a != NULL);
216
217
BC_SIG_ASSERT_LOCKED;
218
219
bc_vec_expand(a, len);
220
221
// If this is true, then we have a num array.
222
if (a->size == sizeof(BcNum) && a->dtor == BC_DTOR_NUM)
223
{
224
// Initialize numbers until we reach the target.
225
while (len > a->len)
226
{
227
BcNum* n = bc_vec_pushEmpty(a);
228
bc_num_init(n, BC_NUM_DEF_SIZE);
229
}
230
}
231
else
232
{
233
assert(a->size == sizeof(BcVec) && a->dtor == BC_DTOR_VEC);
234
235
// Recursively initialize arrays until we reach the target. Having the
236
// second argument of bc_array_init() be true will activate the base
237
// case, so we're safe.
238
while (len > a->len)
239
{
240
BcVec* v = bc_vec_pushEmpty(a);
241
bc_array_init(v, true);
242
}
243
}
244
}
245
246
void
247
bc_result_clear(BcResult* r)
248
{
249
r->t = BC_RESULT_TEMP;
250
bc_num_clear(&r->d.n);
251
}
252
253
#if DC_ENABLED
254
void
255
bc_result_copy(BcResult* d, BcResult* src)
256
{
257
assert(d != NULL && src != NULL);
258
259
BC_SIG_ASSERT_LOCKED;
260
261
// d is assumed to not be valid yet.
262
d->t = src->t;
263
264
// Yes, it depends on what type.
265
switch (d->t)
266
{
267
case BC_RESULT_TEMP:
268
case BC_RESULT_IBASE:
269
case BC_RESULT_SCALE:
270
case BC_RESULT_OBASE:
271
#if BC_ENABLE_EXTRA_MATH
272
case BC_RESULT_SEED:
273
#endif // BC_ENABLE_EXTRA_MATH
274
{
275
bc_num_createCopy(&d->d.n, &src->d.n);
276
break;
277
}
278
279
case BC_RESULT_VAR:
280
case BC_RESULT_ARRAY:
281
case BC_RESULT_ARRAY_ELEM:
282
{
283
// NOLINTNEXTLINE
284
memcpy(&d->d.loc, &src->d.loc, sizeof(BcLoc));
285
break;
286
}
287
288
case BC_RESULT_STR:
289
{
290
// NOLINTNEXTLINE
291
memcpy(&d->d.n, &src->d.n, sizeof(BcNum));
292
break;
293
}
294
295
case BC_RESULT_ZERO:
296
case BC_RESULT_ONE:
297
{
298
// Do nothing.
299
break;
300
}
301
302
#if BC_ENABLED
303
case BC_RESULT_VOID:
304
case BC_RESULT_LAST:
305
{
306
#if BC_DEBUG
307
// We should *never* try copying either of these.
308
abort();
309
#endif // BC_DEBUG
310
}
311
#endif // BC_ENABLED
312
}
313
}
314
#endif // DC_ENABLED
315
316
void
317
bc_result_free(void* result)
318
{
319
BcResult* r = (BcResult*) result;
320
321
BC_SIG_ASSERT_LOCKED;
322
323
assert(r != NULL);
324
325
switch (r->t)
326
{
327
case BC_RESULT_TEMP:
328
case BC_RESULT_IBASE:
329
case BC_RESULT_SCALE:
330
case BC_RESULT_OBASE:
331
#if BC_ENABLE_EXTRA_MATH
332
case BC_RESULT_SEED:
333
#endif // BC_ENABLE_EXTRA_MATH
334
{
335
bc_num_free(&r->d.n);
336
break;
337
}
338
339
case BC_RESULT_VAR:
340
case BC_RESULT_ARRAY:
341
case BC_RESULT_ARRAY_ELEM:
342
case BC_RESULT_STR:
343
case BC_RESULT_ZERO:
344
case BC_RESULT_ONE:
345
#if BC_ENABLED
346
case BC_RESULT_VOID:
347
case BC_RESULT_LAST:
348
#endif // BC_ENABLED
349
{
350
// Do nothing.
351
break;
352
}
353
}
354
}
355
356