diff options
Diffstat (limited to 'usr/src/lib/libast/common/misc/stack.c')
-rw-r--r-- | usr/src/lib/libast/common/misc/stack.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/usr/src/lib/libast/common/misc/stack.c b/usr/src/lib/libast/common/misc/stack.c new file mode 100644 index 0000000000..05621992b2 --- /dev/null +++ b/usr/src/lib/libast/common/misc/stack.c @@ -0,0 +1,172 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* A copy of the License is available at * +* http://www.opensource.org/licenses/cpl1.0.txt * +* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * pointer stack routines + */ + +static const char id_stack[] = "\n@(#)$Id: stack (AT&T Bell Laboratories) 1984-05-01 $\0\n"; + +#include <ast.h> +#include <stack.h> + +/* + * create a new stack + */ + +STACK +stackalloc(register int size, void* error) +{ + register STACK stack; + register struct stackblock *b; + + if (size <= 0) size = 100; + if (!(stack = newof(0, struct stacktable, 1, 0))) return(0); + if (!(b = newof(0, struct stackblock, 1, 0))) + { + free(stack); + return(0); + } + if (!(b->stack = newof(0, void*, size, 0))) + { + free(b); + free(stack); + return(0); + } + stack->blocks = b; + stack->size = size; + stack->error = error; + stack->position.block = b; + stack->position.index = -1; + b->next = 0; + b->prev = 0; + return(stack); +} + +/* + * remove a stack + */ + +void +stackfree(register STACK stack) +{ + register struct stackblock* b; + register struct stackblock* p; + + b = stack->blocks; + while (p = b) + { + b = p->next; + free(p->stack); + free(p); + } + free(stack); +} + +/* + * clear stack + */ + +void +stackclear(register STACK stack) +{ + stack->position.block = stack->blocks; + stack->position.index = -1; +} + +/* + * get value on top of stack + */ + +void* +stackget(register STACK stack) +{ + if (stack->position.index < 0) return(stack->error); + else return(stack->position.block->stack[stack->position.index]); +} + +/* + * push value on to stack + */ + +int +stackpush(register STACK stack, void* value) +{ + register struct stackblock *b; + + if (++stack->position.index >= stack->size) + { + b = stack->position.block; + if (b->next) b = b->next; + else + { + if (!(b->next = newof(0, struct stackblock, 1, 0))) + return(-1); + b = b->next; + if (!(b->stack = newof(0, void*, stack->size, 0))) + return(-1); + b->prev = stack->position.block; + b->next = 0; + } + stack->position.block = b; + stack->position.index = 0; + } + stack->position.block->stack[stack->position.index] = value; + return(0); +} + +/* + * pop value off stack + */ + +int +stackpop(register STACK stack) +{ + /* + * return: + * + * -1 if stack empty before pop + * 0 if stack empty after pop + * 1 if stack not empty before & after pop + */ + + if (stack->position.index < 0) return(-1); + else if (--stack->position.index < 0) + { + if (!stack->position.block->prev) return(0); + stack->position.block = stack->position.block->prev; + stack->position.index = stack->size - 1; + return(1); + } + else return(1); +} + +/* + * set|get stack position + */ + +void +stacktell(register STACK stack, int set, STACKPOS* position) +{ + if (set) stack->position = *position; + else *position = stack->position; +} |