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