stack.c revision 40883
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** 7*******************************************************************/ 8 9#ifdef TESTMAIN 10#include <stdlib.h> 11#else 12#include <stand.h> 13#endif 14#include "ficl.h" 15 16#define STKDEPTH(s) ((s)->sp - (s)->base) 17 18/* 19** N O T E: Stack convention: 20** 21** sp points to the first available cell 22** push: store value at sp, increment sp 23** pop: decrement sp, fetch value at sp 24** Stack grows from low to high memory 25*/ 26 27/******************************************************************* 28 v m C h e c k S t a c k 29** Check the parameter stack for underflow or overflow. 30** nCells controls the type of check: if nCells is zero, 31** the function checks the stack state for underflow and overflow. 32** If nCells > 0, checks to see that the stack has room to push 33** that many cells. If less than zero, checks to see that the 34** stack has room to pop that many cells. If any test fails, 35** the function throws (via vmThrow) a VM_ERREXIT exception. 36*******************************************************************/ 37void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells) 38{ 39 FICL_STACK *pStack = pVM->pStack; 40 int nFree = pStack->base + pStack->nCells - pStack->sp; 41 42 if (popCells > STKDEPTH(pStack)) 43 { 44 vmThrowErr(pVM, "Error: stack underflow"); 45 } 46 47 if (nFree < pushCells - popCells) 48 { 49 vmThrowErr(pVM, "Error: stack overflow"); 50 } 51 52 return; 53} 54 55/******************************************************************* 56 s t a c k C r e a t e 57** 58*******************************************************************/ 59 60FICL_STACK *stackCreate(unsigned nCells) 61{ 62 size_t size = sizeof (FICL_STACK) + nCells * sizeof (CELL); 63 FICL_STACK *pStack = ficlMalloc(size); 64 65#if FICL_ROBUST 66 assert (nCells != 0); 67 assert (pStack != NULL); 68#endif 69 70 pStack->nCells = nCells; 71 pStack->sp = pStack->base; 72 pStack->pFrame = NULL; 73 return pStack; 74} 75 76 77/******************************************************************* 78 s t a c k D e l e t e 79** 80*******************************************************************/ 81 82void stackDelete(FICL_STACK *pStack) 83{ 84 if (pStack) 85 ficlFree(pStack); 86 return; 87} 88 89 90/******************************************************************* 91 s t a c k D e p t h 92** 93*******************************************************************/ 94 95int stackDepth(FICL_STACK *pStack) 96{ 97 return STKDEPTH(pStack); 98} 99 100/******************************************************************* 101 s t a c k D r o p 102** 103*******************************************************************/ 104 105void stackDrop(FICL_STACK *pStack, int n) 106{ 107#if FICL_ROBUST 108 assert(n > 0); 109#endif 110 pStack->sp -= n; 111 return; 112} 113 114 115/******************************************************************* 116 s t a c k F e t c h 117** 118*******************************************************************/ 119 120CELL stackFetch(FICL_STACK *pStack, int n) 121{ 122 return pStack->sp[-n-1]; 123} 124 125void stackStore(FICL_STACK *pStack, int n, CELL c) 126{ 127 pStack->sp[-n-1] = c; 128 return; 129} 130 131 132/******************************************************************* 133 s t a c k G e t T o p 134** 135*******************************************************************/ 136 137CELL stackGetTop(FICL_STACK *pStack) 138{ 139 return pStack->sp[-1]; 140} 141 142 143/******************************************************************* 144 s t a c k L i n k 145** Link a frame using the stack's frame pointer. Allot space for 146** nCells cells in the frame 147** 1) Push pFrame 148** 2) pFrame = sp 149** 3) sp += nCells 150*******************************************************************/ 151 152void stackLink(FICL_STACK *pStack, int nCells) 153{ 154 stackPushPtr(pStack, pStack->pFrame); 155 pStack->pFrame = pStack->sp; 156 pStack->sp += nCells; 157 return; 158} 159 160 161/******************************************************************* 162 s t a c k U n l i n k 163** Unink a stack frame previously created by stackLink 164** 1) sp = pFrame 165** 2) pFrame = pop() 166*******************************************************************/ 167 168void stackUnlink(FICL_STACK *pStack) 169{ 170 pStack->sp = pStack->pFrame; 171 pStack->pFrame = stackPopPtr(pStack); 172 return; 173} 174 175 176/******************************************************************* 177 s t a c k P i c k 178** 179*******************************************************************/ 180 181void stackPick(FICL_STACK *pStack, int n) 182{ 183 stackPush(pStack, stackFetch(pStack, n)); 184 return; 185} 186 187 188/******************************************************************* 189 s t a c k P o p 190** 191*******************************************************************/ 192 193CELL stackPop(FICL_STACK *pStack) 194{ 195 return *--pStack->sp; 196} 197 198void *stackPopPtr(FICL_STACK *pStack) 199{ 200 return (*--pStack->sp).p; 201} 202 203UNS32 stackPopUNS32(FICL_STACK *pStack) 204{ 205 return (*--pStack->sp).u; 206} 207 208INT32 stackPopINT32(FICL_STACK *pStack) 209{ 210 return (*--pStack->sp).i; 211} 212 213 214/******************************************************************* 215 s t a c k P u s h 216** 217*******************************************************************/ 218 219void stackPush(FICL_STACK *pStack, CELL c) 220{ 221 *pStack->sp++ = c; 222} 223 224void stackPushPtr(FICL_STACK *pStack, void *ptr) 225{ 226 *pStack->sp++ = LVALUEtoCELL(ptr); 227} 228 229void stackPushUNS32(FICL_STACK *pStack, UNS32 u) 230{ 231 *pStack->sp++ = LVALUEtoCELL(u); 232} 233 234void stackPushINT32(FICL_STACK *pStack, INT32 i) 235{ 236 *pStack->sp++ = LVALUEtoCELL(i); 237} 238 239/******************************************************************* 240 s t a c k R e s e t 241** 242*******************************************************************/ 243 244void stackReset(FICL_STACK *pStack) 245{ 246 pStack->sp = pStack->base; 247 return; 248} 249 250 251/******************************************************************* 252 s t a c k R o l l 253** Roll nth stack entry to the top (counting from zero), if n is 254** >= 0. Drop other entries as needed to fill the hole. 255** If n < 0, roll top-of-stack to nth entry, pushing others 256** upward as needed to fill the hole. 257*******************************************************************/ 258 259void stackRoll(FICL_STACK *pStack, int n) 260{ 261 CELL c; 262 CELL *pCell; 263 264 if (n == 0) 265 return; 266 else if (n > 0) 267 { 268 pCell = pStack->sp - n - 1; 269 c = *pCell; 270 271 for (;n > 0; --n, pCell++) 272 { 273 *pCell = pCell[1]; 274 } 275 276 *pCell = c; 277 } 278 else 279 { 280 pCell = pStack->sp - 1; 281 c = *pCell; 282 283 for (; n < 0; ++n, pCell--) 284 { 285 *pCell = pCell[-1]; 286 } 287 288 *pCell = c; 289 } 290 return; 291} 292 293 294/******************************************************************* 295 s t a c k S e t T o p 296** 297*******************************************************************/ 298 299void stackSetTop(FICL_STACK *pStack, CELL c) 300{ 301 pStack->sp[-1] = c; 302 return; 303} 304 305 306