1 /* $OpenBSD: stack.c,v 1.13 2014/12/01 13:13:00 deraadt Exp $ */
4 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/cdefs.h>
26 static __inline bool stack_empty(const struct stack *);
27 static void stack_grow(struct stack *);
28 static struct array *array_new(void);
29 static __inline void array_free(struct array *);
30 static struct array *array_dup(const struct array *);
31 static __inline void array_grow(struct array *, size_t);
32 static __inline void array_assign(struct array *, size_t, const struct value *);
33 static __inline struct value *array_retrieve(const struct array *, size_t);
36 stack_init(struct stack *stack)
45 stack_empty(const struct stack *stack)
47 bool empty = stack->sp == -1;
54 /* Clear number or string, but leave value itself */
56 stack_free_value(struct value *v)
63 free_number(v->u.num);
73 /* Copy number or string content into already allocated target */
75 stack_dup_value(const struct value *a, struct value *copy)
84 copy->u.num = dup_number(a->u.num);
87 copy->u.string = strdup(a->u.string);
88 if (copy->u.string == NULL)
93 copy->array = a->array == NULL ? NULL : array_dup(a->array);
99 stack_size(const struct stack *stack)
102 return (stack->sp + 1);
106 stack_dup(struct stack *stack)
111 value = stack_tos(stack);
113 warnx("stack empty");
116 stack_push(stack, stack_dup_value(value, ©));
120 stack_swap(struct stack *stack)
125 warnx("stack empty");
128 copy = stack->stack[stack->sp];
129 stack->stack[stack->sp] = stack->stack[stack->sp-1];
130 stack->stack[stack->sp-1] = copy;
134 stack_grow(struct stack *stack)
138 if (++stack->sp == stack->size) {
139 new_size = stack->size * 2 + 1;
140 stack->stack = breallocarray(stack->stack,
141 new_size, sizeof(*stack->stack));
142 stack->size = new_size;
147 stack_pushnumber(struct stack *stack, struct number *b)
151 stack->stack[stack->sp].type = BCODE_NUMBER;
152 stack->stack[stack->sp].u.num = b;
153 stack->stack[stack->sp].array = NULL;
157 stack_pushstring(struct stack *stack, char *string)
161 stack->stack[stack->sp].type = BCODE_STRING;
162 stack->stack[stack->sp].u.string = string;
163 stack->stack[stack->sp].array = NULL;
167 stack_push(struct stack *stack, struct value *v)
173 stack->stack[stack->sp].type = BCODE_NONE;
176 stack_pushnumber(stack, v->u.num);
179 stack_pushstring(stack, v->u.string);
182 stack->stack[stack->sp].array = v->array == NULL ?
183 NULL : array_dup(v->array);
187 stack_tos(const struct stack *stack)
192 return &stack->stack[stack->sp];
196 stack_set_tos(struct stack *stack, struct value *v)
200 stack_push(stack, v);
202 stack_free_value(&stack->stack[stack->sp]);
203 stack->stack[stack->sp] = *v;
204 stack->stack[stack->sp].array = v->array == NULL ?
205 NULL : array_dup(v->array);
210 stack_pop(struct stack *stack)
213 if (stack_empty(stack))
215 return &stack->stack[stack->sp--];
219 stack_popnumber(struct stack *stack)
222 if (stack_empty(stack))
224 array_free(stack->stack[stack->sp].array);
225 stack->stack[stack->sp].array = NULL;
226 if (stack->stack[stack->sp].type != BCODE_NUMBER) {
227 warnx("not a number"); /* XXX remove */
230 return stack->stack[stack->sp--].u.num;
234 stack_popstring(struct stack *stack)
237 if (stack_empty(stack))
239 array_free(stack->stack[stack->sp].array);
240 stack->stack[stack->sp].array = NULL;
241 if (stack->stack[stack->sp].type != BCODE_STRING) {
242 warnx("not a string"); /* XXX remove */
245 return stack->stack[stack->sp--].u.string;
249 stack_clear(struct stack *stack)
252 while (stack->sp >= 0)
253 stack_free_value(&stack->stack[stack->sp--]);
259 stack_print(FILE *f, const struct stack *stack, const char *prefix, u_int base)
263 for (i = stack->sp; i >= 0; i--) {
264 print_value(f, &stack->stack[i], prefix, base);
270 static struct array *
275 a = bmalloc(sizeof(*a));
282 array_free(struct array *a)
288 for (i = 0; i < a->size; i++)
289 stack_free_value(&a->data[i]);
294 static struct array *
295 array_dup(const struct array *a)
303 array_grow(n, a->size);
304 for (i = 0; i < a->size; i++)
305 stack_dup_value(&a->data[i], &n->data[i]);
310 array_grow(struct array *array, size_t newsize)
314 array->data = breallocarray(array->data, newsize, sizeof(*array->data));
315 for (i = array->size; i < newsize; i++) {
316 array->data[i].type = BCODE_NONE;
317 array->data[i].array = NULL;
319 array->size = newsize;
323 array_assign(struct array *array, size_t i, const struct value *v)
326 if (i >= array->size)
327 array_grow(array, i + 1);
328 stack_free_value(&array->data[i]);
332 static __inline struct value *
333 array_retrieve(const struct array *array, size_t i)
336 if (i >= array->size)
338 return &array->data[i];
342 frame_assign(struct stack *stack, size_t i, const struct value *v)
347 if (stack->sp == -1) {
350 stack_push(stack, &n);
353 a = stack->stack[stack->sp].array;
355 a = stack->stack[stack->sp].array = array_new();
356 array_assign(a, i, v);
360 frame_retrieve(const struct stack *stack, size_t i)
366 a = stack->stack[stack->sp].array;
368 a = stack->stack[stack->sp].array = array_new();
369 return array_retrieve(a, i);