3 * Forth Inspired Command Language
4 * Author: John Sadler (john_sadler@alum.mit.edu)
6 * $Id: stack.c,v 1.11 2010/08/12 13:57:22 asau Exp $
9 * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
10 * All rights reserved.
12 * Get the latest Ficl release at http://ficl.sourceforge.net
14 * I am interested in hearing from anyone who uses Ficl. If you have
15 * a problem, a success story, a defect, an enhancement request, or
16 * if you would like to contribute to the Ficl release, please
17 * contact me by email at the address above.
19 * L I C E N S E and D I S C L A I M E R
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 #define STKDEPTH(s) (((s)->top - (s)->base) + 1)
48 * N O T E: Stack convention:
50 * THIS CHANGED IN FICL 4.0!
52 * top points to the *current* top data value
53 * push: increment top, store value at top
54 * pop: fetch value at top, decrement top
55 * Stack grows from low to high memory
59 * v m C h e c k S t a c k
60 * Check the parameter stack for underflow or overflow.
61 * size controls the type of check: if size is zero,
62 * the function checks the stack state for underflow and overflow.
63 * If size > 0, checks to see that the stack has room to push
64 * that many cells. If less than zero, checks to see that the
65 * stack has room to pop that many cells. If any test fails,
66 * the function throws (via vmThrow) a VM_ERREXIT exception.
69 ficlStackCheck(ficlStack
*stack
, int popCells
, int pushCells
)
72 int nFree
= stack
->size
- STKDEPTH(stack
);
74 if (popCells
> STKDEPTH(stack
))
75 ficlVmThrowError(stack
->vm
, "Error: %s stack underflow",
78 if (nFree
< pushCells
- popCells
)
79 ficlVmThrowError(stack
->vm
, "Error: %s stack overflow",
81 #else /* FICL_ROBUST >= 1 */
83 FICL_IGNORE(popCells
);
84 FICL_IGNORE(pushCells
);
85 #endif /* FICL_ROBUST >= 1 */
89 * s t a c k C r e a t e
93 ficlStackCreate(ficlVm
*vm
, char *name
, unsigned size
)
95 size_t totalSize
= sizeof (ficlStack
) + (size
* sizeof (ficlCell
));
96 ficlStack
*stack
= ficlMalloc(totalSize
);
98 FICL_VM_ASSERT(vm
, size
!= 0);
99 FICL_VM_ASSERT(vm
, stack
!= NULL
);
107 ficlStackReset(stack
);
112 * s t a c k D e l e t e
115 ficlStackDestroy(ficlStack
*stack
)
122 * s t a c k D e p t h
125 ficlStackDepth(ficlStack
*stack
)
127 return (STKDEPTH(stack
));
134 ficlStackDrop(ficlStack
*stack
, int n
)
136 FICL_VM_ASSERT(stack
->vm
, n
> 0);
141 * s t a c k F e t c h
144 ficlStackFetch(ficlStack
*stack
, int n
)
146 return (stack
->top
[-n
]);
150 ficlStackStore(ficlStack
*stack
, int n
, ficlCell c
)
156 * s t a c k G e t T o p
159 ficlStackGetTop(ficlStack
*stack
)
161 return (stack
->top
[0]);
167 * Link a frame using the stack's frame pointer. Allot space for
168 * size cells in the frame
174 ficlStackLink(ficlStack
*stack
, int size
)
176 ficlStackPushPointer(stack
, stack
->frame
);
177 stack
->frame
= stack
->top
+ 1;
182 * s t a c k U n l i n k
183 * Unink a stack frame previously created by stackLink
188 ficlStackUnlink(ficlStack
*stack
)
190 stack
->top
= stack
->frame
- 1;
191 stack
->frame
= ficlStackPopPointer(stack
);
193 #endif /* FICL_WANT_LOCALS */
199 ficlStackPick(ficlStack
*stack
, int n
)
201 ficlStackPush(stack
, ficlStackFetch(stack
, n
));
208 ficlStackPop(ficlStack
*stack
)
210 return (*stack
->top
--);
214 ficlStackPopPointer(ficlStack
*stack
)
216 return ((*stack
->top
--).p
);
220 ficlStackPopUnsigned(ficlStack
*stack
)
222 return ((*stack
->top
--).u
);
226 ficlStackPopInteger(ficlStack
*stack
)
228 return ((*stack
->top
--).i
);
232 ficlStackPop2Integer(ficlStack
*stack
)
235 ficlInteger high
= ficlStackPopInteger(stack
);
236 ficlInteger low
= ficlStackPopInteger(stack
);
237 FICL_2INTEGER_SET(high
, low
, ret
);
242 ficlStackPop2Unsigned(ficlStack
*stack
)
245 ficlUnsigned high
= ficlStackPopUnsigned(stack
);
246 ficlUnsigned low
= ficlStackPopUnsigned(stack
);
247 FICL_2UNSIGNED_SET(high
, low
, ret
);
251 #if (FICL_WANT_FLOAT)
253 ficlStackPopFloat(ficlStack
*stack
)
255 return ((*stack
->top
--).f
);
263 ficlStackPush(ficlStack
*stack
, ficlCell c
)
269 ficlStackPushPointer(ficlStack
*stack
, void *ptr
)
278 ficlStackPushInteger(ficlStack
*stack
, ficlInteger i
)
287 ficlStackPushUnsigned(ficlStack
*stack
, ficlUnsigned u
)
296 ficlStackPush2Unsigned(ficlStack
*stack
, ficl2Unsigned du
)
298 ficlStackPushUnsigned(stack
, FICL_2UNSIGNED_GET_LOW(du
));
299 ficlStackPushUnsigned(stack
, FICL_2UNSIGNED_GET_HIGH(du
));
303 ficlStackPush2Integer(ficlStack
*stack
, ficl2Integer di
)
306 FICL_2UNSIGNED_SET(FICL_2UNSIGNED_GET_HIGH(di
),
307 FICL_2UNSIGNED_GET_LOW(di
), du
);
308 ficlStackPush2Unsigned(stack
, du
);
311 #if (FICL_WANT_FLOAT)
313 ficlStackPushFloat(ficlStack
*stack
, ficlFloat f
)
323 * s t a c k R e s e t
326 ficlStackReset(ficlStack
*stack
)
328 stack
->top
= stack
->base
- 1;
333 * Roll nth stack entry to the top (counting from zero), if n is
334 * >= 0. Drop other entries as needed to fill the hole.
335 * If n < 0, roll top-of-stack to nth entry, pushing others
336 * upward as needed to fill the hole.
339 ficlStackRoll(ficlStack
*stack
, int n
)
347 cell
= stack
->top
- n
;
350 for (; n
> 0; --n
, cell
++) {
359 for (; n
< 0; ++n
, cell
--) {
368 * s t a c k S e t T o p
371 ficlStackSetTop(ficlStack
*stack
, ficlCell c
)
373 FICL_STACK_CHECK(stack
, 1, 1);
378 ficlStackWalk(ficlStack
*stack
, ficlStackWalkFunction callback
,
379 void *context
, ficlInteger bottomToTop
)
384 FICL_STACK_CHECK(stack
, 0, 0);
386 depth
= ficlStackDepth(stack
);
387 cell
= bottomToTop
? stack
->base
: stack
->top
;
388 for (i
= 0; i
< depth
; i
++) {
389 if (callback(context
, cell
) == FICL_FALSE
)
391 cell
+= bottomToTop
? 1 : -1;