1 /*
2  * Copyright © 1988-2004 Keith Packard and Bart Massey.
3  * All Rights Reserved.  See the file COPYING in this directory
4  * for licensing information.
5  */
6 
7 #ifndef _STACK_H_
8 #define _STACK_H_
9 #define STACK_ENTS_PER_CHUNK	126
10 
11 typedef void		*StackElement;
12 typedef StackElement	*StackPointer;
13 
14 typedef struct _StackChunk {
15     DataType		*type;
16     struct _StackChunk	*previous;
17     StackElement	elements[STACK_ENTS_PER_CHUNK];
18 } StackChunk;
19 
20 typedef struct _Stack {
21     DataType		*type;
22     StackPointer	stackPointer;
23     StackChunk		*current;
24     StackChunk		*save;
25     StackElement	temp;
26 } StackObject;
27 
28 extern StackObject  *StackCreate (void);
29 extern StackObject  *StackCopy (StackObject *stack);
30 extern StackElement StackPush (StackObject *stack, StackElement object);
31 extern StackElement StackPop (StackObject *stack);
32 extern void	    StackDrop (StackObject *stack, int i);
33 extern void	    StackReset (StackObject *stack, StackPointer stackPointer);
34 extern StackElement StackReturn (StackObject *stack, StackPointer stackPointer, StackElement object);
35 extern StackElement StackElt (StackObject *stack, int i);
36 
37 #define CHUNK_MAX(c)	((c)->elements + STACK_ENTS_PER_CHUNK)
38 #define CHUNK_MIN(c)	((c)->elements)
39 #define STACK_MAX(s)	(CHUNK_MAX((s)->current))
40 #define STACK_MIN(s)	(CHUNK_MIN((s)->current))
41 #define STACK_TOP(s)	((s)->stackPointer)
42 
43 #define STACK_POP(s)	    ((STACK_TOP(s) == STACK_MAX(s)) ? \
44 			     StackPop (s) : *STACK_TOP(s)++)
45 
46 #define STACK_DROP(s,i)	    ((STACK_TOP(s) + (i) <= STACK_MAX(s)) ? \
47 			     ((STACK_TOP(s) += (i)), 0) : (StackDrop(s, i), 0))
48 
49 #define STACK_RESET(s,sp)   (STACK_TOP(s) == (sp) ? 0 : \
50 			     ((STACK_TOP(s) <= (sp) && (sp) <= STACK_MAX(s)) ? \
51 			      ((STACK_TOP(s) = (sp)), 0) : \
52 			      (StackReset ((s), (sp)), 0)))
53 
54 #define STACK_ELT(s,i)	((STACK_TOP(s) + (i) < STACK_MAX(s)) ? \
55 			 STACK_TOP(s)[i] : StackElt(s,i))
56 
57 #if 0
58 #define STACK_VALID(s)	((!(s)->stackPointer && !(s)->current) || \
59 			 (STACK_MIN(s) <= STACK_TOP(s) && \
60 			  STACK_TOP(s) <= STACK_MAX(s)))
61 
62 void
63 panic (char *, ...);
64 
65 #define STACK_ASSERT(s)	if (!STACK_VALID(s)) panic ("invalid stack\n");
66 #define STACK_CHUNK_ASSERT(c)	assert((c)->type == &stackChunkType)
67 #else
68 #define STACK_ASSERT(s)
69 #define STACK_CHUNK_ASSERT(c)
70 #endif
71 
72 #if 0
73 /*
74  * Can't work -- o gets evaluated after the stack overflow check,
75  * if o also uses the stack, this will break
76  */
77 #define STACK_PUSH(s,o)	    ((STACK_TOP(s) == STACK_MIN(s)) ? \
78 			     StackPush ((s), (o)) : (*--STACK_TOP(s) = (o)))
79 #endif
80 
81 static inline StackElement
StackPushInline(StackObject * s,StackElement o)82 StackPushInline(StackObject *s, StackElement o)
83 {
84     STACK_ASSERT (s);
85     if (STACK_TOP(s) == STACK_MIN(s))
86 	return StackPush (s, o);
87     return *--STACK_TOP(s) = o;
88 }
89 #define STACK_PUSH(s,o) StackPushInline(s,o)
90 static inline StackElement
StackReturnInline(StackObject * s,StackPointer sp,StackElement o)91 StackReturnInline(StackObject *s, StackPointer sp, StackElement o)
92 {
93     STACK_ASSERT(s);
94     STACK_RESET(s, sp);
95     STACK_ASSERT(s);
96     if (STACK_TOP(s) == STACK_MIN(s))
97 	return StackPush (s, o);
98     return *--STACK_TOP(s) = o;
99 }
100 #define STACK_RETURN(s,sp,o) StackReturnInline(s,sp,o)
101 
102 #endif /* _STACK_H_ */
103