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