summaryrefslogtreecommitdiff
path: root/usr/src/common/ficl/stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common/ficl/stack.c')
-rw-r--r--usr/src/common/ficl/stack.c393
1 files changed, 393 insertions, 0 deletions
diff --git a/usr/src/common/ficl/stack.c b/usr/src/common/ficl/stack.c
new file mode 100644
index 0000000000..4970e058bb
--- /dev/null
+++ b/usr/src/common/ficl/stack.c
@@ -0,0 +1,393 @@
+/*
+ * s t a c k . c
+ * Forth Inspired Command Language
+ * Author: John Sadler (john_sadler@alum.mit.edu)
+ * Created: 16 Oct 1997
+ * $Id: stack.c,v 1.11 2010/08/12 13:57:22 asau Exp $
+ */
+/*
+ * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+ * All rights reserved.
+ *
+ * Get the latest Ficl release at http://ficl.sourceforge.net
+ *
+ * I am interested in hearing from anyone who uses Ficl. If you have
+ * a problem, a success story, a defect, an enhancement request, or
+ * if you would like to contribute to the Ficl release, please
+ * contact me by email at the address above.
+ *
+ * L I C E N S E and D I S C L A I M E R
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ficl.h"
+
+#define STKDEPTH(s) (((s)->top - (s)->base) + 1)
+
+/*
+ * N O T E: Stack convention:
+ *
+ * THIS CHANGED IN FICL 4.0!
+ *
+ * top points to the *current* top data value
+ * push: increment top, store value at top
+ * pop: fetch value at top, decrement top
+ * Stack grows from low to high memory
+ */
+
+/*
+ * v m C h e c k S t a c k
+ * Check the parameter stack for underflow or overflow.
+ * size controls the type of check: if size is zero,
+ * the function checks the stack state for underflow and overflow.
+ * If size > 0, checks to see that the stack has room to push
+ * that many cells. If less than zero, checks to see that the
+ * stack has room to pop that many cells. If any test fails,
+ * the function throws (via vmThrow) a VM_ERREXIT exception.
+ */
+void
+ficlStackCheck(ficlStack *stack, int popCells, int pushCells)
+{
+#if FICL_ROBUST >= 1
+ int nFree = stack->size - STKDEPTH(stack);
+
+ if (popCells > STKDEPTH(stack))
+ ficlVmThrowError(stack->vm, "Error: %s stack underflow",
+ stack->name);
+
+ if (nFree < pushCells - popCells)
+ ficlVmThrowError(stack->vm, "Error: %s stack overflow",
+ stack->name);
+#else /* FICL_ROBUST >= 1 */
+ FICL_IGNORE(stack);
+ FICL_IGNORE(popCells);
+ FICL_IGNORE(pushCells);
+#endif /* FICL_ROBUST >= 1 */
+}
+
+/*
+ * s t a c k C r e a t e
+ */
+
+ficlStack *
+ficlStackCreate(ficlVm *vm, char *name, unsigned size)
+{
+ size_t totalSize = sizeof (ficlStack) + (size * sizeof (ficlCell));
+ ficlStack *stack = ficlMalloc(totalSize);
+
+ FICL_VM_ASSERT(vm, size != 0);
+ FICL_VM_ASSERT(vm, stack != NULL);
+
+ stack->size = size;
+ stack->frame = NULL;
+
+ stack->vm = vm;
+ stack->name = name;
+
+ ficlStackReset(stack);
+ return (stack);
+}
+
+/*
+ * s t a c k D e l e t e
+ */
+void
+ficlStackDestroy(ficlStack *stack)
+{
+ if (stack)
+ ficlFree(stack);
+}
+
+/*
+ * s t a c k D e p t h
+ */
+int
+ficlStackDepth(ficlStack *stack)
+{
+ return (STKDEPTH(stack));
+}
+
+/*
+ * s t a c k D r o p
+ */
+void
+ficlStackDrop(ficlStack *stack, int n)
+{
+ FICL_VM_ASSERT(stack->vm, n > 0);
+ stack->top -= n;
+}
+
+/*
+ * s t a c k F e t c h
+ */
+ficlCell
+ficlStackFetch(ficlStack *stack, int n)
+{
+ return (stack->top[-n]);
+}
+
+void
+ficlStackStore(ficlStack *stack, int n, ficlCell c)
+{
+ stack->top[-n] = c;
+}
+
+/*
+ * s t a c k G e t T o p
+ */
+ficlCell
+ficlStackGetTop(ficlStack *stack)
+{
+ return (stack->top[0]);
+}
+
+#if FICL_WANT_LOCALS
+/*
+ * s t a c k L i n k
+ * Link a frame using the stack's frame pointer. Allot space for
+ * size cells in the frame
+ * 1) Push frame
+ * 2) frame = top
+ * 3) top += size
+ */
+void
+ficlStackLink(ficlStack *stack, int size)
+{
+ ficlStackPushPointer(stack, stack->frame);
+ stack->frame = stack->top + 1;
+ stack->top += size;
+}
+
+/*
+ * s t a c k U n l i n k
+ * Unink a stack frame previously created by stackLink
+ * 1) top = frame
+ * 2) frame = pop()
+ */
+void
+ficlStackUnlink(ficlStack *stack)
+{
+ stack->top = stack->frame - 1;
+ stack->frame = ficlStackPopPointer(stack);
+}
+#endif /* FICL_WANT_LOCALS */
+
+/*
+ * s t a c k P i c k
+ */
+void
+ficlStackPick(ficlStack *stack, int n)
+{
+ ficlStackPush(stack, ficlStackFetch(stack, n));
+}
+
+/*
+ * s t a c k P o p
+ */
+ficlCell
+ficlStackPop(ficlStack *stack)
+{
+ return (*stack->top--);
+}
+
+void *
+ficlStackPopPointer(ficlStack *stack)
+{
+ return ((*stack->top--).p);
+}
+
+ficlUnsigned
+ficlStackPopUnsigned(ficlStack *stack)
+{
+ return ((*stack->top--).u);
+}
+
+ficlInteger
+ficlStackPopInteger(ficlStack *stack)
+{
+ return ((*stack->top--).i);
+}
+
+ficl2Integer
+ficlStackPop2Integer(ficlStack *stack)
+{
+ ficl2Integer ret;
+ ficlInteger high = ficlStackPopInteger(stack);
+ ficlInteger low = ficlStackPopInteger(stack);
+ FICL_2INTEGER_SET(high, low, ret);
+ return (ret);
+}
+
+ficl2Unsigned
+ficlStackPop2Unsigned(ficlStack *stack)
+{
+ ficl2Unsigned ret;
+ ficlUnsigned high = ficlStackPopUnsigned(stack);
+ ficlUnsigned low = ficlStackPopUnsigned(stack);
+ FICL_2UNSIGNED_SET(high, low, ret);
+ return (ret);
+}
+
+#if (FICL_WANT_FLOAT)
+ficlFloat
+ficlStackPopFloat(ficlStack *stack)
+{
+ return ((*stack->top--).f);
+}
+#endif
+
+/*
+ * s t a c k P u s h
+ */
+void
+ficlStackPush(ficlStack *stack, ficlCell c)
+{
+ *++stack->top = c;
+}
+
+void
+ficlStackPushPointer(ficlStack *stack, void *ptr)
+{
+ ficlCell c;
+
+ c.p = ptr;
+ *++stack->top = c;
+}
+
+void
+ficlStackPushInteger(ficlStack *stack, ficlInteger i)
+{
+ ficlCell c;
+
+ c.i = i;
+ *++stack->top = c;
+}
+
+void
+ficlStackPushUnsigned(ficlStack *stack, ficlUnsigned u)
+{
+ ficlCell c;
+
+ c.u = u;
+ *++stack->top = c;
+}
+
+void
+ficlStackPush2Unsigned(ficlStack *stack, ficl2Unsigned du)
+{
+ ficlStackPushUnsigned(stack, FICL_2UNSIGNED_GET_LOW(du));
+ ficlStackPushUnsigned(stack, FICL_2UNSIGNED_GET_HIGH(du));
+}
+
+void
+ficlStackPush2Integer(ficlStack *stack, ficl2Integer di)
+{
+ ficl2Unsigned du;
+ FICL_2UNSIGNED_SET(FICL_2UNSIGNED_GET_HIGH(di),
+ FICL_2UNSIGNED_GET_LOW(di), du);
+ ficlStackPush2Unsigned(stack, du);
+}
+
+#if (FICL_WANT_FLOAT)
+void
+ficlStackPushFloat(ficlStack *stack, ficlFloat f)
+{
+ ficlCell c;
+
+ c.f = f;
+ *++stack->top = c;
+}
+#endif
+
+/*
+ * s t a c k R e s e t
+ */
+void
+ficlStackReset(ficlStack *stack)
+{
+ stack->top = stack->base - 1;
+}
+
+/*
+ * s t a c k R o l l
+ * Roll nth stack entry to the top (counting from zero), if n is
+ * >= 0. Drop other entries as needed to fill the hole.
+ * If n < 0, roll top-of-stack to nth entry, pushing others
+ * upward as needed to fill the hole.
+ */
+void
+ficlStackRoll(ficlStack *stack, int n)
+{
+ ficlCell c;
+ ficlCell *cell;
+
+ if (n == 0)
+ return;
+ else if (n > 0) {
+ cell = stack->top - n;
+ c = *cell;
+
+ for (; n > 0; --n, cell++) {
+ *cell = cell[1];
+ }
+
+ *cell = c;
+ } else {
+ cell = stack->top;
+ c = *cell;
+
+ for (; n < 0; ++n, cell--) {
+ *cell = cell[-1];
+ }
+
+ *cell = c;
+ }
+}
+
+/*
+ * s t a c k S e t T o p
+ */
+void
+ficlStackSetTop(ficlStack *stack, ficlCell c)
+{
+ FICL_STACK_CHECK(stack, 1, 1);
+ stack->top[0] = c;
+}
+
+void
+ficlStackWalk(ficlStack *stack, ficlStackWalkFunction callback,
+ void *context, ficlInteger bottomToTop)
+{
+ int i;
+ int depth;
+ ficlCell *cell;
+ FICL_STACK_CHECK(stack, 0, 0);
+
+ depth = ficlStackDepth(stack);
+ cell = bottomToTop ? stack->base : stack->top;
+ for (i = 0; i < depth; i++) {
+ if (callback(context, cell) == FICL_FALSE)
+ break;
+ cell += bottomToTop ? 1 : -1;
+ }
+}