stack.c revision 40843
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
640843Smsmith**
740843Smsmith*******************************************************************/
840843Smsmith#include <stdlib.h>
940843Smsmith
1040843Smsmith#include "ficl.h"
1140843Smsmith
1240843Smsmith#define STKDEPTH(s) ((s)->sp - (s)->base)
1340843Smsmith
1440843Smsmith/*
1540843Smsmith** N O T E: Stack convention:
1640843Smsmith**
1740843Smsmith** sp points to the first available cell
1840843Smsmith** push: store value at sp, increment sp
1940843Smsmith** pop:  decrement sp, fetch value at sp
2040843Smsmith** Stack grows from low to high memory
2140843Smsmith*/
2240843Smsmith
2340843Smsmith/*******************************************************************
2440843Smsmith                    v m C h e c k S t a c k
2540843Smsmith** Check the parameter stack for underflow or overflow.
2640843Smsmith** nCells controls the type of check: if nCells is zero,
2740843Smsmith** the function checks the stack state for underflow and overflow.
2840843Smsmith** If nCells > 0, checks to see that the stack has room to push
2940843Smsmith** that many cells. If less than zero, checks to see that the
3040843Smsmith** stack has room to pop that many cells. If any test fails,
3140843Smsmith** the function throws (via vmThrow) a VM_ERREXIT exception.
3240843Smsmith*******************************************************************/
3340843Smsmithvoid vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)
3440843Smsmith{
3540843Smsmith    FICL_STACK *pStack = pVM->pStack;
3640843Smsmith    int nFree = pStack->base + pStack->nCells - pStack->sp;
3740843Smsmith
3840843Smsmith    if (popCells > STKDEPTH(pStack))
3940843Smsmith    {
4040843Smsmith        vmThrowErr(pVM, "Error: stack underflow");
4140843Smsmith    }
4240843Smsmith
4340843Smsmith    if (nFree < pushCells - popCells)
4440843Smsmith    {
4540843Smsmith        vmThrowErr(pVM, "Error: stack overflow");
4640843Smsmith    }
4740843Smsmith
4840843Smsmith    return;
4940843Smsmith}
5040843Smsmith
5140843Smsmith/*******************************************************************
5240843Smsmith                    s t a c k C r e a t e
5340843Smsmith**
5440843Smsmith*******************************************************************/
5540843Smsmith
5640843SmsmithFICL_STACK *stackCreate(unsigned nCells)
5740843Smsmith{
5840843Smsmith    size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);
5940843Smsmith    FICL_STACK *pStack = ficlMalloc(size);
6040843Smsmith
6140843Smsmith#if FICL_ROBUST
6240843Smsmith    assert (nCells != 0);
6340843Smsmith    assert (pStack != NULL);
6440843Smsmith#endif
6540843Smsmith
6640843Smsmith    pStack->nCells = nCells;
6740843Smsmith    pStack->sp     = pStack->base;
6840843Smsmith    pStack->pFrame = NULL;
6940843Smsmith    return pStack;
7040843Smsmith}
7140843Smsmith
7240843Smsmith
7340843Smsmith/*******************************************************************
7440843Smsmith                    s t a c k D e l e t e
7540843Smsmith**
7640843Smsmith*******************************************************************/
7740843Smsmith
7840843Smsmithvoid stackDelete(FICL_STACK *pStack)
7940843Smsmith{
8040843Smsmith    if (pStack)
8140843Smsmith        ficlFree(pStack);
8240843Smsmith    return;
8340843Smsmith}
8440843Smsmith
8540843Smsmith
8640843Smsmith/*******************************************************************
8740843Smsmith                    s t a c k D e p t h
8840843Smsmith**
8940843Smsmith*******************************************************************/
9040843Smsmith
9140843Smsmithint stackDepth(FICL_STACK *pStack)
9240843Smsmith{
9340843Smsmith    return STKDEPTH(pStack);
9440843Smsmith}
9540843Smsmith
9640843Smsmith/*******************************************************************
9740843Smsmith                    s t a c k D r o p
9840843Smsmith**
9940843Smsmith*******************************************************************/
10040843Smsmith
10140843Smsmithvoid stackDrop(FICL_STACK *pStack, int n)
10240843Smsmith{
10340843Smsmith#if FICL_ROBUST
10440843Smsmith    assert(n > 0);
10540843Smsmith#endif
10640843Smsmith    pStack->sp -= n;
10740843Smsmith    return;
10840843Smsmith}
10940843Smsmith
11040843Smsmith
11140843Smsmith/*******************************************************************
11240843Smsmith                    s t a c k F e t c h
11340843Smsmith**
11440843Smsmith*******************************************************************/
11540843Smsmith
11640843SmsmithCELL stackFetch(FICL_STACK *pStack, int n)
11740843Smsmith{
11840843Smsmith    return pStack->sp[-n-1];
11940843Smsmith}
12040843Smsmith
12140843Smsmithvoid stackStore(FICL_STACK *pStack, int n, CELL c)
12240843Smsmith{
12340843Smsmith    pStack->sp[-n-1] = c;
12440843Smsmith    return;
12540843Smsmith}
12640843Smsmith
12740843Smsmith
12840843Smsmith/*******************************************************************
12940843Smsmith                    s t a c k G e t T o p
13040843Smsmith**
13140843Smsmith*******************************************************************/
13240843Smsmith
13340843SmsmithCELL stackGetTop(FICL_STACK *pStack)
13440843Smsmith{
13540843Smsmith    return pStack->sp[-1];
13640843Smsmith}
13740843Smsmith
13840843Smsmith
13940843Smsmith/*******************************************************************
14040843Smsmith                    s t a c k L i n k
14140843Smsmith** Link a frame using the stack's frame pointer. Allot space for
14240843Smsmith** nCells cells in the frame
14340843Smsmith** 1) Push pFrame
14440843Smsmith** 2) pFrame = sp
14540843Smsmith** 3) sp += nCells
14640843Smsmith*******************************************************************/
14740843Smsmith
14840843Smsmithvoid stackLink(FICL_STACK *pStack, int nCells)
14940843Smsmith{
15040843Smsmith    stackPushPtr(pStack, pStack->pFrame);
15140843Smsmith    pStack->pFrame = pStack->sp;
15240843Smsmith    pStack->sp += nCells;
15340843Smsmith    return;
15440843Smsmith}
15540843Smsmith
15640843Smsmith
15740843Smsmith/*******************************************************************
15840843Smsmith                    s t a c k U n l i n k
15940843Smsmith** Unink a stack frame previously created by stackLink
16040843Smsmith** 1) sp = pFrame
16140843Smsmith** 2) pFrame = pop()
16240843Smsmith*******************************************************************/
16340843Smsmith
16440843Smsmithvoid stackUnlink(FICL_STACK *pStack)
16540843Smsmith{
16640843Smsmith    pStack->sp = pStack->pFrame;
16740843Smsmith    pStack->pFrame = stackPopPtr(pStack);
16840843Smsmith    return;
16940843Smsmith}
17040843Smsmith
17140843Smsmith
17240843Smsmith/*******************************************************************
17340843Smsmith                    s t a c k P i c k
17440843Smsmith**
17540843Smsmith*******************************************************************/
17640843Smsmith
17740843Smsmithvoid stackPick(FICL_STACK *pStack, int n)
17840843Smsmith{
17940843Smsmith    stackPush(pStack, stackFetch(pStack, n));
18040843Smsmith    return;
18140843Smsmith}
18240843Smsmith
18340843Smsmith
18440843Smsmith/*******************************************************************
18540843Smsmith                    s t a c k P o p
18640843Smsmith**
18740843Smsmith*******************************************************************/
18840843Smsmith
18940843SmsmithCELL stackPop(FICL_STACK *pStack)
19040843Smsmith{
19140843Smsmith    return *--pStack->sp;
19240843Smsmith}
19340843Smsmith
19440843Smsmithvoid *stackPopPtr(FICL_STACK *pStack)
19540843Smsmith{
19640843Smsmith    return (*--pStack->sp).p;
19740843Smsmith}
19840843Smsmith
19940843SmsmithUNS32 stackPopUNS32(FICL_STACK *pStack)
20040843Smsmith{
20140843Smsmith    return (*--pStack->sp).u;
20240843Smsmith}
20340843Smsmith
20440843SmsmithINT32 stackPopINT32(FICL_STACK *pStack)
20540843Smsmith{
20640843Smsmith    return (*--pStack->sp).i;
20740843Smsmith}
20840843Smsmith
20940843Smsmith
21040843Smsmith/*******************************************************************
21140843Smsmith                    s t a c k P u s h
21240843Smsmith**
21340843Smsmith*******************************************************************/
21440843Smsmith
21540843Smsmithvoid stackPush(FICL_STACK *pStack, CELL c)
21640843Smsmith{
21740843Smsmith    *pStack->sp++ = c;
21840843Smsmith}
21940843Smsmith
22040843Smsmithvoid stackPushPtr(FICL_STACK *pStack, void *ptr)
22140843Smsmith{
22240843Smsmith    *pStack->sp++ = LVALUEtoCELL(ptr);
22340843Smsmith}
22440843Smsmith
22540843Smsmithvoid stackPushUNS32(FICL_STACK *pStack, UNS32 u)
22640843Smsmith{
22740843Smsmith    *pStack->sp++ = LVALUEtoCELL(u);
22840843Smsmith}
22940843Smsmith
23040843Smsmithvoid stackPushINT32(FICL_STACK *pStack, INT32 i)
23140843Smsmith{
23240843Smsmith    *pStack->sp++ = LVALUEtoCELL(i);
23340843Smsmith}
23440843Smsmith
23540843Smsmith/*******************************************************************
23640843Smsmith                    s t a c k R e s e t
23740843Smsmith**
23840843Smsmith*******************************************************************/
23940843Smsmith
24040843Smsmithvoid stackReset(FICL_STACK *pStack)
24140843Smsmith{
24240843Smsmith    pStack->sp = pStack->base;
24340843Smsmith    return;
24440843Smsmith}
24540843Smsmith
24640843Smsmith
24740843Smsmith/*******************************************************************
24840843Smsmith                    s t a c k R o l l
24940843Smsmith** Roll nth stack entry to the top (counting from zero), if n is
25040843Smsmith** >= 0. Drop other entries as needed to fill the hole.
25140843Smsmith** If n < 0, roll top-of-stack to nth entry, pushing others
25240843Smsmith** upward as needed to fill the hole.
25340843Smsmith*******************************************************************/
25440843Smsmith
25540843Smsmithvoid stackRoll(FICL_STACK *pStack, int n)
25640843Smsmith{
25740843Smsmith    CELL c;
25840843Smsmith    CELL *pCell;
25940843Smsmith
26040843Smsmith    if (n == 0)
26140843Smsmith        return;
26240843Smsmith    else if (n > 0)
26340843Smsmith    {
26440843Smsmith        pCell = pStack->sp - n - 1;
26540843Smsmith        c = *pCell;
26640843Smsmith
26740843Smsmith        for (;n > 0; --n, pCell++)
26840843Smsmith        {
26940843Smsmith            *pCell = pCell[1];
27040843Smsmith        }
27140843Smsmith
27240843Smsmith        *pCell = c;
27340843Smsmith    }
27440843Smsmith    else
27540843Smsmith    {
27640843Smsmith        pCell = pStack->sp - 1;
27740843Smsmith        c = *pCell;
27840843Smsmith
27940843Smsmith        for (; n < 0; ++n, pCell--)
28040843Smsmith        {
28140843Smsmith            *pCell = pCell[-1];
28240843Smsmith        }
28340843Smsmith
28440843Smsmith        *pCell = c;
28540843Smsmith    }
28640843Smsmith    return;
28740843Smsmith}
28840843Smsmith
28940843Smsmith
29040843Smsmith/*******************************************************************
29140843Smsmith                    s t a c k S e t T o p
29240843Smsmith**
29340843Smsmith*******************************************************************/
29440843Smsmith
29540843Smsmithvoid stackSetTop(FICL_STACK *pStack, CELL c)
29640843Smsmith{
29740843Smsmith    pStack->sp[-1] = c;
29840843Smsmith    return;
29940843Smsmith}
30040843Smsmith
30140843Smsmith
302