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