stack.c revision 51786
155682Smarkm/*******************************************************************
255682Smarkm** s t a c k . c
355682Smarkm** Forth Inspired Command Language
455682Smarkm** Author: John Sadler (john_sadler@alum.mit.edu)
555682Smarkm** Created: 16 Oct 1997
655682Smarkm**
755682Smarkm*******************************************************************/
855682Smarkm
955682Smarkm/* $FreeBSD: head/sys/boot/ficl/stack.c 51786 1999-09-29 04:43:16Z dcs $ */
1055682Smarkm
1155682Smarkm#ifdef TESTMAIN
1255682Smarkm#include <stdlib.h>
1355682Smarkm#else
1455682Smarkm#include <stand.h>
1555682Smarkm#endif
1655682Smarkm#include "ficl.h"
1755682Smarkm
1855682Smarkm#define STKDEPTH(s) ((s)->sp - (s)->base)
1955682Smarkm
2055682Smarkm/*
2155682Smarkm** N O T E: Stack convention:
2255682Smarkm**
2355682Smarkm** sp points to the first available cell
2455682Smarkm** push: store value at sp, increment sp
2555682Smarkm** pop:  decrement sp, fetch value at sp
2655682Smarkm** Stack grows from low to high memory
2755682Smarkm*/
2855682Smarkm
2955682Smarkm/*******************************************************************
3055682Smarkm                    v m C h e c k S t a c k
3155682Smarkm** Check the parameter stack for underflow or overflow.
3255682Smarkm** nCells controls the type of check: if nCells is zero,
3355682Smarkm** the function checks the stack state for underflow and overflow.
3455682Smarkm** If nCells > 0, checks to see that the stack has room to push
3555682Smarkm** that many cells. If less than zero, checks to see that the
3655682Smarkm** stack has room to pop that many cells. If any test fails,
3755682Smarkm** the function throws (via vmThrow) a VM_ERREXIT exception.
3855682Smarkm*******************************************************************/
3955682Smarkmvoid vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)
4055682Smarkm{
4155682Smarkm    FICL_STACK *pStack = pVM->pStack;
4255682Smarkm    int nFree = pStack->base + pStack->nCells - pStack->sp;
4355682Smarkm
4455682Smarkm    if (popCells > STKDEPTH(pStack))
4555682Smarkm    {
4655682Smarkm        vmThrowErr(pVM, "Error: stack underflow");
4755682Smarkm    }
4855682Smarkm
4955682Smarkm    if (nFree < pushCells - popCells)
5055682Smarkm    {
5155682Smarkm        vmThrowErr(pVM, "Error: stack overflow");
5255682Smarkm    }
5355682Smarkm
5455682Smarkm    return;
5555682Smarkm}
5655682Smarkm
5755682Smarkm/*******************************************************************
5855682Smarkm                    s t a c k C r e a t e
5955682Smarkm**
6055682Smarkm*******************************************************************/
6155682Smarkm
6255682SmarkmFICL_STACK *stackCreate(unsigned nCells)
6355682Smarkm{
6455682Smarkm    size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);
6555682Smarkm    FICL_STACK *pStack = ficlMalloc(size);
6655682Smarkm
6755682Smarkm#if FICL_ROBUST
6855682Smarkm    assert (nCells != 0);
6955682Smarkm    assert (pStack != NULL);
7055682Smarkm#endif
7155682Smarkm
7255682Smarkm    pStack->nCells = nCells;
7355682Smarkm    pStack->sp     = pStack->base;
7455682Smarkm    pStack->pFrame = NULL;
7555682Smarkm    return pStack;
7655682Smarkm}
7755682Smarkm
7855682Smarkm
79/*******************************************************************
80                    s t a c k D e l e t e
81**
82*******************************************************************/
83
84void stackDelete(FICL_STACK *pStack)
85{
86    if (pStack)
87        ficlFree(pStack);
88    return;
89}
90
91
92/*******************************************************************
93                    s t a c k D e p t h
94**
95*******************************************************************/
96
97int stackDepth(FICL_STACK *pStack)
98{
99    return STKDEPTH(pStack);
100}
101
102/*******************************************************************
103                    s t a c k D r o p
104**
105*******************************************************************/
106
107void stackDrop(FICL_STACK *pStack, int n)
108{
109#if FICL_ROBUST
110    assert(n > 0);
111#endif
112    pStack->sp -= n;
113    return;
114}
115
116
117/*******************************************************************
118                    s t a c k F e t c h
119**
120*******************************************************************/
121
122CELL stackFetch(FICL_STACK *pStack, int n)
123{
124    return pStack->sp[-n-1];
125}
126
127void stackStore(FICL_STACK *pStack, int n, CELL c)
128{
129    pStack->sp[-n-1] = c;
130    return;
131}
132
133
134/*******************************************************************
135                    s t a c k G e t T o p
136**
137*******************************************************************/
138
139CELL stackGetTop(FICL_STACK *pStack)
140{
141    return pStack->sp[-1];
142}
143
144
145/*******************************************************************
146                    s t a c k L i n k
147** Link a frame using the stack's frame pointer. Allot space for
148** nCells cells in the frame
149** 1) Push pFrame
150** 2) pFrame = sp
151** 3) sp += nCells
152*******************************************************************/
153
154void stackLink(FICL_STACK *pStack, int nCells)
155{
156    stackPushPtr(pStack, pStack->pFrame);
157    pStack->pFrame = pStack->sp;
158    pStack->sp += nCells;
159    return;
160}
161
162
163/*******************************************************************
164                    s t a c k U n l i n k
165** Unink a stack frame previously created by stackLink
166** 1) sp = pFrame
167** 2) pFrame = pop()
168*******************************************************************/
169
170void stackUnlink(FICL_STACK *pStack)
171{
172    pStack->sp = pStack->pFrame;
173    pStack->pFrame = stackPopPtr(pStack);
174    return;
175}
176
177
178/*******************************************************************
179                    s t a c k P i c k
180**
181*******************************************************************/
182
183void stackPick(FICL_STACK *pStack, int n)
184{
185    stackPush(pStack, stackFetch(pStack, n));
186    return;
187}
188
189
190/*******************************************************************
191                    s t a c k P o p
192**
193*******************************************************************/
194
195CELL stackPop(FICL_STACK *pStack)
196{
197    return *--pStack->sp;
198}
199
200void *stackPopPtr(FICL_STACK *pStack)
201{
202    return (*--pStack->sp).p;
203}
204
205FICL_UNS stackPopUNS(FICL_STACK *pStack)
206{
207    return (*--pStack->sp).u;
208}
209
210FICL_INT stackPopINT(FICL_STACK *pStack)
211{
212    return (*--pStack->sp).i;
213}
214
215
216/*******************************************************************
217                    s t a c k P u s h
218**
219*******************************************************************/
220
221void stackPush(FICL_STACK *pStack, CELL c)
222{
223    *pStack->sp++ = c;
224}
225
226void stackPushPtr(FICL_STACK *pStack, void *ptr)
227{
228    *pStack->sp++ = LVALUEtoCELL(ptr);
229}
230
231void stackPushUNS(FICL_STACK *pStack, FICL_UNS u)
232{
233    *pStack->sp++ = LVALUEtoCELL(u);
234}
235
236void stackPushINT(FICL_STACK *pStack, FICL_INT i)
237{
238    *pStack->sp++ = LVALUEtoCELL(i);
239}
240
241/*******************************************************************
242                    s t a c k R e s e t
243**
244*******************************************************************/
245
246void stackReset(FICL_STACK *pStack)
247{
248    pStack->sp = pStack->base;
249    return;
250}
251
252
253/*******************************************************************
254                    s t a c k R o l l
255** Roll nth stack entry to the top (counting from zero), if n is
256** >= 0. Drop other entries as needed to fill the hole.
257** If n < 0, roll top-of-stack to nth entry, pushing others
258** upward as needed to fill the hole.
259*******************************************************************/
260
261void stackRoll(FICL_STACK *pStack, int n)
262{
263    CELL c;
264    CELL *pCell;
265
266    if (n == 0)
267        return;
268    else if (n > 0)
269    {
270        pCell = pStack->sp - n - 1;
271        c = *pCell;
272
273        for (;n > 0; --n, pCell++)
274        {
275            *pCell = pCell[1];
276        }
277
278        *pCell = c;
279    }
280    else
281    {
282        pCell = pStack->sp - 1;
283        c = *pCell;
284
285        for (; n < 0; ++n, pCell--)
286        {
287            *pCell = pCell[-1];
288        }
289
290        *pCell = c;
291    }
292    return;
293}
294
295
296/*******************************************************************
297                    s t a c k S e t T o p
298**
299*******************************************************************/
300
301void stackSetTop(FICL_STACK *pStack, CELL c)
302{
303    pStack->sp[-1] = c;
304    return;
305}
306
307
308