Annotation of src/usr.bin/dc/stack.c, Revision 1.7
1.7 ! deraadt 1: /* $OpenBSD: stack.c,v 1.6 2003/11/26 19:30:52 otto Exp $ */
1.1 otto 2:
3: /*
4: * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5: *
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.
9: *
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.
17: */
18:
19: #ifndef lint
1.7 ! deraadt 20: static const char rcsid[] = "$OpenBSD: stack.c,v 1.6 2003/11/26 19:30:52 otto Exp $";
1.1 otto 21: #endif /* not lint */
22:
23: #include <err.h>
24: #include <stdlib.h>
25: #include <string.h>
26:
27: #include "extern.h"
28:
29: static __inline bool stack_empty(const struct stack *);
30: static void stack_grow(struct stack *);
31: static struct array *array_new(void);
32: static __inline void array_free(struct array *);
33: static struct array * array_dup(const struct array *);
34: static __inline void array_grow(struct array *, size_t);
35: static __inline void array_assign(struct array *, size_t, const struct value *);
36: static __inline struct value *array_retrieve(const struct array *, size_t);
37:
38: void
39: stack_init(struct stack *stack)
40: {
41: stack->size = 0;
42: stack->sp = -1;
43: stack->stack = NULL;
44: }
45:
46: static __inline bool
1.7 ! deraadt 47: stack_empty(const struct stack *stack)
1.1 otto 48: {
49: bool empty = stack->sp == -1;
50: if (empty)
51: warnx("stack empty");
52: return empty;
53: }
54:
55: /* Clear number or string, but leave value itself */
56: void
57: stack_free_value(struct value *v)
58: {
59: switch (v->type) {
60: case BCODE_NONE:
61: break;
62: case BCODE_NUMBER:
63: free_number(v->u.num);
64: break;
65: case BCODE_STRING:
66: free(v->u.string);
67: break;
68: }
69: if (v->array != NULL) {
70: array_free(v->array);
71: v->array = NULL;
72: }
73: }
74:
75: /* Copy number or string content into already allocated target */
76: struct value *
77: stack_dup_value(const struct value *a, struct value *copy)
78: {
79: copy->type = a->type;
80:
81: switch (a->type) {
82: case BCODE_NONE:
83: break;
84: case BCODE_NUMBER:
85: copy->u.num = dup_number(a->u.num);
86: break;
87: case BCODE_STRING:
88: copy->u.string = strdup(a->u.string);
89: if (copy->u.string == NULL)
1.4 otto 90: err(1, NULL);
1.1 otto 91: break;
92: }
93:
94: copy->array = a->array == NULL ? NULL : array_dup(a->array);
95:
96: return copy;
97: }
98:
99: int
1.7 ! deraadt 100: stack_size(const struct stack *stack)
1.1 otto 101: {
102: return stack->sp + 1;
103: }
104:
105: void
106: stack_dup(struct stack *stack)
107: {
108: struct value *value;
109: struct value copy;
110:
111: value = stack_tos(stack);
112: if (value == NULL) {
113: warnx("stack empty");
114: return;
115: }
116: stack_push(stack, stack_dup_value(value, ©));
1.5 otto 117: }
118:
119: void
120: stack_swap(struct stack *stack)
121: {
122: struct value copy;
123:
124: if (stack->sp < 1) {
125: warnx("stack empty");
126: return;
127: }
128: copy = stack->stack[stack->sp];
129: stack->stack[stack->sp] = stack->stack[stack->sp-1];
130: stack->stack[stack->sp-1] = copy;
1.1 otto 131: }
132:
133: static void
134: stack_grow(struct stack *stack)
135: {
1.3 otto 136: int new_size, i;
1.1 otto 137:
138: if (++stack->sp == stack->size) {
1.3 otto 139: new_size = stack->size * 2 + 1;
1.1 otto 140: stack->stack = brealloc(stack->stack,
1.3 otto 141: new_size * sizeof(*stack->stack));
142: for (i = stack->size; i < new_size; i++)
1.1 otto 143: stack->stack[i].array = NULL;
1.3 otto 144: stack->size = new_size;
1.1 otto 145: }
146: }
147:
148: void
149: stack_pushnumber(struct stack *stack, struct number *b)
150: {
151: stack_grow(stack);
152: stack->stack[stack->sp].type = BCODE_NUMBER;
153: stack->stack[stack->sp].u.num = b;
154: }
155:
156: void
157: stack_pushstring(struct stack *stack, char *string)
158: {
159: stack_grow(stack);
160: stack->stack[stack->sp].type = BCODE_STRING;
161: stack->stack[stack->sp].u.string = string;
162: }
163:
164: void
165: stack_push(struct stack *stack, struct value *v)
166: {
167: switch (v->type) {
168: case BCODE_NONE:
169: stack_grow(stack);
170: stack->stack[stack->sp].type = BCODE_NONE;
171: break;
172: case BCODE_NUMBER:
173: stack_pushnumber(stack, v->u.num);
174: break;
175: case BCODE_STRING:
176: stack_pushstring(stack, v->u.string);
177: break;
178: }
179: stack->stack[stack->sp].array = v->array == NULL ?
180: NULL : array_dup(v->array);
181: }
182:
183: struct value *
184: stack_tos(const struct stack *stack)
185: {
186: if (stack->sp == -1)
187: return NULL;
188: return &stack->stack[stack->sp];
189: }
190:
191: void
192: stack_set_tos(struct stack *stack, struct value *v)
193: {
194: if (stack->sp == -1)
195: stack_push(stack, v);
196: else {
197: stack_free_value(&stack->stack[stack->sp]);
198: stack->stack[stack->sp] = *v;
199: stack->stack[stack->sp].array = v->array == NULL ?
1.7 ! deraadt 200: NULL : array_dup(v->array);
1.1 otto 201: }
202: }
203:
204: struct value *
205: stack_pop(struct stack *stack)
206: {
207: if (stack_empty(stack))
208: return NULL;
209: return &stack->stack[stack->sp--];
210: }
211:
212: struct number *
213: stack_popnumber(struct stack *stack)
214: {
215: if (stack_empty(stack))
216: return NULL;
217: if (stack->stack[stack->sp].array != NULL) {
218: array_free(stack->stack[stack->sp].array);
219: stack->stack[stack->sp].array = NULL;
220: }
221: if (stack->stack[stack->sp].type != BCODE_NUMBER) {
222: warnx("not a number"); /* XXX remove */
223: return NULL;
224: }
225: return stack->stack[stack->sp--].u.num;
226: }
227:
228: char *
229: stack_popstring(struct stack *stack)
230: {
231: if (stack_empty(stack))
232: return NULL;
233: if (stack->stack[stack->sp].array != NULL) {
234: array_free(stack->stack[stack->sp].array);
235: stack->stack[stack->sp].array = NULL;
236: }
237: if (stack->stack[stack->sp].type != BCODE_STRING) {
238: warnx("not a string"); /* XXX remove */
239: return NULL;
240: }
241: return stack->stack[stack->sp--].u.string;
242: }
243:
244: void
245: stack_clear(struct stack *stack)
246: {
247: while (stack->sp >= 0) {
248: stack_free_value(&stack->stack[stack->sp--]);
249: }
250: free(stack->stack);
251: stack_init(stack);
252: }
253:
254: void
255: stack_print(FILE *f, const struct stack *stack, const char *prefix, u_int base)
256: {
257: int i;
258:
259: for (i = stack->sp; i >= 0; i--) {
260: print_value(f, &stack->stack[i], prefix, base);
261: putc('\n', f);
262: }
263: }
264:
265:
266: static struct array *
267: array_new(void)
268: {
269: struct array *a;
270:
271: a = bmalloc(sizeof(*a));
272: a->data = NULL;
273: a->size = 0;
274: return a;
275: }
276:
277: static __inline void
278: array_free(struct array *a)
279: {
280: u_int i;
281:
282: if (a == NULL)
283: return;
284: for (i = 0; i < a->size; i++)
285: stack_free_value(&a->data[i]);
286: free(a->data);
287: free(a);
288: }
289:
290: static struct array *
291: array_dup(const struct array *a)
292: {
293: struct array *n;
294: u_int i;
295:
296: if (a == NULL)
297: return NULL;
298: n = array_new();
299: array_grow(n, a->size);
1.2 deraadt 300: for (i = 0; i < a->size; i++)
1.1 otto 301: stack_dup_value(&a->data[i], &n->data[i]);
302: return n;
303: }
304:
305: static __inline void
306: array_grow(struct array *array, size_t newsize)
307: {
308: size_t i;
309:
310: array->data = brealloc(array->data, newsize * sizeof(*array->data));
311: for (i = array->size; i < newsize; i++)
312: array->data[i].array = NULL;
313: array->size = newsize;
314: }
315:
316: static __inline void
317: array_assign(struct array *array, size_t index, const struct value *v)
318: {
319: if (index >= array->size)
320: array_grow(array, index+1);
321: array->data[index] = *v;
322: }
323:
324: static __inline struct value *
325: array_retrieve(const struct array *array, size_t index)
326: {
327: if (index >= array->size)
328: return NULL;
329: return &array->data[index];
330: }
331:
332: void
333: frame_assign(struct stack *stack, size_t index, const struct value *v)
334: {
335: struct array *a;
336: struct value n;
337:
338: if (stack->sp == -1) {
339: n.type = BCODE_NONE;
340: n.array = NULL;
341: stack_push(stack, &n);
342: }
343:
344: a = stack->stack[stack->sp].array;
345: if (a == NULL)
346: a = stack->stack[stack->sp].array = array_new();
347: array_assign(a, index, v);
348: }
349:
350: struct value *
351: frame_retrieve(const struct stack *stack, size_t index)
352: {
353: struct array *a;
354:
1.6 otto 355: if (stack->sp == -1)
356: return NULL;
1.1 otto 357: a = stack->stack[stack->sp].array;
358: if (a == NULL)
359: a = stack->stack[stack->sp].array = array_new();
360: return array_retrieve(a, index);
361: }