1 /*******************************************************************
3 ** Forth Inspired Command Language
4 ** Author: John Sadler (john_sadler@alum.mit.edu)
5 ** Created: 16 Oct 1997
6 ** $Id: stack.c,v 1.10 2001/12/05 07:21:34 jsadler Exp $
7 *******************************************************************/
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
44 * $FreeBSD: src/sys/boot/ficl/stack.c,v 1.5 2002/04/09 17:45:11 dcs Exp $
45 * $DragonFly: src/sys/boot/ficl/stack.c,v 1.3 2003/11/10 06:08:33 dillon Exp $
55 #define STKDEPTH(s) ((s)->sp - (s)->base)
58 ** N O T E: Stack convention:
60 ** sp points to the first available cell
61 ** push: store value at sp, increment sp
62 ** pop: decrement sp, fetch value at sp
63 ** Stack grows from low to high memory
66 /*******************************************************************
67 v m C h e c k S t a c k
68 ** Check the parameter stack for underflow or overflow.
69 ** nCells controls the type of check: if nCells is zero,
70 ** the function checks the stack state for underflow and overflow.
71 ** If nCells > 0, checks to see that the stack has room to push
72 ** that many cells. If less than zero, checks to see that the
73 ** stack has room to pop that many cells. If any test fails,
74 ** the function throws (via vmThrow) a VM_ERREXIT exception.
75 *******************************************************************/
76 void vmCheckStack(FICL_VM
*pVM
, int popCells
, int pushCells
)
78 FICL_STACK
*pStack
= pVM
->pStack
;
79 int nFree
= pStack
->base
+ pStack
->nCells
- pStack
->sp
;
81 if (popCells
> STKDEPTH(pStack
))
83 vmThrowErr(pVM
, "Error: stack underflow");
86 if (nFree
< pushCells
- popCells
)
88 vmThrowErr(pVM
, "Error: stack overflow");
95 void vmCheckFStack(FICL_VM
*pVM
, int popCells
, int pushCells
)
97 FICL_STACK
*fStack
= pVM
->fStack
;
98 int nFree
= fStack
->base
+ fStack
->nCells
- fStack
->sp
;
100 if (popCells
> STKDEPTH(fStack
))
102 vmThrowErr(pVM
, "Error: float stack underflow");
105 if (nFree
< pushCells
- popCells
)
107 vmThrowErr(pVM
, "Error: float stack overflow");
112 /*******************************************************************
113 s t a c k C r e a t e
115 *******************************************************************/
117 FICL_STACK
*stackCreate(unsigned nCells
)
119 size_t size
= sizeof (FICL_STACK
) + nCells
* sizeof (CELL
);
120 FICL_STACK
*pStack
= ficlMalloc(size
);
123 assert (nCells
!= 0);
124 assert (pStack
!= NULL
);
127 pStack
->nCells
= nCells
;
128 pStack
->sp
= pStack
->base
;
129 pStack
->pFrame
= NULL
;
134 /*******************************************************************
135 s t a c k D e l e t e
137 *******************************************************************/
139 void stackDelete(FICL_STACK
*pStack
)
147 /*******************************************************************
150 *******************************************************************/
152 int stackDepth(FICL_STACK
*pStack
)
154 return STKDEPTH(pStack
);
157 /*******************************************************************
160 *******************************************************************/
162 void stackDrop(FICL_STACK
*pStack
, int n
)
172 /*******************************************************************
175 *******************************************************************/
177 CELL
stackFetch(FICL_STACK
*pStack
, int n
)
179 return pStack
->sp
[-n
-1];
182 void stackStore(FICL_STACK
*pStack
, int n
, CELL c
)
184 pStack
->sp
[-n
-1] = c
;
189 /*******************************************************************
190 s t a c k G e t T o p
192 *******************************************************************/
194 CELL
stackGetTop(FICL_STACK
*pStack
)
196 return pStack
->sp
[-1];
200 /*******************************************************************
202 ** Link a frame using the stack's frame pointer. Allot space for
203 ** nCells cells in the frame
207 *******************************************************************/
209 void stackLink(FICL_STACK
*pStack
, int nCells
)
211 stackPushPtr(pStack
, pStack
->pFrame
);
212 pStack
->pFrame
= pStack
->sp
;
213 pStack
->sp
+= nCells
;
218 /*******************************************************************
219 s t a c k U n l i n k
220 ** Unink a stack frame previously created by stackLink
223 *******************************************************************/
225 void stackUnlink(FICL_STACK
*pStack
)
227 pStack
->sp
= pStack
->pFrame
;
228 pStack
->pFrame
= stackPopPtr(pStack
);
233 /*******************************************************************
236 *******************************************************************/
238 void stackPick(FICL_STACK
*pStack
, int n
)
240 stackPush(pStack
, stackFetch(pStack
, n
));
245 /*******************************************************************
248 *******************************************************************/
250 CELL
stackPop(FICL_STACK
*pStack
)
252 return *--pStack
->sp
;
255 void *stackPopPtr(FICL_STACK
*pStack
)
257 return (*--pStack
->sp
).p
;
260 FICL_UNS
stackPopUNS(FICL_STACK
*pStack
)
262 return (*--pStack
->sp
).u
;
265 FICL_INT
stackPopINT(FICL_STACK
*pStack
)
267 return (*--pStack
->sp
).i
;
270 #if (FICL_WANT_FLOAT)
271 float stackPopFloat(FICL_STACK
*pStack
)
273 return (*(--pStack
->sp
)).f
;
277 /*******************************************************************
280 *******************************************************************/
282 void stackPush(FICL_STACK
*pStack
, CELL c
)
287 void stackPushPtr(FICL_STACK
*pStack
, void *ptr
)
289 *pStack
->sp
++ = LVALUEtoCELL(ptr
);
292 void stackPushUNS(FICL_STACK
*pStack
, FICL_UNS u
)
294 *pStack
->sp
++ = LVALUEtoCELL(u
);
297 void stackPushINT(FICL_STACK
*pStack
, FICL_INT i
)
299 *pStack
->sp
++ = LVALUEtoCELL(i
);
302 #if (FICL_WANT_FLOAT)
303 void stackPushFloat(FICL_STACK
*pStack
, FICL_FLOAT f
)
305 *pStack
->sp
++ = LVALUEtoCELL(f
);
309 /*******************************************************************
312 *******************************************************************/
314 void stackReset(FICL_STACK
*pStack
)
316 pStack
->sp
= pStack
->base
;
321 /*******************************************************************
323 ** Roll nth stack entry to the top (counting from zero), if n is
324 ** >= 0. Drop other entries as needed to fill the hole.
325 ** If n < 0, roll top-of-stack to nth entry, pushing others
326 ** upward as needed to fill the hole.
327 *******************************************************************/
329 void stackRoll(FICL_STACK
*pStack
, int n
)
338 pCell
= pStack
->sp
- n
- 1;
341 for (;n
> 0; --n
, pCell
++)
350 pCell
= pStack
->sp
- 1;
353 for (; n
< 0; ++n
, pCell
--)
364 /*******************************************************************
365 s t a c k S e t T o p
367 *******************************************************************/
369 void stackSetTop(FICL_STACK
*pStack
, CELL c
)