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
51 #define STKDEPTH(s) ((s)->sp - (s)->base)
54 ** N O T E: Stack convention:
56 ** sp points to the first available cell
57 ** push: store value at sp, increment sp
58 ** pop: decrement sp, fetch value at sp
59 ** Stack grows from low to high memory
62 /*******************************************************************
63 v m C h e c k S t a c k
64 ** Check the parameter stack for underflow or overflow.
65 ** nCells controls the type of check: if nCells is zero,
66 ** the function checks the stack state for underflow and overflow.
67 ** If nCells > 0, checks to see that the stack has room to push
68 ** that many cells. If less than zero, checks to see that the
69 ** stack has room to pop that many cells. If any test fails,
70 ** the function throws (via vmThrow) a VM_ERREXIT exception.
71 *******************************************************************/
72 void vmCheckStack(FICL_VM
*pVM
, int popCells
, int pushCells
)
74 FICL_STACK
*pStack
= pVM
->pStack
;
75 int nFree
= pStack
->base
+ pStack
->nCells
- pStack
->sp
;
77 if (popCells
> STKDEPTH(pStack
))
79 vmThrowErr(pVM
, "Error: stack underflow");
82 if (nFree
< pushCells
- popCells
)
84 vmThrowErr(pVM
, "Error: stack overflow");
91 void vmCheckFStack(FICL_VM
*pVM
, int popCells
, int pushCells
)
93 FICL_STACK
*fStack
= pVM
->fStack
;
94 int nFree
= fStack
->base
+ fStack
->nCells
- fStack
->sp
;
96 if (popCells
> STKDEPTH(fStack
))
98 vmThrowErr(pVM
, "Error: float stack underflow");
101 if (nFree
< pushCells
- popCells
)
103 vmThrowErr(pVM
, "Error: float stack overflow");
108 /*******************************************************************
109 s t a c k C r e a t e
111 *******************************************************************/
113 FICL_STACK
*stackCreate(unsigned nCells
)
115 size_t size
= sizeof (FICL_STACK
) + nCells
* sizeof (CELL
);
116 FICL_STACK
*pStack
= ficlMalloc(size
);
119 assert (nCells
!= 0);
120 assert (pStack
!= NULL
);
123 pStack
->nCells
= nCells
;
124 pStack
->sp
= pStack
->base
;
125 pStack
->pFrame
= NULL
;
130 /*******************************************************************
131 s t a c k D e l e t e
133 *******************************************************************/
135 void stackDelete(FICL_STACK
*pStack
)
143 /*******************************************************************
146 *******************************************************************/
148 int stackDepth(FICL_STACK
*pStack
)
150 return STKDEPTH(pStack
);
153 /*******************************************************************
156 *******************************************************************/
158 void stackDrop(FICL_STACK
*pStack
, int n
)
168 /*******************************************************************
171 *******************************************************************/
173 CELL
stackFetch(FICL_STACK
*pStack
, int n
)
175 return pStack
->sp
[-n
-1];
178 void stackStore(FICL_STACK
*pStack
, int n
, CELL c
)
180 pStack
->sp
[-n
-1] = c
;
185 /*******************************************************************
186 s t a c k G e t T o p
188 *******************************************************************/
190 CELL
stackGetTop(FICL_STACK
*pStack
)
192 return pStack
->sp
[-1];
196 /*******************************************************************
198 ** Link a frame using the stack's frame pointer. Allot space for
199 ** nCells cells in the frame
203 *******************************************************************/
205 void stackLink(FICL_STACK
*pStack
, int nCells
)
207 stackPushPtr(pStack
, pStack
->pFrame
);
208 pStack
->pFrame
= pStack
->sp
;
209 pStack
->sp
+= nCells
;
214 /*******************************************************************
215 s t a c k U n l i n k
216 ** Unink a stack frame previously created by stackLink
219 *******************************************************************/
221 void stackUnlink(FICL_STACK
*pStack
)
223 pStack
->sp
= pStack
->pFrame
;
224 pStack
->pFrame
= stackPopPtr(pStack
);
229 /*******************************************************************
232 *******************************************************************/
234 void stackPick(FICL_STACK
*pStack
, int n
)
236 stackPush(pStack
, stackFetch(pStack
, n
));
241 /*******************************************************************
244 *******************************************************************/
246 CELL
stackPop(FICL_STACK
*pStack
)
248 return *--pStack
->sp
;
251 void *stackPopPtr(FICL_STACK
*pStack
)
253 return (*--pStack
->sp
).p
;
256 FICL_UNS
stackPopUNS(FICL_STACK
*pStack
)
258 return (*--pStack
->sp
).u
;
261 FICL_INT
stackPopINT(FICL_STACK
*pStack
)
263 return (*--pStack
->sp
).i
;
266 #if (FICL_WANT_FLOAT)
267 float stackPopFloat(FICL_STACK
*pStack
)
269 return (*(--pStack
->sp
)).f
;
273 /*******************************************************************
276 *******************************************************************/
278 void stackPush(FICL_STACK
*pStack
, CELL c
)
283 void stackPushPtr(FICL_STACK
*pStack
, void *ptr
)
285 *pStack
->sp
++ = LVALUEtoCELL(ptr
);
288 void stackPushUNS(FICL_STACK
*pStack
, FICL_UNS u
)
290 *pStack
->sp
++ = LVALUEtoCELL(u
);
293 void stackPushINT(FICL_STACK
*pStack
, FICL_INT i
)
295 *pStack
->sp
++ = LVALUEtoCELL(i
);
298 #if (FICL_WANT_FLOAT)
299 void stackPushFloat(FICL_STACK
*pStack
, FICL_FLOAT f
)
301 *pStack
->sp
++ = LVALUEtoCELL(f
);
305 /*******************************************************************
308 *******************************************************************/
310 void stackReset(FICL_STACK
*pStack
)
312 pStack
->sp
= pStack
->base
;
317 /*******************************************************************
319 ** Roll nth stack entry to the top (counting from zero), if n is
320 ** >= 0. Drop other entries as needed to fill the hole.
321 ** If n < 0, roll top-of-stack to nth entry, pushing others
322 ** upward as needed to fill the hole.
323 *******************************************************************/
325 void stackRoll(FICL_STACK
*pStack
, int n
)
334 pCell
= pStack
->sp
- n
- 1;
337 for (;n
> 0; --n
, pCell
++)
346 pCell
= pStack
->sp
- 1;
349 for (; n
< 0; ++n
, pCell
--)
360 /*******************************************************************
361 s t a c k S e t T o p
363 *******************************************************************/
365 void stackSetTop(FICL_STACK
*pStack
, CELL c
)