2 * $OpenBSD: stack.c,v 1.6 2003/11/26 19:30:52 otto Exp $
3 * $DragonFly: src/usr.bin/dc/stack.c,v 1.1 2004/09/20 04:20:39 dillon Exp $
7 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 static __inline bool stack_empty(const struct stack *);
29 static void stack_grow(struct stack *);
30 static struct array *array_new(void);
31 static __inline void array_free(struct array *);
32 static struct array * array_dup(const struct array *);
33 static __inline void array_grow(struct array *, size_t);
34 static __inline void array_assign(struct array *, size_t, const struct value *);
35 static __inline struct value *array_retrieve(const struct array *, size_t);
38 stack_init(struct stack *stack)
46 stack_empty(const struct stack * stack)
48 bool empty = stack->sp == -1;
54 /* Clear number or string, but leave value itself */
56 stack_free_value(struct value *v)
62 free_number(v->u.num);
68 if (v->array != NULL) {
74 /* Copy number or string content into already allocated target */
76 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)
101 return stack->sp + 1;
105 stack_dup(struct stack *stack)
110 value = stack_tos(stack);
112 warnx("stack empty");
115 stack_push(stack, stack_dup_value(value, ©));
119 stack_swap(struct stack *stack)
124 warnx("stack empty");
127 copy = stack->stack[stack->sp];
128 stack->stack[stack->sp] = stack->stack[stack->sp-1];
129 stack->stack[stack->sp-1] = copy;
133 stack_grow(struct stack *stack)
137 if (++stack->sp == stack->size) {
138 new_size = stack->size * 2 + 1;
139 stack->stack = brealloc(stack->stack,
140 new_size * sizeof(*stack->stack));
141 for (i = stack->size; i < new_size; i++)
142 stack->stack[i].array = NULL;
143 stack->size = new_size;
148 stack_pushnumber(struct stack *stack, struct number *b)
151 stack->stack[stack->sp].type = BCODE_NUMBER;
152 stack->stack[stack->sp].u.num = b;
156 stack_pushstring(struct stack *stack, char *string)
159 stack->stack[stack->sp].type = BCODE_STRING;
160 stack->stack[stack->sp].u.string = string;
164 stack_push(struct stack *stack, struct value *v)
169 stack->stack[stack->sp].type = BCODE_NONE;
172 stack_pushnumber(stack, v->u.num);
175 stack_pushstring(stack, v->u.string);
178 stack->stack[stack->sp].array = v->array == NULL ?
179 NULL : array_dup(v->array);
183 stack_tos(const struct stack *stack)
187 return &stack->stack[stack->sp];
191 stack_set_tos(struct stack *stack, struct value *v)
194 stack_push(stack, v);
196 stack_free_value(&stack->stack[stack->sp]);
197 stack->stack[stack->sp] = *v;
198 stack->stack[stack->sp].array = v->array == NULL ?
199 NULL : array_dup(v->array);
204 stack_pop(struct stack *stack)
206 if (stack_empty(stack))
208 return &stack->stack[stack->sp--];
212 stack_popnumber(struct stack *stack)
214 if (stack_empty(stack))
216 if (stack->stack[stack->sp].array != NULL) {
217 array_free(stack->stack[stack->sp].array);
218 stack->stack[stack->sp].array = NULL;
220 if (stack->stack[stack->sp].type != BCODE_NUMBER) {
221 warnx("not a number"); /* XXX remove */
224 return stack->stack[stack->sp--].u.num;
228 stack_popstring(struct stack *stack)
230 if (stack_empty(stack))
232 if (stack->stack[stack->sp].array != NULL) {
233 array_free(stack->stack[stack->sp].array);
234 stack->stack[stack->sp].array = NULL;
236 if (stack->stack[stack->sp].type != BCODE_STRING) {
237 warnx("not a string"); /* XXX remove */
240 return stack->stack[stack->sp--].u.string;
244 stack_clear(struct stack *stack)
246 while (stack->sp >= 0) {
247 stack_free_value(&stack->stack[stack->sp--]);
254 stack_print(FILE *f, const struct stack *stack, const char *prefix, u_int base)
258 for (i = stack->sp; i >= 0; i--) {
259 print_value(f, &stack->stack[i], prefix, base);
265 static struct array *
270 a = bmalloc(sizeof(*a));
277 array_free(struct array *a)
283 for (i = 0; i < a->size; i++)
284 stack_free_value(&a->data[i]);
289 static struct array *
290 array_dup(const struct array *a)
298 array_grow(n, a->size);
299 for (i = 0; i < a->size; i++)
300 stack_dup_value(&a->data[i], &n->data[i]);
305 array_grow(struct array *array, size_t newsize)
309 array->data = brealloc(array->data, newsize * sizeof(*array->data));
310 for (i = array->size; i < newsize; i++)
311 array->data[i].array = NULL;
312 array->size = newsize;
316 array_assign(struct array *array, size_t index, const struct value *v)
318 if (index >= array->size)
319 array_grow(array, index+1);
320 array->data[index] = *v;
323 static __inline struct value *
324 array_retrieve(const struct array *array, size_t index)
326 if (index >= array->size)
328 return &array->data[index];
332 frame_assign(struct stack *stack, size_t index, const struct value *v)
337 if (stack->sp == -1) {
340 stack_push(stack, &n);
343 a = stack->stack[stack->sp].array;
345 a = stack->stack[stack->sp].array = array_new();
346 array_assign(a, index, v);
350 frame_retrieve(const struct stack *stack, size_t index)
356 a = stack->stack[stack->sp].array;
358 a = stack->stack[stack->sp].array = array_new();
359 return array_retrieve(a, index);