1*9ec9f480Sotto /* $OpenBSD: stack.c,v 1.15 2017/12/06 13:48:05 otto Exp $ */
2a6ce4a44Sotto
3a6ce4a44Sotto /*
4a6ce4a44Sotto * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5a6ce4a44Sotto *
6a6ce4a44Sotto * Permission to use, copy, modify, and distribute this software for any
7a6ce4a44Sotto * purpose with or without fee is hereby granted, provided that the above
8a6ce4a44Sotto * copyright notice and this permission notice appear in all copies.
9a6ce4a44Sotto *
10a6ce4a44Sotto * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11a6ce4a44Sotto * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12a6ce4a44Sotto * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13a6ce4a44Sotto * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a6ce4a44Sotto * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a6ce4a44Sotto * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a6ce4a44Sotto * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a6ce4a44Sotto */
18a6ce4a44Sotto
19a6ce4a44Sotto #include <err.h>
20a6ce4a44Sotto #include <stdlib.h>
21a6ce4a44Sotto #include <string.h>
22a6ce4a44Sotto
23a6ce4a44Sotto #include "extern.h"
24a6ce4a44Sotto
25a6ce4a44Sotto static __inline bool stack_empty(const struct stack *);
26a6ce4a44Sotto static void stack_grow(struct stack *);
27a6ce4a44Sotto static struct array *array_new(void);
28a6ce4a44Sotto static __inline void array_free(struct array *);
29a6ce4a44Sotto static struct array * array_dup(const struct array *);
30a6ce4a44Sotto static __inline void array_grow(struct array *, size_t);
31a6ce4a44Sotto static __inline void array_assign(struct array *, size_t, const struct value *);
32a6ce4a44Sotto static __inline struct value *array_retrieve(const struct array *, size_t);
33a6ce4a44Sotto
34a6ce4a44Sotto void
stack_init(struct stack * stack)35a6ce4a44Sotto stack_init(struct stack *stack)
36a6ce4a44Sotto {
37a6ce4a44Sotto stack->size = 0;
38a6ce4a44Sotto stack->sp = -1;
39a6ce4a44Sotto stack->stack = NULL;
40a6ce4a44Sotto }
41a6ce4a44Sotto
42a6ce4a44Sotto static __inline bool
stack_empty(const struct stack * stack)43a6ce4a44Sotto stack_empty(const struct stack *stack)
44a6ce4a44Sotto {
45a6ce4a44Sotto bool empty = stack->sp == -1;
46a6ce4a44Sotto if (empty)
47a6ce4a44Sotto warnx("stack empty");
48a6ce4a44Sotto return empty;
49a6ce4a44Sotto }
50a6ce4a44Sotto
51a6ce4a44Sotto /* Clear number or string, but leave value itself */
52a6ce4a44Sotto void
stack_free_value(struct value * v)53a6ce4a44Sotto stack_free_value(struct value *v)
54a6ce4a44Sotto {
55a6ce4a44Sotto switch (v->type) {
56a6ce4a44Sotto case BCODE_NONE:
57a6ce4a44Sotto break;
58a6ce4a44Sotto case BCODE_NUMBER:
59a6ce4a44Sotto free_number(v->u.num);
60a6ce4a44Sotto break;
61a6ce4a44Sotto case BCODE_STRING:
62a6ce4a44Sotto free(v->u.string);
63a6ce4a44Sotto break;
64a6ce4a44Sotto }
65a6ce4a44Sotto array_free(v->array);
66a6ce4a44Sotto v->array = NULL;
67a6ce4a44Sotto }
68a6ce4a44Sotto
69a6ce4a44Sotto /* Copy number or string content into already allocated target */
70a6ce4a44Sotto struct value *
stack_dup_value(const struct value * a,struct value * copy)71a6ce4a44Sotto stack_dup_value(const struct value *a, struct value *copy)
72a6ce4a44Sotto {
73a6ce4a44Sotto copy->type = a->type;
74a6ce4a44Sotto
75a6ce4a44Sotto switch (a->type) {
76a6ce4a44Sotto case BCODE_NONE:
77a6ce4a44Sotto break;
78a6ce4a44Sotto case BCODE_NUMBER:
79a6ce4a44Sotto copy->u.num = dup_number(a->u.num);
80a6ce4a44Sotto break;
81a6ce4a44Sotto case BCODE_STRING:
82*9ec9f480Sotto copy->u.string = bstrdup(a->u.string);
83a6ce4a44Sotto break;
84a6ce4a44Sotto }
85a6ce4a44Sotto
86a6ce4a44Sotto copy->array = a->array == NULL ? NULL : array_dup(a->array);
87a6ce4a44Sotto
88a6ce4a44Sotto return copy;
89a6ce4a44Sotto }
90a6ce4a44Sotto
91c982bb45Sotto size_t
stack_size(const struct stack * stack)92a6ce4a44Sotto stack_size(const struct stack *stack)
93a6ce4a44Sotto {
94a6ce4a44Sotto return stack->sp + 1;
95a6ce4a44Sotto }
96a6ce4a44Sotto
97a6ce4a44Sotto void
stack_dup(struct stack * stack)98a6ce4a44Sotto stack_dup(struct stack *stack)
99a6ce4a44Sotto {
100a6ce4a44Sotto struct value *value;
101a6ce4a44Sotto struct value copy;
102a6ce4a44Sotto
103a6ce4a44Sotto value = stack_tos(stack);
104a6ce4a44Sotto if (value == NULL) {
105a6ce4a44Sotto warnx("stack empty");
106a6ce4a44Sotto return;
107a6ce4a44Sotto }
108a6ce4a44Sotto stack_push(stack, stack_dup_value(value, ©));
109a6ce4a44Sotto }
110a6ce4a44Sotto
1114e2c9909Sotto void
stack_swap(struct stack * stack)1124e2c9909Sotto stack_swap(struct stack *stack)
1134e2c9909Sotto {
1144e2c9909Sotto struct value copy;
1154e2c9909Sotto
1164e2c9909Sotto if (stack->sp < 1) {
1174e2c9909Sotto warnx("stack empty");
1184e2c9909Sotto return;
1194e2c9909Sotto }
1204e2c9909Sotto copy = stack->stack[stack->sp];
1214e2c9909Sotto stack->stack[stack->sp] = stack->stack[stack->sp-1];
1224e2c9909Sotto stack->stack[stack->sp-1] = copy;
1234e2c9909Sotto }
1244e2c9909Sotto
125a6ce4a44Sotto static void
stack_grow(struct stack * stack)126a6ce4a44Sotto stack_grow(struct stack *stack)
127a6ce4a44Sotto {
128311bfd08Sotto size_t new_size;
129a6ce4a44Sotto
130a6ce4a44Sotto if (++stack->sp == stack->size) {
13144845cb5Sotto new_size = stack->size * 2 + 1;
1325805b5e9Sderaadt stack->stack = breallocarray(stack->stack,
1335805b5e9Sderaadt new_size, sizeof(*stack->stack));
13444845cb5Sotto stack->size = new_size;
135a6ce4a44Sotto }
136a6ce4a44Sotto }
137a6ce4a44Sotto
138a6ce4a44Sotto void
stack_pushnumber(struct stack * stack,struct number * b)139a6ce4a44Sotto stack_pushnumber(struct stack *stack, struct number *b)
140a6ce4a44Sotto {
141a6ce4a44Sotto stack_grow(stack);
142a6ce4a44Sotto stack->stack[stack->sp].type = BCODE_NUMBER;
143a6ce4a44Sotto stack->stack[stack->sp].u.num = b;
144311bfd08Sotto stack->stack[stack->sp].array = NULL;
145a6ce4a44Sotto }
146a6ce4a44Sotto
147a6ce4a44Sotto void
stack_pushstring(struct stack * stack,char * string)148a6ce4a44Sotto stack_pushstring(struct stack *stack, char *string)
149a6ce4a44Sotto {
150a6ce4a44Sotto stack_grow(stack);
151a6ce4a44Sotto stack->stack[stack->sp].type = BCODE_STRING;
152a6ce4a44Sotto stack->stack[stack->sp].u.string = string;
153311bfd08Sotto stack->stack[stack->sp].array = NULL;
154a6ce4a44Sotto }
155a6ce4a44Sotto
156a6ce4a44Sotto void
stack_push(struct stack * stack,struct value * v)157a6ce4a44Sotto stack_push(struct stack *stack, struct value *v)
158a6ce4a44Sotto {
159a6ce4a44Sotto switch (v->type) {
160a6ce4a44Sotto case BCODE_NONE:
161a6ce4a44Sotto stack_grow(stack);
162a6ce4a44Sotto stack->stack[stack->sp].type = BCODE_NONE;
163a6ce4a44Sotto break;
164a6ce4a44Sotto case BCODE_NUMBER:
165a6ce4a44Sotto stack_pushnumber(stack, v->u.num);
166a6ce4a44Sotto break;
167a6ce4a44Sotto case BCODE_STRING:
168a6ce4a44Sotto stack_pushstring(stack, v->u.string);
169a6ce4a44Sotto break;
170a6ce4a44Sotto }
171a6ce4a44Sotto stack->stack[stack->sp].array = v->array == NULL ?
172a6ce4a44Sotto NULL : array_dup(v->array);
173a6ce4a44Sotto }
174a6ce4a44Sotto
175a6ce4a44Sotto struct value *
stack_tos(const struct stack * stack)176a6ce4a44Sotto stack_tos(const struct stack *stack)
177a6ce4a44Sotto {
178a6ce4a44Sotto if (stack->sp == -1)
179a6ce4a44Sotto return NULL;
180a6ce4a44Sotto return &stack->stack[stack->sp];
181a6ce4a44Sotto }
182a6ce4a44Sotto
183a6ce4a44Sotto void
stack_set_tos(struct stack * stack,struct value * v)184a6ce4a44Sotto stack_set_tos(struct stack *stack, struct value *v)
185a6ce4a44Sotto {
186a6ce4a44Sotto if (stack->sp == -1)
187a6ce4a44Sotto stack_push(stack, v);
188a6ce4a44Sotto else {
189a6ce4a44Sotto stack_free_value(&stack->stack[stack->sp]);
190a6ce4a44Sotto stack->stack[stack->sp] = *v;
191a6ce4a44Sotto stack->stack[stack->sp].array = v->array == NULL ?
192a6ce4a44Sotto NULL : array_dup(v->array);
193a6ce4a44Sotto }
194a6ce4a44Sotto }
195a6ce4a44Sotto
196a6ce4a44Sotto struct value *
stack_pop(struct stack * stack)197a6ce4a44Sotto stack_pop(struct stack *stack)
198a6ce4a44Sotto {
199a6ce4a44Sotto if (stack_empty(stack))
200a6ce4a44Sotto return NULL;
201a6ce4a44Sotto return &stack->stack[stack->sp--];
202a6ce4a44Sotto }
203a6ce4a44Sotto
204a6ce4a44Sotto struct number *
stack_popnumber(struct stack * stack)205a6ce4a44Sotto stack_popnumber(struct stack *stack)
206a6ce4a44Sotto {
207a6ce4a44Sotto if (stack_empty(stack))
208a6ce4a44Sotto return NULL;
209a6ce4a44Sotto array_free(stack->stack[stack->sp].array);
210a6ce4a44Sotto stack->stack[stack->sp].array = NULL;
211a6ce4a44Sotto if (stack->stack[stack->sp].type != BCODE_NUMBER) {
212a6ce4a44Sotto warnx("not a number"); /* XXX remove */
213a6ce4a44Sotto return NULL;
214a6ce4a44Sotto }
215a6ce4a44Sotto return stack->stack[stack->sp--].u.num;
216a6ce4a44Sotto }
217a6ce4a44Sotto
218a6ce4a44Sotto char *
stack_popstring(struct stack * stack)219a6ce4a44Sotto stack_popstring(struct stack *stack)
220a6ce4a44Sotto {
221a6ce4a44Sotto if (stack_empty(stack))
222a6ce4a44Sotto return NULL;
223a6ce4a44Sotto array_free(stack->stack[stack->sp].array);
224a6ce4a44Sotto stack->stack[stack->sp].array = NULL;
225a6ce4a44Sotto if (stack->stack[stack->sp].type != BCODE_STRING) {
226a6ce4a44Sotto warnx("not a string"); /* XXX remove */
227a6ce4a44Sotto return NULL;
228a6ce4a44Sotto }
229a6ce4a44Sotto return stack->stack[stack->sp--].u.string;
230a6ce4a44Sotto }
231a6ce4a44Sotto
232a6ce4a44Sotto void
stack_clear(struct stack * stack)233a6ce4a44Sotto stack_clear(struct stack *stack)
234a6ce4a44Sotto {
235e952d73dSotto while (stack->sp >= 0)
236a6ce4a44Sotto stack_free_value(&stack->stack[stack->sp--]);
237a6ce4a44Sotto free(stack->stack);
238a6ce4a44Sotto stack_init(stack);
239a6ce4a44Sotto }
240a6ce4a44Sotto
241a6ce4a44Sotto void
stack_print(FILE * f,const struct stack * stack,const char * prefix,u_int base)242a6ce4a44Sotto stack_print(FILE *f, const struct stack *stack, const char *prefix, u_int base)
243a6ce4a44Sotto {
244c982bb45Sotto ssize_t i;
245a6ce4a44Sotto
246a6ce4a44Sotto for (i = stack->sp; i >= 0; i--) {
247a6ce4a44Sotto print_value(f, &stack->stack[i], prefix, base);
248a1a9dfc3Sotto (void)putc('\n', f);
249a6ce4a44Sotto }
250a6ce4a44Sotto }
251a6ce4a44Sotto
252a6ce4a44Sotto
253a6ce4a44Sotto static struct array *
array_new(void)254a6ce4a44Sotto array_new(void)
255a6ce4a44Sotto {
256a6ce4a44Sotto struct array *a;
257a6ce4a44Sotto
258a6ce4a44Sotto a = bmalloc(sizeof(*a));
259a6ce4a44Sotto a->data = NULL;
260a6ce4a44Sotto a->size = 0;
261a6ce4a44Sotto return a;
262a6ce4a44Sotto }
263a6ce4a44Sotto
264a6ce4a44Sotto static __inline void
array_free(struct array * a)265a6ce4a44Sotto array_free(struct array *a)
266a6ce4a44Sotto {
267c982bb45Sotto size_t i;
268a6ce4a44Sotto
269a6ce4a44Sotto if (a == NULL)
270a6ce4a44Sotto return;
271a6ce4a44Sotto for (i = 0; i < a->size; i++)
272a6ce4a44Sotto stack_free_value(&a->data[i]);
273a6ce4a44Sotto free(a->data);
274a6ce4a44Sotto free(a);
275a6ce4a44Sotto }
276a6ce4a44Sotto
277a6ce4a44Sotto static struct array *
array_dup(const struct array * a)278a6ce4a44Sotto array_dup(const struct array *a)
279a6ce4a44Sotto {
280a6ce4a44Sotto struct array *n;
281c982bb45Sotto size_t i;
282a6ce4a44Sotto
283a6ce4a44Sotto if (a == NULL)
284a6ce4a44Sotto return NULL;
285a6ce4a44Sotto n = array_new();
286a6ce4a44Sotto array_grow(n, a->size);
287a6ce4a44Sotto for (i = 0; i < a->size; i++)
288a1a9dfc3Sotto (void)stack_dup_value(&a->data[i], &n->data[i]);
289a6ce4a44Sotto return n;
290a6ce4a44Sotto }
291a6ce4a44Sotto
292a6ce4a44Sotto static __inline void
array_grow(struct array * array,size_t newsize)293a6ce4a44Sotto array_grow(struct array *array, size_t newsize)
294a6ce4a44Sotto {
295a6ce4a44Sotto size_t i;
296a6ce4a44Sotto
2975805b5e9Sderaadt array->data = breallocarray(array->data, newsize, sizeof(*array->data));
2987444001dSotto for (i = array->size; i < newsize; i++) {
2997444001dSotto array->data[i].type = BCODE_NONE;
300a6ce4a44Sotto array->data[i].array = NULL;
3017444001dSotto }
302a6ce4a44Sotto array->size = newsize;
303a6ce4a44Sotto }
304a6ce4a44Sotto
305a6ce4a44Sotto static __inline void
array_assign(struct array * array,size_t index,const struct value * v)306a6ce4a44Sotto array_assign(struct array *array, size_t index, const struct value *v)
307a6ce4a44Sotto {
308a6ce4a44Sotto if (index >= array->size)
309a6ce4a44Sotto array_grow(array, index+1);
3107444001dSotto stack_free_value(&array->data[index]);
311a6ce4a44Sotto array->data[index] = *v;
312a6ce4a44Sotto }
313a6ce4a44Sotto
314a6ce4a44Sotto static __inline struct value *
array_retrieve(const struct array * array,size_t index)315a6ce4a44Sotto array_retrieve(const struct array *array, size_t index)
316a6ce4a44Sotto {
317a6ce4a44Sotto if (index >= array->size)
318a6ce4a44Sotto return NULL;
319a6ce4a44Sotto return &array->data[index];
320a6ce4a44Sotto }
321a6ce4a44Sotto
322a6ce4a44Sotto void
frame_assign(struct stack * stack,size_t index,const struct value * v)323a6ce4a44Sotto frame_assign(struct stack *stack, size_t index, const struct value *v)
324a6ce4a44Sotto {
325a6ce4a44Sotto struct array *a;
326a6ce4a44Sotto struct value n;
327a6ce4a44Sotto
328a6ce4a44Sotto if (stack->sp == -1) {
329a6ce4a44Sotto n.type = BCODE_NONE;
330a6ce4a44Sotto n.array = NULL;
331a6ce4a44Sotto stack_push(stack, &n);
332a6ce4a44Sotto }
333a6ce4a44Sotto
334a6ce4a44Sotto a = stack->stack[stack->sp].array;
335a6ce4a44Sotto if (a == NULL)
336a6ce4a44Sotto a = stack->stack[stack->sp].array = array_new();
337a6ce4a44Sotto array_assign(a, index, v);
338a6ce4a44Sotto }
339a6ce4a44Sotto
340a6ce4a44Sotto struct value *
frame_retrieve(const struct stack * stack,size_t index)341a6ce4a44Sotto frame_retrieve(const struct stack *stack, size_t index)
342a6ce4a44Sotto {
343a6ce4a44Sotto struct array *a;
344a6ce4a44Sotto
34510a3df37Sotto if (stack->sp == -1)
34610a3df37Sotto return NULL;
347a6ce4a44Sotto a = stack->stack[stack->sp].array;
348a6ce4a44Sotto if (a == NULL)
349a6ce4a44Sotto a = stack->stack[stack->sp].array = array_new();
350a6ce4a44Sotto return array_retrieve(a, index);
351a6ce4a44Sotto }
352