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