/*******************************************************************1** s t a c k . c2** Forth Inspired Command Language3** Author: John Sadler ([email protected])4** Created: 16 Oct 19975** $Id: stack.c,v 1.10 2001/12/05 07:21:34 jsadler Exp $6*******************************************************************/7/*8** Copyright (c) 1997-2001 John Sadler ([email protected])9** All rights reserved.10**11** Get the latest Ficl release at http://ficl.sourceforge.net12**13** I am interested in hearing from anyone who uses ficl. If you have14** a problem, a success story, a defect, an enhancement request, or15** if you would like to contribute to the ficl release, please16** contact me by email at the address above.17**18** L I C E N S E and D I S C L A I M E R19**20** Redistribution and use in source and binary forms, with or without21** modification, are permitted provided that the following conditions22** are met:23** 1. Redistributions of source code must retain the above copyright24** notice, this list of conditions and the following disclaimer.25** 2. Redistributions in binary form must reproduce the above copyright26** notice, this list of conditions and the following disclaimer in the27** documentation and/or other materials provided with the distribution.28**29** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND30** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE31** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE32** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE33** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS35** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)36** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT37** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY38** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF39** SUCH DAMAGE.40*/414243#ifdef TESTMAIN44#include <stdlib.h>45#else46#include <stand.h>47#endif48#include "ficl.h"4950#define STKDEPTH(s) ((s)->sp - (s)->base)5152/*53** N O T E: Stack convention:54**55** sp points to the first available cell56** push: store value at sp, increment sp57** pop: decrement sp, fetch value at sp58** Stack grows from low to high memory59*/6061/*******************************************************************62v m C h e c k S t a c k63** Check the parameter stack for underflow or overflow.64** nCells controls the type of check: if nCells is zero,65** the function checks the stack state for underflow and overflow.66** If nCells > 0, checks to see that the stack has room to push67** that many cells. If less than zero, checks to see that the68** stack has room to pop that many cells. If any test fails,69** the function throws (via vmThrow) a VM_ERREXIT exception.70*******************************************************************/71void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells)72{73FICL_STACK *pStack = pVM->pStack;74int nFree = pStack->base + pStack->nCells - pStack->sp;7576if (popCells > STKDEPTH(pStack))77{78vmThrowErr(pVM, "Error: stack underflow");79}8081if (nFree < pushCells - popCells)82{83vmThrowErr(pVM, "Error: stack overflow");84}8586return;87}8889#if FICL_WANT_FLOAT90void vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells)91{92FICL_STACK *fStack = pVM->fStack;93int nFree = fStack->base + fStack->nCells - fStack->sp;9495if (popCells > STKDEPTH(fStack))96{97vmThrowErr(pVM, "Error: float stack underflow");98}99100if (nFree < pushCells - popCells)101{102vmThrowErr(pVM, "Error: float stack overflow");103}104}105#endif106107/*******************************************************************108s t a c k C r e a t e109**110*******************************************************************/111112FICL_STACK *stackCreate(unsigned nCells)113{114size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL);115FICL_STACK *pStack = ficlMalloc(size);116117#if FICL_ROBUST118assert (nCells != 0);119assert (pStack != NULL);120#endif121122pStack->nCells = nCells;123pStack->sp = pStack->base;124pStack->pFrame = NULL;125return pStack;126}127128129/*******************************************************************130s t a c k D e l e t e131**132*******************************************************************/133134void stackDelete(FICL_STACK *pStack)135{136if (pStack)137ficlFree(pStack);138return;139}140141142/*******************************************************************143s t a c k D e p t h144**145*******************************************************************/146147int stackDepth(FICL_STACK *pStack)148{149return STKDEPTH(pStack);150}151152/*******************************************************************153s t a c k D r o p154**155*******************************************************************/156157void stackDrop(FICL_STACK *pStack, int n)158{159#if FICL_ROBUST160assert(n > 0);161#endif162pStack->sp -= n;163return;164}165166167/*******************************************************************168s t a c k F e t c h169**170*******************************************************************/171172CELL stackFetch(FICL_STACK *pStack, int n)173{174return pStack->sp[-n-1];175}176177void stackStore(FICL_STACK *pStack, int n, CELL c)178{179pStack->sp[-n-1] = c;180return;181}182183184/*******************************************************************185s t a c k G e t T o p186**187*******************************************************************/188189CELL stackGetTop(FICL_STACK *pStack)190{191return pStack->sp[-1];192}193194195/*******************************************************************196s t a c k L i n k197** Link a frame using the stack's frame pointer. Allot space for198** nCells cells in the frame199** 1) Push pFrame200** 2) pFrame = sp201** 3) sp += nCells202*******************************************************************/203204void stackLink(FICL_STACK *pStack, int nCells)205{206stackPushPtr(pStack, pStack->pFrame);207pStack->pFrame = pStack->sp;208pStack->sp += nCells;209return;210}211212213/*******************************************************************214s t a c k U n l i n k215** Unink a stack frame previously created by stackLink216** 1) sp = pFrame217** 2) pFrame = pop()218*******************************************************************/219220void stackUnlink(FICL_STACK *pStack)221{222pStack->sp = pStack->pFrame;223pStack->pFrame = stackPopPtr(pStack);224return;225}226227228/*******************************************************************229s t a c k P i c k230**231*******************************************************************/232233void stackPick(FICL_STACK *pStack, int n)234{235stackPush(pStack, stackFetch(pStack, n));236return;237}238239240/*******************************************************************241s t a c k P o p242**243*******************************************************************/244245CELL stackPop(FICL_STACK *pStack)246{247return *--pStack->sp;248}249250void *stackPopPtr(FICL_STACK *pStack)251{252return (*--pStack->sp).p;253}254255FICL_UNS stackPopUNS(FICL_STACK *pStack)256{257return (*--pStack->sp).u;258}259260FICL_INT stackPopINT(FICL_STACK *pStack)261{262return (*--pStack->sp).i;263}264265#if (FICL_WANT_FLOAT)266float stackPopFloat(FICL_STACK *pStack)267{268return (*(--pStack->sp)).f;269}270#endif271272/*******************************************************************273s t a c k P u s h274**275*******************************************************************/276277void stackPush(FICL_STACK *pStack, CELL c)278{279*pStack->sp++ = c;280}281282void stackPushPtr(FICL_STACK *pStack, void *ptr)283{284*pStack->sp++ = LVALUEtoCELL(ptr);285}286287void stackPushUNS(FICL_STACK *pStack, FICL_UNS u)288{289*pStack->sp++ = LVALUEtoCELL(u);290}291292void stackPushINT(FICL_STACK *pStack, FICL_INT i)293{294*pStack->sp++ = LVALUEtoCELL(i);295}296297#if (FICL_WANT_FLOAT)298void stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f)299{300*pStack->sp++ = LVALUEtoCELL(f);301}302#endif303304/*******************************************************************305s t a c k R e s e t306**307*******************************************************************/308309void stackReset(FICL_STACK *pStack)310{311pStack->sp = pStack->base;312return;313}314315316/*******************************************************************317s t a c k R o l l318** Roll nth stack entry to the top (counting from zero), if n is319** >= 0. Drop other entries as needed to fill the hole.320** If n < 0, roll top-of-stack to nth entry, pushing others321** upward as needed to fill the hole.322*******************************************************************/323324void stackRoll(FICL_STACK *pStack, int n)325{326CELL c;327CELL *pCell;328329if (n == 0)330return;331else if (n > 0)332{333pCell = pStack->sp - n - 1;334c = *pCell;335336for (;n > 0; --n, pCell++)337{338*pCell = pCell[1];339}340341*pCell = c;342}343else344{345pCell = pStack->sp - 1;346c = *pCell;347348for (; n < 0; ++n, pCell--)349{350*pCell = pCell[-1];351}352353*pCell = c;354}355return;356}357358359/*******************************************************************360s t a c k S e t T o p361**362*******************************************************************/363364void stackSetTop(FICL_STACK *pStack, CELL c)365{366pStack->sp[-1] = c;367return;368}369370371372373