stack.c revision 76116
140843Smsmith/*******************************************************************
240843Smsmith** s t a c k . c
340843Smsmith** Forth Inspired Command Language
440843Smsmith** Author: John Sadler (john_sadler@alum.mit.edu)
540843Smsmith** Created: 16 Oct 1997
676116Sdcs** $Id: stack.c,v 1.5 2001-04-26 21:41:29-07 jsadler Exp jsadler $
776116Sdcs*******************************************************************/
876116Sdcs/*
976116Sdcs** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
1076116Sdcs** All rights reserved.
1176116Sdcs**
1276116Sdcs** Get the latest Ficl release at http://ficl.sourceforge.net
1376116Sdcs**
1476116Sdcs** L I C E N S E  and  D I S C L A I M E R
1540843Smsmith**
1676116Sdcs** Redistribution and use in source and binary forms, with or without
1776116Sdcs** modification, are permitted provided that the following conditions
1876116Sdcs** are met:
1976116Sdcs** 1. Redistributions of source code must retain the above copyright
2076116Sdcs**    notice, this list of conditions and the following disclaimer.
2176116Sdcs** 2. Redistributions in binary form must reproduce the above copyright
2276116Sdcs**    notice, this list of conditions and the following disclaimer in the
2376116Sdcs**    documentation and/or other materials provided with the distribution.
2476116Sdcs**
2576116Sdcs** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2676116Sdcs** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2776116Sdcs** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2876116Sdcs** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2976116Sdcs** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3076116Sdcs** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3176116Sdcs** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3276116Sdcs** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3376116Sdcs** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3476116Sdcs** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3576116Sdcs** SUCH DAMAGE.
3676116Sdcs**
3776116Sdcs** I am interested in hearing from anyone who uses ficl. If you have
3876116Sdcs** a problem, a success story, a defect, an enhancement request, or
3976116Sdcs** if you would like to contribute to the ficl release, please send
4076116Sdcs** contact me by email at the address above.
4176116Sdcs**
4276116Sdcs** $Id: stack.c,v 1.5 2001-04-26 21:41:29-07 jsadler Exp jsadler $
4376116Sdcs*/
4440883Smsmith
4551786Sdcs/* $FreeBSD: head/sys/boot/ficl/stack.c 76116 2001-04-29 02:36:36Z dcs $ */
4651786Sdcs
4740883Smsmith#ifdef TESTMAIN
4840843Smsmith#include <stdlib.h>
4940883Smsmith#else
5040883Smsmith#include <stand.h>
5140883Smsmith#endif
5240843Smsmith#include "ficl.h"
5340843Smsmith
5440843Smsmith#define STKDEPTH(s) ((s)->sp - (s)->base)
5540843Smsmith
5640843Smsmith/*
5740843Smsmith** N O T E: Stack convention:
5840843Smsmith**
5940843Smsmith** sp points to the first available cell
6040843Smsmith** push: store value at sp, increment sp
6140843Smsmith** pop:  decrement sp, fetch value at sp
6240843Smsmith** Stack grows from low to high memory
6340843Smsmith*/
6440843Smsmith
6540843Smsmith/*******************************************************************
6640843Smsmith                    v m C h e c k S t a c k
6740843Smsmith** Check the parameter stack for underflow or overflow.
6840843Smsmith** nCells controls the type of check: if nCells is zero,
6940843Smsmith** the function checks the stack state for underflow and overflow.
7040843Smsmith** If nCells > 0, checks to see that the stack has room to push
7140843Smsmith** that many cells. If less than zero, checks to see that the
7240843Smsmith** stack has room to pop that many cells. If any test fails,
7340843Smsmith** the function throws (via vmThrow) a VM_ERREXIT exception.
7440843Smsmith*******************************************************************/
7540843Smsmithvoid vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)
7640843Smsmith{
7740843Smsmith    FICL_STACK *pStack = pVM->pStack;
7840843Smsmith    int nFree = pStack->base + pStack->nCells - pStack->sp;
7940843Smsmith
8040843Smsmith    if (popCells > STKDEPTH(pStack))
8140843Smsmith    {
8240843Smsmith        vmThrowErr(pVM, "Error: stack underflow");
8340843Smsmith    }
8440843Smsmith
8540843Smsmith    if (nFree < pushCells - popCells)
8640843Smsmith    {
8740843Smsmith        vmThrowErr(pVM, "Error: stack overflow");
8840843Smsmith    }
8940843Smsmith
9040843Smsmith    return;
9140843Smsmith}
9240843Smsmith
9376116Sdcs#if FICL_WANT_FLOAT
9476116Sdcsvoid vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells)
9576116Sdcs{
9676116Sdcs    FICL_STACK *fStack = pVM->fStack;
9776116Sdcs    int nFree = fStack->base + fStack->nCells - fStack->sp;
9876116Sdcs
9976116Sdcs    if (popCells > STKDEPTH(fStack))
10076116Sdcs    {
10176116Sdcs        vmThrowErr(pVM, "Error: float stack underflow");
10276116Sdcs    }
10376116Sdcs
10476116Sdcs    if (nFree < pushCells - popCells)
10576116Sdcs    {
10676116Sdcs        vmThrowErr(pVM, "Error: float stack overflow");
10776116Sdcs    }
10876116Sdcs}
10976116Sdcs#endif
11076116Sdcs
11140843Smsmith/*******************************************************************
11240843Smsmith                    s t a c k C r e a t e
11340843Smsmith**
11440843Smsmith*******************************************************************/
11540843Smsmith
11640843SmsmithFICL_STACK *stackCreate(unsigned nCells)
11740843Smsmith{
11840843Smsmith    size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);
11940843Smsmith    FICL_STACK *pStack = ficlMalloc(size);
12040843Smsmith
12140843Smsmith#if FICL_ROBUST
12240843Smsmith    assert (nCells != 0);
12340843Smsmith    assert (pStack != NULL);
12440843Smsmith#endif
12540843Smsmith
12640843Smsmith    pStack->nCells = nCells;
12740843Smsmith    pStack->sp     = pStack->base;
12840843Smsmith    pStack->pFrame = NULL;
12940843Smsmith    return pStack;
13040843Smsmith}
13140843Smsmith
13240843Smsmith
13340843Smsmith/*******************************************************************
13440843Smsmith                    s t a c k D e l e t e
13540843Smsmith**
13640843Smsmith*******************************************************************/
13740843Smsmith
13840843Smsmithvoid stackDelete(FICL_STACK *pStack)
13940843Smsmith{
14040843Smsmith    if (pStack)
14140843Smsmith        ficlFree(pStack);
14240843Smsmith    return;
14340843Smsmith}
14440843Smsmith
14540843Smsmith
14640843Smsmith/*******************************************************************
14740843Smsmith                    s t a c k D e p t h
14840843Smsmith**
14940843Smsmith*******************************************************************/
15040843Smsmith
15140843Smsmithint stackDepth(FICL_STACK *pStack)
15240843Smsmith{
15340843Smsmith    return STKDEPTH(pStack);
15440843Smsmith}
15540843Smsmith
15640843Smsmith/*******************************************************************
15740843Smsmith                    s t a c k D r o p
15840843Smsmith**
15940843Smsmith*******************************************************************/
16040843Smsmith
16140843Smsmithvoid stackDrop(FICL_STACK *pStack, int n)
16240843Smsmith{
16340843Smsmith#if FICL_ROBUST
16440843Smsmith    assert(n > 0);
16540843Smsmith#endif
16640843Smsmith    pStack->sp -= n;
16740843Smsmith    return;
16840843Smsmith}
16940843Smsmith
17040843Smsmith
17140843Smsmith/*******************************************************************
17240843Smsmith                    s t a c k F e t c h
17340843Smsmith**
17440843Smsmith*******************************************************************/
17540843Smsmith
17640843SmsmithCELL stackFetch(FICL_STACK *pStack, int n)
17740843Smsmith{
17840843Smsmith    return pStack->sp[-n-1];
17940843Smsmith}
18040843Smsmith
18140843Smsmithvoid stackStore(FICL_STACK *pStack, int n, CELL c)
18240843Smsmith{
18340843Smsmith    pStack->sp[-n-1] = c;
18440843Smsmith    return;
18540843Smsmith}
18640843Smsmith
18740843Smsmith
18840843Smsmith/*******************************************************************
18940843Smsmith                    s t a c k G e t T o p
19040843Smsmith**
19140843Smsmith*******************************************************************/
19240843Smsmith
19340843SmsmithCELL stackGetTop(FICL_STACK *pStack)
19440843Smsmith{
19540843Smsmith    return pStack->sp[-1];
19640843Smsmith}
19740843Smsmith
19840843Smsmith
19940843Smsmith/*******************************************************************
20040843Smsmith                    s t a c k L i n k
20140843Smsmith** Link a frame using the stack's frame pointer. Allot space for
20240843Smsmith** nCells cells in the frame
20340843Smsmith** 1) Push pFrame
20440843Smsmith** 2) pFrame = sp
20540843Smsmith** 3) sp += nCells
20640843Smsmith*******************************************************************/
20740843Smsmith
20840843Smsmithvoid stackLink(FICL_STACK *pStack, int nCells)
20940843Smsmith{
21040843Smsmith    stackPushPtr(pStack, pStack->pFrame);
21140843Smsmith    pStack->pFrame = pStack->sp;
21240843Smsmith    pStack->sp += nCells;
21340843Smsmith    return;
21440843Smsmith}
21540843Smsmith
21640843Smsmith
21740843Smsmith/*******************************************************************
21840843Smsmith                    s t a c k U n l i n k
21940843Smsmith** Unink a stack frame previously created by stackLink
22040843Smsmith** 1) sp = pFrame
22140843Smsmith** 2) pFrame = pop()
22240843Smsmith*******************************************************************/
22340843Smsmith
22440843Smsmithvoid stackUnlink(FICL_STACK *pStack)
22540843Smsmith{
22640843Smsmith    pStack->sp = pStack->pFrame;
22740843Smsmith    pStack->pFrame = stackPopPtr(pStack);
22840843Smsmith    return;
22940843Smsmith}
23040843Smsmith
23140843Smsmith
23240843Smsmith/*******************************************************************
23340843Smsmith                    s t a c k P i c k
23440843Smsmith**
23540843Smsmith*******************************************************************/
23640843Smsmith
23740843Smsmithvoid stackPick(FICL_STACK *pStack, int n)
23840843Smsmith{
23940843Smsmith    stackPush(pStack, stackFetch(pStack, n));
24040843Smsmith    return;
24140843Smsmith}
24240843Smsmith
24340843Smsmith
24440843Smsmith/*******************************************************************
24540843Smsmith                    s t a c k P o p
24640843Smsmith**
24740843Smsmith*******************************************************************/
24840843Smsmith
24940843SmsmithCELL stackPop(FICL_STACK *pStack)
25040843Smsmith{
25140843Smsmith    return *--pStack->sp;
25240843Smsmith}
25340843Smsmith
25440843Smsmithvoid *stackPopPtr(FICL_STACK *pStack)
25540843Smsmith{
25640843Smsmith    return (*--pStack->sp).p;
25740843Smsmith}
25840843Smsmith
25951786SdcsFICL_UNS stackPopUNS(FICL_STACK *pStack)
26040843Smsmith{
26140843Smsmith    return (*--pStack->sp).u;
26240843Smsmith}
26340843Smsmith
26451786SdcsFICL_INT stackPopINT(FICL_STACK *pStack)
26540843Smsmith{
26640843Smsmith    return (*--pStack->sp).i;
26740843Smsmith}
26840843Smsmith
26976116Sdcs#if (FICL_WANT_FLOAT)
27076116Sdcsfloat stackPopFloat(FICL_STACK *pStack)
27176116Sdcs{
27276116Sdcs    return (*(--pStack->sp)).f;
27376116Sdcs}
27476116Sdcs#endif
27540843Smsmith
27640843Smsmith/*******************************************************************
27740843Smsmith                    s t a c k P u s h
27840843Smsmith**
27940843Smsmith*******************************************************************/
28040843Smsmith
28140843Smsmithvoid stackPush(FICL_STACK *pStack, CELL c)
28240843Smsmith{
28340843Smsmith    *pStack->sp++ = c;
28440843Smsmith}
28540843Smsmith
28640843Smsmithvoid stackPushPtr(FICL_STACK *pStack, void *ptr)
28740843Smsmith{
28840843Smsmith    *pStack->sp++ = LVALUEtoCELL(ptr);
28940843Smsmith}
29040843Smsmith
29151786Sdcsvoid stackPushUNS(FICL_STACK *pStack, FICL_UNS u)
29240843Smsmith{
29340843Smsmith    *pStack->sp++ = LVALUEtoCELL(u);
29440843Smsmith}
29540843Smsmith
29651786Sdcsvoid stackPushINT(FICL_STACK *pStack, FICL_INT i)
29740843Smsmith{
29840843Smsmith    *pStack->sp++ = LVALUEtoCELL(i);
29940843Smsmith}
30040843Smsmith
30176116Sdcs#if (FICL_WANT_FLOAT)
30276116Sdcsvoid stackPushFloat(FICL_STACK *pStack, float f)
30376116Sdcs{
30476116Sdcs    *pStack->sp++ = LVALUEtoCELL(f);
30576116Sdcs}
30676116Sdcs#endif
30776116Sdcs
30840843Smsmith/*******************************************************************
30940843Smsmith                    s t a c k R e s e t
31040843Smsmith**
31140843Smsmith*******************************************************************/
31240843Smsmith
31340843Smsmithvoid stackReset(FICL_STACK *pStack)
31440843Smsmith{
31540843Smsmith    pStack->sp = pStack->base;
31640843Smsmith    return;
31740843Smsmith}
31840843Smsmith
31940843Smsmith
32040843Smsmith/*******************************************************************
32140843Smsmith                    s t a c k R o l l
32240843Smsmith** Roll nth stack entry to the top (counting from zero), if n is
32340843Smsmith** >= 0. Drop other entries as needed to fill the hole.
32440843Smsmith** If n < 0, roll top-of-stack to nth entry, pushing others
32540843Smsmith** upward as needed to fill the hole.
32640843Smsmith*******************************************************************/
32740843Smsmith
32840843Smsmithvoid stackRoll(FICL_STACK *pStack, int n)
32940843Smsmith{
33040843Smsmith    CELL c;
33140843Smsmith    CELL *pCell;
33240843Smsmith
33340843Smsmith    if (n == 0)
33440843Smsmith        return;
33540843Smsmith    else if (n > 0)
33640843Smsmith    {
33740843Smsmith        pCell = pStack->sp - n - 1;
33840843Smsmith        c = *pCell;
33940843Smsmith
34040843Smsmith        for (;n > 0; --n, pCell++)
34140843Smsmith        {
34240843Smsmith            *pCell = pCell[1];
34340843Smsmith        }
34440843Smsmith
34540843Smsmith        *pCell = c;
34640843Smsmith    }
34740843Smsmith    else
34840843Smsmith    {
34940843Smsmith        pCell = pStack->sp - 1;
35040843Smsmith        c = *pCell;
35140843Smsmith
35240843Smsmith        for (; n < 0; ++n, pCell--)
35340843Smsmith        {
35440843Smsmith            *pCell = pCell[-1];
35540843Smsmith        }
35640843Smsmith
35740843Smsmith        *pCell = c;
35840843Smsmith    }
35940843Smsmith    return;
36040843Smsmith}
36140843Smsmith
36240843Smsmith
36340843Smsmith/*******************************************************************
36440843Smsmith                    s t a c k S e t T o p
36540843Smsmith**
36640843Smsmith*******************************************************************/
36740843Smsmith
36840843Smsmithvoid stackSetTop(FICL_STACK *pStack, CELL c)
36940843Smsmith{
37040843Smsmith    pStack->sp[-1] = c;
37140843Smsmith    return;
37240843Smsmith}
37340843Smsmith
37440843Smsmith
375