1*ca987d46SWarner Losh /*******************************************************************
2*ca987d46SWarner Losh ** s t a c k . c
3*ca987d46SWarner Losh ** Forth Inspired Command Language
4*ca987d46SWarner Losh ** Author: John Sadler (john_sadler@alum.mit.edu)
5*ca987d46SWarner Losh ** Created: 16 Oct 1997
6*ca987d46SWarner Losh ** $Id: stack.c,v 1.10 2001/12/05 07:21:34 jsadler Exp $
7*ca987d46SWarner Losh *******************************************************************/
8*ca987d46SWarner Losh /*
9*ca987d46SWarner Losh ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
10*ca987d46SWarner Losh ** All rights reserved.
11*ca987d46SWarner Losh **
12*ca987d46SWarner Losh ** Get the latest Ficl release at http://ficl.sourceforge.net
13*ca987d46SWarner Losh **
14*ca987d46SWarner Losh ** I am interested in hearing from anyone who uses ficl. If you have
15*ca987d46SWarner Losh ** a problem, a success story, a defect, an enhancement request, or
16*ca987d46SWarner Losh ** if you would like to contribute to the ficl release, please
17*ca987d46SWarner Losh ** contact me by email at the address above.
18*ca987d46SWarner Losh **
19*ca987d46SWarner Losh ** L I C E N S E and D I S C L A I M E R
20*ca987d46SWarner Losh **
21*ca987d46SWarner Losh ** Redistribution and use in source and binary forms, with or without
22*ca987d46SWarner Losh ** modification, are permitted provided that the following conditions
23*ca987d46SWarner Losh ** are met:
24*ca987d46SWarner Losh ** 1. Redistributions of source code must retain the above copyright
25*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer.
26*ca987d46SWarner Losh ** 2. Redistributions in binary form must reproduce the above copyright
27*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer in the
28*ca987d46SWarner Losh ** documentation and/or other materials provided with the distribution.
29*ca987d46SWarner Losh **
30*ca987d46SWarner Losh ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
31*ca987d46SWarner Losh ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32*ca987d46SWarner Losh ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33*ca987d46SWarner Losh ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
34*ca987d46SWarner Losh ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35*ca987d46SWarner Losh ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36*ca987d46SWarner Losh ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37*ca987d46SWarner Losh ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38*ca987d46SWarner Losh ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39*ca987d46SWarner Losh ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40*ca987d46SWarner Losh ** SUCH DAMAGE.
41*ca987d46SWarner Losh */
42*ca987d46SWarner Losh
43*ca987d46SWarner Losh
44*ca987d46SWarner Losh #ifdef TESTMAIN
45*ca987d46SWarner Losh #include <stdlib.h>
46*ca987d46SWarner Losh #else
47*ca987d46SWarner Losh #include <stand.h>
48*ca987d46SWarner Losh #endif
49*ca987d46SWarner Losh #include "ficl.h"
50*ca987d46SWarner Losh
51*ca987d46SWarner Losh #define STKDEPTH(s) ((s)->sp - (s)->base)
52*ca987d46SWarner Losh
53*ca987d46SWarner Losh /*
54*ca987d46SWarner Losh ** N O T E: Stack convention:
55*ca987d46SWarner Losh **
56*ca987d46SWarner Losh ** sp points to the first available cell
57*ca987d46SWarner Losh ** push: store value at sp, increment sp
58*ca987d46SWarner Losh ** pop: decrement sp, fetch value at sp
59*ca987d46SWarner Losh ** Stack grows from low to high memory
60*ca987d46SWarner Losh */
61*ca987d46SWarner Losh
62*ca987d46SWarner Losh /*******************************************************************
63*ca987d46SWarner Losh v m C h e c k S t a c k
64*ca987d46SWarner Losh ** Check the parameter stack for underflow or overflow.
65*ca987d46SWarner Losh ** nCells controls the type of check: if nCells is zero,
66*ca987d46SWarner Losh ** the function checks the stack state for underflow and overflow.
67*ca987d46SWarner Losh ** If nCells > 0, checks to see that the stack has room to push
68*ca987d46SWarner Losh ** that many cells. If less than zero, checks to see that the
69*ca987d46SWarner Losh ** stack has room to pop that many cells. If any test fails,
70*ca987d46SWarner Losh ** the function throws (via vmThrow) a VM_ERREXIT exception.
71*ca987d46SWarner Losh *******************************************************************/
vmCheckStack(FICL_VM * pVM,int popCells,int pushCells)72*ca987d46SWarner Losh void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)
73*ca987d46SWarner Losh {
74*ca987d46SWarner Losh FICL_STACK *pStack = pVM->pStack;
75*ca987d46SWarner Losh int nFree = pStack->base + pStack->nCells - pStack->sp;
76*ca987d46SWarner Losh
77*ca987d46SWarner Losh if (popCells > STKDEPTH(pStack))
78*ca987d46SWarner Losh {
79*ca987d46SWarner Losh vmThrowErr(pVM, "Error: stack underflow");
80*ca987d46SWarner Losh }
81*ca987d46SWarner Losh
82*ca987d46SWarner Losh if (nFree < pushCells - popCells)
83*ca987d46SWarner Losh {
84*ca987d46SWarner Losh vmThrowErr(pVM, "Error: stack overflow");
85*ca987d46SWarner Losh }
86*ca987d46SWarner Losh
87*ca987d46SWarner Losh return;
88*ca987d46SWarner Losh }
89*ca987d46SWarner Losh
90*ca987d46SWarner Losh #if FICL_WANT_FLOAT
vmCheckFStack(FICL_VM * pVM,int popCells,int pushCells)91*ca987d46SWarner Losh void vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells)
92*ca987d46SWarner Losh {
93*ca987d46SWarner Losh FICL_STACK *fStack = pVM->fStack;
94*ca987d46SWarner Losh int nFree = fStack->base + fStack->nCells - fStack->sp;
95*ca987d46SWarner Losh
96*ca987d46SWarner Losh if (popCells > STKDEPTH(fStack))
97*ca987d46SWarner Losh {
98*ca987d46SWarner Losh vmThrowErr(pVM, "Error: float stack underflow");
99*ca987d46SWarner Losh }
100*ca987d46SWarner Losh
101*ca987d46SWarner Losh if (nFree < pushCells - popCells)
102*ca987d46SWarner Losh {
103*ca987d46SWarner Losh vmThrowErr(pVM, "Error: float stack overflow");
104*ca987d46SWarner Losh }
105*ca987d46SWarner Losh }
106*ca987d46SWarner Losh #endif
107*ca987d46SWarner Losh
108*ca987d46SWarner Losh /*******************************************************************
109*ca987d46SWarner Losh s t a c k C r e a t e
110*ca987d46SWarner Losh **
111*ca987d46SWarner Losh *******************************************************************/
112*ca987d46SWarner Losh
stackCreate(unsigned nCells)113*ca987d46SWarner Losh FICL_STACK *stackCreate(unsigned nCells)
114*ca987d46SWarner Losh {
115*ca987d46SWarner Losh size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);
116*ca987d46SWarner Losh FICL_STACK *pStack = ficlMalloc(size);
117*ca987d46SWarner Losh
118*ca987d46SWarner Losh #if FICL_ROBUST
119*ca987d46SWarner Losh assert (nCells != 0);
120*ca987d46SWarner Losh assert (pStack != NULL);
121*ca987d46SWarner Losh #endif
122*ca987d46SWarner Losh
123*ca987d46SWarner Losh pStack->nCells = nCells;
124*ca987d46SWarner Losh pStack->sp = pStack->base;
125*ca987d46SWarner Losh pStack->pFrame = NULL;
126*ca987d46SWarner Losh return pStack;
127*ca987d46SWarner Losh }
128*ca987d46SWarner Losh
129*ca987d46SWarner Losh
130*ca987d46SWarner Losh /*******************************************************************
131*ca987d46SWarner Losh s t a c k D e l e t e
132*ca987d46SWarner Losh **
133*ca987d46SWarner Losh *******************************************************************/
134*ca987d46SWarner Losh
stackDelete(FICL_STACK * pStack)135*ca987d46SWarner Losh void stackDelete(FICL_STACK *pStack)
136*ca987d46SWarner Losh {
137*ca987d46SWarner Losh if (pStack)
138*ca987d46SWarner Losh ficlFree(pStack);
139*ca987d46SWarner Losh return;
140*ca987d46SWarner Losh }
141*ca987d46SWarner Losh
142*ca987d46SWarner Losh
143*ca987d46SWarner Losh /*******************************************************************
144*ca987d46SWarner Losh s t a c k D e p t h
145*ca987d46SWarner Losh **
146*ca987d46SWarner Losh *******************************************************************/
147*ca987d46SWarner Losh
stackDepth(FICL_STACK * pStack)148*ca987d46SWarner Losh int stackDepth(FICL_STACK *pStack)
149*ca987d46SWarner Losh {
150*ca987d46SWarner Losh return STKDEPTH(pStack);
151*ca987d46SWarner Losh }
152*ca987d46SWarner Losh
153*ca987d46SWarner Losh /*******************************************************************
154*ca987d46SWarner Losh s t a c k D r o p
155*ca987d46SWarner Losh **
156*ca987d46SWarner Losh *******************************************************************/
157*ca987d46SWarner Losh
stackDrop(FICL_STACK * pStack,int n)158*ca987d46SWarner Losh void stackDrop(FICL_STACK *pStack, int n)
159*ca987d46SWarner Losh {
160*ca987d46SWarner Losh #if FICL_ROBUST
161*ca987d46SWarner Losh assert(n > 0);
162*ca987d46SWarner Losh #endif
163*ca987d46SWarner Losh pStack->sp -= n;
164*ca987d46SWarner Losh return;
165*ca987d46SWarner Losh }
166*ca987d46SWarner Losh
167*ca987d46SWarner Losh
168*ca987d46SWarner Losh /*******************************************************************
169*ca987d46SWarner Losh s t a c k F e t c h
170*ca987d46SWarner Losh **
171*ca987d46SWarner Losh *******************************************************************/
172*ca987d46SWarner Losh
stackFetch(FICL_STACK * pStack,int n)173*ca987d46SWarner Losh CELL stackFetch(FICL_STACK *pStack, int n)
174*ca987d46SWarner Losh {
175*ca987d46SWarner Losh return pStack->sp[-n-1];
176*ca987d46SWarner Losh }
177*ca987d46SWarner Losh
stackStore(FICL_STACK * pStack,int n,CELL c)178*ca987d46SWarner Losh void stackStore(FICL_STACK *pStack, int n, CELL c)
179*ca987d46SWarner Losh {
180*ca987d46SWarner Losh pStack->sp[-n-1] = c;
181*ca987d46SWarner Losh return;
182*ca987d46SWarner Losh }
183*ca987d46SWarner Losh
184*ca987d46SWarner Losh
185*ca987d46SWarner Losh /*******************************************************************
186*ca987d46SWarner Losh s t a c k G e t T o p
187*ca987d46SWarner Losh **
188*ca987d46SWarner Losh *******************************************************************/
189*ca987d46SWarner Losh
stackGetTop(FICL_STACK * pStack)190*ca987d46SWarner Losh CELL stackGetTop(FICL_STACK *pStack)
191*ca987d46SWarner Losh {
192*ca987d46SWarner Losh return pStack->sp[-1];
193*ca987d46SWarner Losh }
194*ca987d46SWarner Losh
195*ca987d46SWarner Losh
196*ca987d46SWarner Losh /*******************************************************************
197*ca987d46SWarner Losh s t a c k L i n k
198*ca987d46SWarner Losh ** Link a frame using the stack's frame pointer. Allot space for
199*ca987d46SWarner Losh ** nCells cells in the frame
200*ca987d46SWarner Losh ** 1) Push pFrame
201*ca987d46SWarner Losh ** 2) pFrame = sp
202*ca987d46SWarner Losh ** 3) sp += nCells
203*ca987d46SWarner Losh *******************************************************************/
204*ca987d46SWarner Losh
stackLink(FICL_STACK * pStack,int nCells)205*ca987d46SWarner Losh void stackLink(FICL_STACK *pStack, int nCells)
206*ca987d46SWarner Losh {
207*ca987d46SWarner Losh stackPushPtr(pStack, pStack->pFrame);
208*ca987d46SWarner Losh pStack->pFrame = pStack->sp;
209*ca987d46SWarner Losh pStack->sp += nCells;
210*ca987d46SWarner Losh return;
211*ca987d46SWarner Losh }
212*ca987d46SWarner Losh
213*ca987d46SWarner Losh
214*ca987d46SWarner Losh /*******************************************************************
215*ca987d46SWarner Losh s t a c k U n l i n k
216*ca987d46SWarner Losh ** Unink a stack frame previously created by stackLink
217*ca987d46SWarner Losh ** 1) sp = pFrame
218*ca987d46SWarner Losh ** 2) pFrame = pop()
219*ca987d46SWarner Losh *******************************************************************/
220*ca987d46SWarner Losh
stackUnlink(FICL_STACK * pStack)221*ca987d46SWarner Losh void stackUnlink(FICL_STACK *pStack)
222*ca987d46SWarner Losh {
223*ca987d46SWarner Losh pStack->sp = pStack->pFrame;
224*ca987d46SWarner Losh pStack->pFrame = stackPopPtr(pStack);
225*ca987d46SWarner Losh return;
226*ca987d46SWarner Losh }
227*ca987d46SWarner Losh
228*ca987d46SWarner Losh
229*ca987d46SWarner Losh /*******************************************************************
230*ca987d46SWarner Losh s t a c k P i c k
231*ca987d46SWarner Losh **
232*ca987d46SWarner Losh *******************************************************************/
233*ca987d46SWarner Losh
stackPick(FICL_STACK * pStack,int n)234*ca987d46SWarner Losh void stackPick(FICL_STACK *pStack, int n)
235*ca987d46SWarner Losh {
236*ca987d46SWarner Losh stackPush(pStack, stackFetch(pStack, n));
237*ca987d46SWarner Losh return;
238*ca987d46SWarner Losh }
239*ca987d46SWarner Losh
240*ca987d46SWarner Losh
241*ca987d46SWarner Losh /*******************************************************************
242*ca987d46SWarner Losh s t a c k P o p
243*ca987d46SWarner Losh **
244*ca987d46SWarner Losh *******************************************************************/
245*ca987d46SWarner Losh
stackPop(FICL_STACK * pStack)246*ca987d46SWarner Losh CELL stackPop(FICL_STACK *pStack)
247*ca987d46SWarner Losh {
248*ca987d46SWarner Losh return *--pStack->sp;
249*ca987d46SWarner Losh }
250*ca987d46SWarner Losh
stackPopPtr(FICL_STACK * pStack)251*ca987d46SWarner Losh void *stackPopPtr(FICL_STACK *pStack)
252*ca987d46SWarner Losh {
253*ca987d46SWarner Losh return (*--pStack->sp).p;
254*ca987d46SWarner Losh }
255*ca987d46SWarner Losh
stackPopUNS(FICL_STACK * pStack)256*ca987d46SWarner Losh FICL_UNS stackPopUNS(FICL_STACK *pStack)
257*ca987d46SWarner Losh {
258*ca987d46SWarner Losh return (*--pStack->sp).u;
259*ca987d46SWarner Losh }
260*ca987d46SWarner Losh
stackPopINT(FICL_STACK * pStack)261*ca987d46SWarner Losh FICL_INT stackPopINT(FICL_STACK *pStack)
262*ca987d46SWarner Losh {
263*ca987d46SWarner Losh return (*--pStack->sp).i;
264*ca987d46SWarner Losh }
265*ca987d46SWarner Losh
266*ca987d46SWarner Losh #if (FICL_WANT_FLOAT)
stackPopFloat(FICL_STACK * pStack)267*ca987d46SWarner Losh float stackPopFloat(FICL_STACK *pStack)
268*ca987d46SWarner Losh {
269*ca987d46SWarner Losh return (*(--pStack->sp)).f;
270*ca987d46SWarner Losh }
271*ca987d46SWarner Losh #endif
272*ca987d46SWarner Losh
273*ca987d46SWarner Losh /*******************************************************************
274*ca987d46SWarner Losh s t a c k P u s h
275*ca987d46SWarner Losh **
276*ca987d46SWarner Losh *******************************************************************/
277*ca987d46SWarner Losh
stackPush(FICL_STACK * pStack,CELL c)278*ca987d46SWarner Losh void stackPush(FICL_STACK *pStack, CELL c)
279*ca987d46SWarner Losh {
280*ca987d46SWarner Losh *pStack->sp++ = c;
281*ca987d46SWarner Losh }
282*ca987d46SWarner Losh
stackPushPtr(FICL_STACK * pStack,void * ptr)283*ca987d46SWarner Losh void stackPushPtr(FICL_STACK *pStack, void *ptr)
284*ca987d46SWarner Losh {
285*ca987d46SWarner Losh *pStack->sp++ = LVALUEtoCELL(ptr);
286*ca987d46SWarner Losh }
287*ca987d46SWarner Losh
stackPushUNS(FICL_STACK * pStack,FICL_UNS u)288*ca987d46SWarner Losh void stackPushUNS(FICL_STACK *pStack, FICL_UNS u)
289*ca987d46SWarner Losh {
290*ca987d46SWarner Losh *pStack->sp++ = LVALUEtoCELL(u);
291*ca987d46SWarner Losh }
292*ca987d46SWarner Losh
stackPushINT(FICL_STACK * pStack,FICL_INT i)293*ca987d46SWarner Losh void stackPushINT(FICL_STACK *pStack, FICL_INT i)
294*ca987d46SWarner Losh {
295*ca987d46SWarner Losh *pStack->sp++ = LVALUEtoCELL(i);
296*ca987d46SWarner Losh }
297*ca987d46SWarner Losh
298*ca987d46SWarner Losh #if (FICL_WANT_FLOAT)
stackPushFloat(FICL_STACK * pStack,FICL_FLOAT f)299*ca987d46SWarner Losh void stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f)
300*ca987d46SWarner Losh {
301*ca987d46SWarner Losh *pStack->sp++ = LVALUEtoCELL(f);
302*ca987d46SWarner Losh }
303*ca987d46SWarner Losh #endif
304*ca987d46SWarner Losh
305*ca987d46SWarner Losh /*******************************************************************
306*ca987d46SWarner Losh s t a c k R e s e t
307*ca987d46SWarner Losh **
308*ca987d46SWarner Losh *******************************************************************/
309*ca987d46SWarner Losh
stackReset(FICL_STACK * pStack)310*ca987d46SWarner Losh void stackReset(FICL_STACK *pStack)
311*ca987d46SWarner Losh {
312*ca987d46SWarner Losh pStack->sp = pStack->base;
313*ca987d46SWarner Losh return;
314*ca987d46SWarner Losh }
315*ca987d46SWarner Losh
316*ca987d46SWarner Losh
317*ca987d46SWarner Losh /*******************************************************************
318*ca987d46SWarner Losh s t a c k R o l l
319*ca987d46SWarner Losh ** Roll nth stack entry to the top (counting from zero), if n is
320*ca987d46SWarner Losh ** >= 0. Drop other entries as needed to fill the hole.
321*ca987d46SWarner Losh ** If n < 0, roll top-of-stack to nth entry, pushing others
322*ca987d46SWarner Losh ** upward as needed to fill the hole.
323*ca987d46SWarner Losh *******************************************************************/
324*ca987d46SWarner Losh
stackRoll(FICL_STACK * pStack,int n)325*ca987d46SWarner Losh void stackRoll(FICL_STACK *pStack, int n)
326*ca987d46SWarner Losh {
327*ca987d46SWarner Losh CELL c;
328*ca987d46SWarner Losh CELL *pCell;
329*ca987d46SWarner Losh
330*ca987d46SWarner Losh if (n == 0)
331*ca987d46SWarner Losh return;
332*ca987d46SWarner Losh else if (n > 0)
333*ca987d46SWarner Losh {
334*ca987d46SWarner Losh pCell = pStack->sp - n - 1;
335*ca987d46SWarner Losh c = *pCell;
336*ca987d46SWarner Losh
337*ca987d46SWarner Losh for (;n > 0; --n, pCell++)
338*ca987d46SWarner Losh {
339*ca987d46SWarner Losh *pCell = pCell[1];
340*ca987d46SWarner Losh }
341*ca987d46SWarner Losh
342*ca987d46SWarner Losh *pCell = c;
343*ca987d46SWarner Losh }
344*ca987d46SWarner Losh else
345*ca987d46SWarner Losh {
346*ca987d46SWarner Losh pCell = pStack->sp - 1;
347*ca987d46SWarner Losh c = *pCell;
348*ca987d46SWarner Losh
349*ca987d46SWarner Losh for (; n < 0; ++n, pCell--)
350*ca987d46SWarner Losh {
351*ca987d46SWarner Losh *pCell = pCell[-1];
352*ca987d46SWarner Losh }
353*ca987d46SWarner Losh
354*ca987d46SWarner Losh *pCell = c;
355*ca987d46SWarner Losh }
356*ca987d46SWarner Losh return;
357*ca987d46SWarner Losh }
358*ca987d46SWarner Losh
359*ca987d46SWarner Losh
360*ca987d46SWarner Losh /*******************************************************************
361*ca987d46SWarner Losh s t a c k S e t T o p
362*ca987d46SWarner Losh **
363*ca987d46SWarner Losh *******************************************************************/
364*ca987d46SWarner Losh
stackSetTop(FICL_STACK * pStack,CELL c)365*ca987d46SWarner Losh void stackSetTop(FICL_STACK *pStack, CELL c)
366*ca987d46SWarner Losh {
367*ca987d46SWarner Losh pStack->sp[-1] = c;
368*ca987d46SWarner Losh return;
369*ca987d46SWarner Losh }
370*ca987d46SWarner Losh
371*ca987d46SWarner Losh
372