1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #pragma prototyped
23*4887Schin /*
24*4887Schin  * pointer stack routines
25*4887Schin  */
26*4887Schin 
27*4887Schin static const char id_stack[] = "\n@(#)$Id: stack (AT&T Bell Laboratories) 1984-05-01 $\0\n";
28*4887Schin 
29*4887Schin #include <ast.h>
30*4887Schin #include <stack.h>
31*4887Schin 
32*4887Schin /*
33*4887Schin  * create a new stack
34*4887Schin  */
35*4887Schin 
36*4887Schin STACK
37*4887Schin stackalloc(register int size, void* error)
38*4887Schin {
39*4887Schin 	register STACK			stack;
40*4887Schin 	register struct stackblock	*b;
41*4887Schin 
42*4887Schin 	if (size <= 0) size = 100;
43*4887Schin 	if (!(stack = newof(0, struct stacktable, 1, 0))) return(0);
44*4887Schin 	if (!(b = newof(0, struct stackblock, 1, 0)))
45*4887Schin 	{
46*4887Schin 		free(stack);
47*4887Schin 		return(0);
48*4887Schin 	}
49*4887Schin 	if (!(b->stack = newof(0, void*, size, 0)))
50*4887Schin 	{
51*4887Schin 		free(b);
52*4887Schin 		free(stack);
53*4887Schin 		return(0);
54*4887Schin 	}
55*4887Schin 	stack->blocks = b;
56*4887Schin 	stack->size = size;
57*4887Schin 	stack->error = error;
58*4887Schin 	stack->position.block = b;
59*4887Schin 	stack->position.index = -1;
60*4887Schin 	b->next = 0;
61*4887Schin 	b->prev = 0;
62*4887Schin 	return(stack);
63*4887Schin }
64*4887Schin 
65*4887Schin /*
66*4887Schin  * remove a stack
67*4887Schin  */
68*4887Schin 
69*4887Schin void
70*4887Schin stackfree(register STACK stack)
71*4887Schin {
72*4887Schin 	register struct stackblock*	b;
73*4887Schin 	register struct stackblock*	p;
74*4887Schin 
75*4887Schin 	b = stack->blocks;
76*4887Schin 	while (p = b)
77*4887Schin 	{
78*4887Schin 		b = p->next;
79*4887Schin 		free(p->stack);
80*4887Schin 		free(p);
81*4887Schin 	}
82*4887Schin 	free(stack);
83*4887Schin }
84*4887Schin 
85*4887Schin /*
86*4887Schin  * clear stack
87*4887Schin  */
88*4887Schin 
89*4887Schin void
90*4887Schin stackclear(register STACK stack)
91*4887Schin {
92*4887Schin 	stack->position.block = stack->blocks;
93*4887Schin 	stack->position.index = -1;
94*4887Schin }
95*4887Schin 
96*4887Schin /*
97*4887Schin  * get value on top of stack
98*4887Schin  */
99*4887Schin 
100*4887Schin void*
101*4887Schin stackget(register STACK stack)
102*4887Schin {
103*4887Schin 	if (stack->position.index < 0) return(stack->error);
104*4887Schin 	else return(stack->position.block->stack[stack->position.index]);
105*4887Schin }
106*4887Schin 
107*4887Schin /*
108*4887Schin  * push value on to stack
109*4887Schin  */
110*4887Schin 
111*4887Schin int
112*4887Schin stackpush(register STACK stack, void* value)
113*4887Schin {
114*4887Schin 	register struct stackblock	*b;
115*4887Schin 
116*4887Schin 	if (++stack->position.index >= stack->size)
117*4887Schin 	{
118*4887Schin 		b = stack->position.block;
119*4887Schin 		if (b->next) b = b->next;
120*4887Schin 		else
121*4887Schin 		{
122*4887Schin 			if (!(b->next = newof(0, struct stackblock, 1, 0)))
123*4887Schin 				return(-1);
124*4887Schin 			b = b->next;
125*4887Schin 			if (!(b->stack = newof(0, void*, stack->size, 0)))
126*4887Schin 				return(-1);
127*4887Schin 			b->prev = stack->position.block;
128*4887Schin 			b->next = 0;
129*4887Schin 		}
130*4887Schin 		stack->position.block = b;
131*4887Schin 		stack->position.index = 0;
132*4887Schin 	}
133*4887Schin 	stack->position.block->stack[stack->position.index] = value;
134*4887Schin 	return(0);
135*4887Schin }
136*4887Schin 
137*4887Schin /*
138*4887Schin  * pop value off stack
139*4887Schin  */
140*4887Schin 
141*4887Schin int
142*4887Schin stackpop(register STACK stack)
143*4887Schin {
144*4887Schin 	/*
145*4887Schin 	 * return:
146*4887Schin 	 *
147*4887Schin 	 *	-1	if stack empty before pop
148*4887Schin 	 *	 0	if stack empty after pop
149*4887Schin 	 *	 1	if stack not empty before & after pop
150*4887Schin 	 */
151*4887Schin 
152*4887Schin 	if (stack->position.index < 0) return(-1);
153*4887Schin 	else if (--stack->position.index < 0)
154*4887Schin 	{
155*4887Schin 		if (!stack->position.block->prev) return(0);
156*4887Schin 		stack->position.block = stack->position.block->prev;
157*4887Schin 		stack->position.index = stack->size - 1;
158*4887Schin 		return(1);
159*4887Schin 	}
160*4887Schin 	else return(1);
161*4887Schin }
162*4887Schin 
163*4887Schin /*
164*4887Schin  * set|get stack position
165*4887Schin  */
166*4887Schin 
167*4887Schin void
168*4887Schin stacktell(register STACK stack, int set, STACKPOS* position)
169*4887Schin {
170*4887Schin 	if (set) stack->position = *position;
171*4887Schin 	else *position = stack->position;
172*4887Schin }
173