stack.c revision 40883
1/*******************************************************************
2** s t a c k . c
3** Forth Inspired Command Language
4** Author: John Sadler (john_sadler@alum.mit.edu)
5** Created: 16 Oct 1997
6**
7*******************************************************************/
8
9#ifdef TESTMAIN
10#include <stdlib.h>
11#else
12#include <stand.h>
13#endif
14#include "ficl.h"
15
16#define STKDEPTH(s) ((s)->sp - (s)->base)
17
18/*
19** N O T E: Stack convention:
20**
21** sp points to the first available cell
22** push: store value at sp, increment sp
23** pop:  decrement sp, fetch value at sp
24** Stack grows from low to high memory
25*/
26
27/*******************************************************************
28                    v m C h e c k S t a c k
29** Check the parameter stack for underflow or overflow.
30** nCells controls the type of check: if nCells is zero,
31** the function checks the stack state for underflow and overflow.
32** If nCells > 0, checks to see that the stack has room to push
33** that many cells. If less than zero, checks to see that the
34** stack has room to pop that many cells. If any test fails,
35** the function throws (via vmThrow) a VM_ERREXIT exception.
36*******************************************************************/
37void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)
38{
39    FICL_STACK *pStack = pVM->pStack;
40    int nFree = pStack->base + pStack->nCells - pStack->sp;
41
42    if (popCells > STKDEPTH(pStack))
43    {
44        vmThrowErr(pVM, "Error: stack underflow");
45    }
46
47    if (nFree < pushCells - popCells)
48    {
49        vmThrowErr(pVM, "Error: stack overflow");
50    }
51
52    return;
53}
54
55/*******************************************************************
56                    s t a c k C r e a t e
57**
58*******************************************************************/
59
60FICL_STACK *stackCreate(unsigned nCells)
61{
62    size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);
63    FICL_STACK *pStack = ficlMalloc(size);
64
65#if FICL_ROBUST
66    assert (nCells != 0);
67    assert (pStack != NULL);
68#endif
69
70    pStack->nCells = nCells;
71    pStack->sp     = pStack->base;
72    pStack->pFrame = NULL;
73    return pStack;
74}
75
76
77/*******************************************************************
78                    s t a c k D e l e t e
79**
80*******************************************************************/
81
82void stackDelete(FICL_STACK *pStack)
83{
84    if (pStack)
85        ficlFree(pStack);
86    return;
87}
88
89
90/*******************************************************************
91                    s t a c k D e p t h
92**
93*******************************************************************/
94
95int stackDepth(FICL_STACK *pStack)
96{
97    return STKDEPTH(pStack);
98}
99
100/*******************************************************************
101                    s t a c k D r o p
102**
103*******************************************************************/
104
105void stackDrop(FICL_STACK *pStack, int n)
106{
107#if FICL_ROBUST
108    assert(n > 0);
109#endif
110    pStack->sp -= n;
111    return;
112}
113
114
115/*******************************************************************
116                    s t a c k F e t c h
117**
118*******************************************************************/
119
120CELL stackFetch(FICL_STACK *pStack, int n)
121{
122    return pStack->sp[-n-1];
123}
124
125void stackStore(FICL_STACK *pStack, int n, CELL c)
126{
127    pStack->sp[-n-1] = c;
128    return;
129}
130
131
132/*******************************************************************
133                    s t a c k G e t T o p
134**
135*******************************************************************/
136
137CELL stackGetTop(FICL_STACK *pStack)
138{
139    return pStack->sp[-1];
140}
141
142
143/*******************************************************************
144                    s t a c k L i n k
145** Link a frame using the stack's frame pointer. Allot space for
146** nCells cells in the frame
147** 1) Push pFrame
148** 2) pFrame = sp
149** 3) sp += nCells
150*******************************************************************/
151
152void stackLink(FICL_STACK *pStack, int nCells)
153{
154    stackPushPtr(pStack, pStack->pFrame);
155    pStack->pFrame = pStack->sp;
156    pStack->sp += nCells;
157    return;
158}
159
160
161/*******************************************************************
162                    s t a c k U n l i n k
163** Unink a stack frame previously created by stackLink
164** 1) sp = pFrame
165** 2) pFrame = pop()
166*******************************************************************/
167
168void stackUnlink(FICL_STACK *pStack)
169{
170    pStack->sp = pStack->pFrame;
171    pStack->pFrame = stackPopPtr(pStack);
172    return;
173}
174
175
176/*******************************************************************
177                    s t a c k P i c k
178**
179*******************************************************************/
180
181void stackPick(FICL_STACK *pStack, int n)
182{
183    stackPush(pStack, stackFetch(pStack, n));
184    return;
185}
186
187
188/*******************************************************************
189                    s t a c k P o p
190**
191*******************************************************************/
192
193CELL stackPop(FICL_STACK *pStack)
194{
195    return *--pStack->sp;
196}
197
198void *stackPopPtr(FICL_STACK *pStack)
199{
200    return (*--pStack->sp).p;
201}
202
203UNS32 stackPopUNS32(FICL_STACK *pStack)
204{
205    return (*--pStack->sp).u;
206}
207
208INT32 stackPopINT32(FICL_STACK *pStack)
209{
210    return (*--pStack->sp).i;
211}
212
213
214/*******************************************************************
215                    s t a c k P u s h
216**
217*******************************************************************/
218
219void stackPush(FICL_STACK *pStack, CELL c)
220{
221    *pStack->sp++ = c;
222}
223
224void stackPushPtr(FICL_STACK *pStack, void *ptr)
225{
226    *pStack->sp++ = LVALUEtoCELL(ptr);
227}
228
229void stackPushUNS32(FICL_STACK *pStack, UNS32 u)
230{
231    *pStack->sp++ = LVALUEtoCELL(u);
232}
233
234void stackPushINT32(FICL_STACK *pStack, INT32 i)
235{
236    *pStack->sp++ = LVALUEtoCELL(i);
237}
238
239/*******************************************************************
240                    s t a c k R e s e t
241**
242*******************************************************************/
243
244void stackReset(FICL_STACK *pStack)
245{
246    pStack->sp = pStack->base;
247    return;
248}
249
250
251/*******************************************************************
252                    s t a c k R o l l
253** Roll nth stack entry to the top (counting from zero), if n is
254** >= 0. Drop other entries as needed to fill the hole.
255** If n < 0, roll top-of-stack to nth entry, pushing others
256** upward as needed to fill the hole.
257*******************************************************************/
258
259void stackRoll(FICL_STACK *pStack, int n)
260{
261    CELL c;
262    CELL *pCell;
263
264    if (n == 0)
265        return;
266    else if (n > 0)
267    {
268        pCell = pStack->sp - n - 1;
269        c = *pCell;
270
271        for (;n > 0; --n, pCell++)
272        {
273            *pCell = pCell[1];
274        }
275
276        *pCell = c;
277    }
278    else
279    {
280        pCell = pStack->sp - 1;
281        c = *pCell;
282
283        for (; n < 0; ++n, pCell--)
284        {
285            *pCell = pCell[-1];
286        }
287
288        *pCell = c;
289    }
290    return;
291}
292
293
294/*******************************************************************
295                    s t a c k S e t T o p
296**
297*******************************************************************/
298
299void stackSetTop(FICL_STACK *pStack, CELL c)
300{
301    pStack->sp[-1] = c;
302    return;
303}
304
305
306