Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / boot / ficl / stack.c
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 /* $FreeBSD: src/sys/boot/ficl/stack.c,v 1.3 1999/09/29 04:43:07 dcs Exp $ */
10
11 #ifdef TESTMAIN
12 #include <stdlib.h>
13 #else
14 #include <stand.h>
15 #endif
16 #include "ficl.h"
17
18 #define STKDEPTH(s) ((s)->sp - (s)->base)
19
20 /*
21 ** N O T E: Stack convention:
22 **
23 ** sp points to the first available cell
24 ** push: store value at sp, increment sp
25 ** pop:  decrement sp, fetch value at sp
26 ** Stack grows from low to high memory
27 */
28
29 /*******************************************************************
30                     v m C h e c k S t a c k
31 ** Check the parameter stack for underflow or overflow.
32 ** nCells controls the type of check: if nCells is zero,
33 ** the function checks the stack state for underflow and overflow.
34 ** If nCells > 0, checks to see that the stack has room to push
35 ** that many cells. If less than zero, checks to see that the
36 ** stack has room to pop that many cells. If any test fails,
37 ** the function throws (via vmThrow) a VM_ERREXIT exception.
38 *******************************************************************/
39 void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)
40 {
41     FICL_STACK *pStack = pVM->pStack;
42     int nFree = pStack->base + pStack->nCells - pStack->sp;
43
44     if (popCells > STKDEPTH(pStack))
45     {
46         vmThrowErr(pVM, "Error: stack underflow");
47     }
48
49     if (nFree < pushCells - popCells)
50     {
51         vmThrowErr(pVM, "Error: stack overflow");
52     }
53
54     return;
55 }
56
57 /*******************************************************************
58                     s t a c k C r e a t e
59 ** 
60 *******************************************************************/
61
62 FICL_STACK *stackCreate(unsigned nCells)
63 {
64     size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);
65     FICL_STACK *pStack = ficlMalloc(size);
66
67 #if FICL_ROBUST
68     assert (nCells != 0);
69     assert (pStack != NULL);
70 #endif
71
72     pStack->nCells = nCells;
73     pStack->sp     = pStack->base;
74     pStack->pFrame = NULL;
75     return pStack;
76 }
77
78
79 /*******************************************************************
80                     s t a c k D e l e t e
81 ** 
82 *******************************************************************/
83
84 void 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
97 int 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
107 void 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
122 CELL stackFetch(FICL_STACK *pStack, int n)
123 {
124     return pStack->sp[-n-1];
125 }
126
127 void 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
139 CELL 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
154 void 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
170 void 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
183 void 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
195 CELL stackPop(FICL_STACK *pStack)
196 {
197     return *--pStack->sp;
198 }
199
200 void *stackPopPtr(FICL_STACK *pStack)
201 {
202     return (*--pStack->sp).p;
203 }
204
205 FICL_UNS stackPopUNS(FICL_STACK *pStack)
206 {
207     return (*--pStack->sp).u;
208 }
209
210 FICL_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
221 void stackPush(FICL_STACK *pStack, CELL c)
222 {
223     *pStack->sp++ = c;
224 }
225
226 void stackPushPtr(FICL_STACK *pStack, void *ptr)
227 {
228     *pStack->sp++ = LVALUEtoCELL(ptr);
229 }
230
231 void stackPushUNS(FICL_STACK *pStack, FICL_UNS u)
232 {
233     *pStack->sp++ = LVALUEtoCELL(u);
234 }
235
236 void 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
246 void 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
261 void 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
301 void stackSetTop(FICL_STACK *pStack, CELL c)
302 {
303     pStack->sp[-1] = c;
304     return;
305 }
306
307