2 * $OpenBSD: stack.c,v 1.12 2014/11/26 15:05:51 otto Exp $
3 * $DragonFly: src/usr.bin/dc/stack.c,v 1.2 2005/04/21 18:50:50 swildner 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 stack
->size
= new_size
;
146 stack_pushnumber(struct stack
*stack
, struct number
*b
)
149 stack
->stack
[stack
->sp
].type
= BCODE_NUMBER
;
150 stack
->stack
[stack
->sp
].u
.num
= b
;
151 stack
->stack
[stack
->sp
].array
= NULL
;
155 stack_pushstring(struct stack
*stack
, char *string
)
158 stack
->stack
[stack
->sp
].type
= BCODE_STRING
;
159 stack
->stack
[stack
->sp
].u
.string
= string
;
160 stack
->stack
[stack
->sp
].array
= NULL
;
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
].type
= BCODE_NONE
;
312 array
->data
[i
].array
= NULL
;
314 array
->size
= newsize
;
318 array_assign(struct array
*array
, size_t index
, const struct value
*v
)
320 if (index
>= array
->size
)
321 array_grow(array
, index
+1);
322 stack_free_value(&array
->data
[index
]);
323 array
->data
[index
] = *v
;
326 static __inline
struct value
*
327 array_retrieve(const struct array
*array
, size_t index
)
329 if (index
>= array
->size
)
331 return &array
->data
[index
];
335 frame_assign(struct stack
*stack
, size_t index
, const struct value
*v
)
340 if (stack
->sp
== -1) {
343 stack_push(stack
, &n
);
346 a
= stack
->stack
[stack
->sp
].array
;
348 a
= stack
->stack
[stack
->sp
].array
= array_new();
349 array_assign(a
, index
, v
);
353 frame_retrieve(const struct stack
*stack
, size_t index
)
359 a
= stack
->stack
[stack
->sp
].array
;
361 a
= stack
->stack
[stack
->sp
].array
= array_new();
362 return array_retrieve(a
, index
);