stack.c revision 51786
155682Smarkm/******************************************************************* 255682Smarkm** s t a c k . c 355682Smarkm** Forth Inspired Command Language 455682Smarkm** Author: John Sadler (john_sadler@alum.mit.edu) 555682Smarkm** Created: 16 Oct 1997 655682Smarkm** 755682Smarkm*******************************************************************/ 855682Smarkm 955682Smarkm/* $FreeBSD: head/sys/boot/ficl/stack.c 51786 1999-09-29 04:43:16Z dcs $ */ 1055682Smarkm 1155682Smarkm#ifdef TESTMAIN 1255682Smarkm#include <stdlib.h> 1355682Smarkm#else 1455682Smarkm#include <stand.h> 1555682Smarkm#endif 1655682Smarkm#include "ficl.h" 1755682Smarkm 1855682Smarkm#define STKDEPTH(s) ((s)->sp - (s)->base) 1955682Smarkm 2055682Smarkm/* 2155682Smarkm** N O T E: Stack convention: 2255682Smarkm** 2355682Smarkm** sp points to the first available cell 2455682Smarkm** push: store value at sp, increment sp 2555682Smarkm** pop: decrement sp, fetch value at sp 2655682Smarkm** Stack grows from low to high memory 2755682Smarkm*/ 2855682Smarkm 2955682Smarkm/******************************************************************* 3055682Smarkm v m C h e c k S t a c k 3155682Smarkm** Check the parameter stack for underflow or overflow. 3255682Smarkm** nCells controls the type of check: if nCells is zero, 3355682Smarkm** the function checks the stack state for underflow and overflow. 3455682Smarkm** If nCells > 0, checks to see that the stack has room to push 3555682Smarkm** that many cells. If less than zero, checks to see that the 3655682Smarkm** stack has room to pop that many cells. If any test fails, 3755682Smarkm** the function throws (via vmThrow) a VM_ERREXIT exception. 3855682Smarkm*******************************************************************/ 3955682Smarkmvoid vmCheckStack(FICL_VM *pVM, int popCells, int pushCells) 4055682Smarkm{ 4155682Smarkm FICL_STACK *pStack = pVM->pStack; 4255682Smarkm int nFree = pStack->base + pStack->nCells - pStack->sp; 4355682Smarkm 4455682Smarkm if (popCells > STKDEPTH(pStack)) 4555682Smarkm { 4655682Smarkm vmThrowErr(pVM, "Error: stack underflow"); 4755682Smarkm } 4855682Smarkm 4955682Smarkm if (nFree < pushCells - popCells) 5055682Smarkm { 5155682Smarkm vmThrowErr(pVM, "Error: stack overflow"); 5255682Smarkm } 5355682Smarkm 5455682Smarkm return; 5555682Smarkm} 5655682Smarkm 5755682Smarkm/******************************************************************* 5855682Smarkm s t a c k C r e a t e 5955682Smarkm** 6055682Smarkm*******************************************************************/ 6155682Smarkm 6255682SmarkmFICL_STACK *stackCreate(unsigned nCells) 6355682Smarkm{ 6455682Smarkm size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL); 6555682Smarkm FICL_STACK *pStack = ficlMalloc(size); 6655682Smarkm 6755682Smarkm#if FICL_ROBUST 6855682Smarkm assert (nCells != 0); 6955682Smarkm assert (pStack != NULL); 7055682Smarkm#endif 7155682Smarkm 7255682Smarkm pStack->nCells = nCells; 7355682Smarkm pStack->sp = pStack->base; 7455682Smarkm pStack->pFrame = NULL; 7555682Smarkm return pStack; 7655682Smarkm} 7755682Smarkm 7855682Smarkm 79/******************************************************************* 80 s t a c k D e l e t e 81** 82*******************************************************************/ 83 84void stackDelete(FICL_STACK *pStack) 85{ 86 if (pStack) 87 ficlFree(pStack); 88 return; 89} 90 91 92/******************************************************************* 93 s t a c k D e p t h 94** 95*******************************************************************/ 96 97int stackDepth(FICL_STACK *pStack) 98{ 99 return STKDEPTH(pStack); 100} 101 102/******************************************************************* 103 s t a c k D r o p 104** 105*******************************************************************/ 106 107void stackDrop(FICL_STACK *pStack, int n) 108{ 109#if FICL_ROBUST 110 assert(n > 0); 111#endif 112 pStack->sp -= n; 113 return; 114} 115 116 117/******************************************************************* 118 s t a c k F e t c h 119** 120*******************************************************************/ 121 122CELL stackFetch(FICL_STACK *pStack, int n) 123{ 124 return pStack->sp[-n-1]; 125} 126 127void stackStore(FICL_STACK *pStack, int n, CELL c) 128{ 129 pStack->sp[-n-1] = c; 130 return; 131} 132 133 134/******************************************************************* 135 s t a c k G e t T o p 136** 137*******************************************************************/ 138 139CELL stackGetTop(FICL_STACK *pStack) 140{ 141 return pStack->sp[-1]; 142} 143 144 145/******************************************************************* 146 s t a c k L i n k 147** Link a frame using the stack's frame pointer. Allot space for 148** nCells cells in the frame 149** 1) Push pFrame 150** 2) pFrame = sp 151** 3) sp += nCells 152*******************************************************************/ 153 154void stackLink(FICL_STACK *pStack, int nCells) 155{ 156 stackPushPtr(pStack, pStack->pFrame); 157 pStack->pFrame = pStack->sp; 158 pStack->sp += nCells; 159 return; 160} 161 162 163/******************************************************************* 164 s t a c k U n l i n k 165** Unink a stack frame previously created by stackLink 166** 1) sp = pFrame 167** 2) pFrame = pop() 168*******************************************************************/ 169 170void stackUnlink(FICL_STACK *pStack) 171{ 172 pStack->sp = pStack->pFrame; 173 pStack->pFrame = stackPopPtr(pStack); 174 return; 175} 176 177 178/******************************************************************* 179 s t a c k P i c k 180** 181*******************************************************************/ 182 183void stackPick(FICL_STACK *pStack, int n) 184{ 185 stackPush(pStack, stackFetch(pStack, n)); 186 return; 187} 188 189 190/******************************************************************* 191 s t a c k P o p 192** 193*******************************************************************/ 194 195CELL stackPop(FICL_STACK *pStack) 196{ 197 return *--pStack->sp; 198} 199 200void *stackPopPtr(FICL_STACK *pStack) 201{ 202 return (*--pStack->sp).p; 203} 204 205FICL_UNS stackPopUNS(FICL_STACK *pStack) 206{ 207 return (*--pStack->sp).u; 208} 209 210FICL_INT stackPopINT(FICL_STACK *pStack) 211{ 212 return (*--pStack->sp).i; 213} 214 215 216/******************************************************************* 217 s t a c k P u s h 218** 219*******************************************************************/ 220 221void stackPush(FICL_STACK *pStack, CELL c) 222{ 223 *pStack->sp++ = c; 224} 225 226void stackPushPtr(FICL_STACK *pStack, void *ptr) 227{ 228 *pStack->sp++ = LVALUEtoCELL(ptr); 229} 230 231void stackPushUNS(FICL_STACK *pStack, FICL_UNS u) 232{ 233 *pStack->sp++ = LVALUEtoCELL(u); 234} 235 236void stackPushINT(FICL_STACK *pStack, FICL_INT i) 237{ 238 *pStack->sp++ = LVALUEtoCELL(i); 239} 240 241/******************************************************************* 242 s t a c k R e s e t 243** 244*******************************************************************/ 245 246void stackReset(FICL_STACK *pStack) 247{ 248 pStack->sp = pStack->base; 249 return; 250} 251 252 253/******************************************************************* 254 s t a c k R o l l 255** Roll nth stack entry to the top (counting from zero), if n is 256** >= 0. Drop other entries as needed to fill the hole. 257** If n < 0, roll top-of-stack to nth entry, pushing others 258** upward as needed to fill the hole. 259*******************************************************************/ 260 261void stackRoll(FICL_STACK *pStack, int n) 262{ 263 CELL c; 264 CELL *pCell; 265 266 if (n == 0) 267 return; 268 else if (n > 0) 269 { 270 pCell = pStack->sp - n - 1; 271 c = *pCell; 272 273 for (;n > 0; --n, pCell++) 274 { 275 *pCell = pCell[1]; 276 } 277 278 *pCell = c; 279 } 280 else 281 { 282 pCell = pStack->sp - 1; 283 c = *pCell; 284 285 for (; n < 0; ++n, pCell--) 286 { 287 *pCell = pCell[-1]; 288 } 289 290 *pCell = c; 291 } 292 return; 293} 294 295 296/******************************************************************* 297 s t a c k S e t T o p 298** 299*******************************************************************/ 300 301void stackSetTop(FICL_STACK *pStack, CELL c) 302{ 303 pStack->sp[-1] = c; 304 return; 305} 306 307 308