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 #include <assert.h>
8
9 #include "nickle-config.h"
10 #include "mem.h"
11 #include "stack.h"
12
13 static void stackMark (void *);
14
15 DataType stackType = { stackMark, 0, "stackType" };
16
17 DataType stackChunkType = { 0, 0, "stackChunkType" };
18
19 static void
addChunk(StackObject * stack)20 addChunk (StackObject *stack)
21 {
22 StackChunk *chunk;
23
24 if (stack->save)
25 {
26 chunk = stack->save;
27 stack->save = 0;
28 }
29 else
30 chunk = MemAllocate (&stackChunkType, sizeof (StackChunk));
31
32 chunk->previous = stack->current;
33 stack->current = chunk;
34 STACK_TOP(stack) = CHUNK_MAX(chunk);
35 }
36
37 StackObject *
StackCreate(void)38 StackCreate (void)
39 {
40 StackObject *stack;
41
42 stack = MemAllocate (&stackType, sizeof (StackObject));
43 stack->current = 0;
44 stack->save = 0;
45 stack->temp = 0;
46 stack->stackPointer = 0;
47 TemporaryData = stack;
48 addChunk (stack);
49 TemporaryData = 0;
50 return stack;
51 }
52
53 void *
StackPush(StackObject * stack,StackElement object)54 StackPush (StackObject *stack, StackElement object)
55 {
56 STACK_ASSERT (stack);
57 if (STACK_TOP(stack) == STACK_MIN(stack))
58 {
59 stack->temp = object;
60 addChunk (stack);
61 stack->temp = 0;
62 }
63 return *--STACK_TOP(stack) = object;
64 }
65
66 void *
StackPop(StackObject * stack)67 StackPop (StackObject *stack)
68 {
69 STACK_ASSERT (stack);
70 if (STACK_TOP(stack) == STACK_MAX(stack))
71 {
72 StackChunk *previous = stack->current->previous;
73
74 if (!stack->save)
75 {
76 stack->save = stack->current;
77 stack->save->previous = 0;
78 }
79 stack->current = previous;
80 if (!stack->current)
81 panic ("Stack underflow\n");
82 STACK_TOP(stack) = previous->elements;
83 }
84 return *STACK_TOP(stack)++;
85 }
86
87 void
StackDrop(StackObject * stack,int i)88 StackDrop (StackObject *stack, int i)
89 {
90 int this;
91 StackChunk *previous;
92 STACK_ASSERT (stack);
93 while (i)
94 {
95 this = STACK_MAX(stack) - STACK_TOP(stack);
96 if (this >= i)
97 {
98 STACK_TOP(stack) += i;
99 break;
100 }
101 i -= this;
102 previous = stack->current->previous;
103
104 if (!stack->save)
105 {
106 stack->save = stack->current;
107 stack->save->previous = 0;
108 }
109 stack->current = previous;
110 if (!stack->current)
111 panic ("Stack underflow\n");
112 STACK_TOP(stack) = CHUNK_MIN(previous);
113 }
114 STACK_ASSERT (stack);
115 }
116
117 void
StackReset(StackObject * stack,StackPointer stackPointer)118 StackReset (StackObject *stack, StackPointer stackPointer)
119 {
120 STACK_ASSERT (stack);
121 while (!(STACK_TOP(stack) <= stackPointer && stackPointer <= STACK_MAX(stack)))
122 {
123 StackChunk *previous = stack->current->previous;
124
125 if (!stack->save)
126 {
127 stack->save = stack->current;
128 stack->save->previous = 0;
129 }
130 stack->current = previous;
131 if (!stack->current)
132 panic ("Stack underflow\n");
133 STACK_TOP(stack) = CHUNK_MIN(previous);
134 }
135 STACK_TOP(stack) = stackPointer;
136 STACK_ASSERT (stack);
137 }
138
139 StackElement
StackReturn(StackObject * stack,StackPointer stackPointer,StackElement object)140 StackReturn (StackObject *stack, StackPointer stackPointer, StackElement object)
141 {
142 STACK_ASSERT (stack);
143 STACK_RESET(stack, stackPointer);
144 return STACK_PUSH(stack,object);
145 }
146
147 StackElement
StackElt(StackObject * stack,int i)148 StackElt (StackObject *stack, int i)
149 {
150 StackChunk *chunk;
151 StackPointer stackPointer;
152
153 STACK_ASSERT (stack);
154 chunk = stack->current;
155 stackPointer = STACK_TOP(stack);
156 while (stackPointer + i >= CHUNK_MAX(chunk))
157 {
158 i -= CHUNK_MAX(chunk) - stackPointer;
159 chunk = chunk->previous;
160 if (!chunk)
161 panic ("StackElt underflow\n");
162 stackPointer = CHUNK_MIN(chunk);
163 }
164 return stackPointer[i];
165 }
166
167 StackObject *
StackCopy(StackObject * stack)168 StackCopy (StackObject *stack)
169 {
170 StackObject *new;
171 StackChunk *chunk, *nchunk, **prev;
172
173 STACK_ASSERT (stack);
174 new = StackCreate ();
175 REFERENCE (new);
176 chunk = stack->current;
177 nchunk = new->current;
178 prev = &new->current;
179 while (chunk)
180 {
181 STACK_ASSERT (new);
182 STACK_ASSERT (stack);
183 if (!nchunk)
184 nchunk = MemAllocate (&stackChunkType, sizeof (StackChunk));
185 else
186 STACK_TOP(new) = (new->current->elements +
187 (STACK_TOP(stack) - stack->current->elements));
188
189 /*
190 * Copy stack data and fix stack pointer
191 */
192 *nchunk = *chunk;
193 STACK_CHUNK_ASSERT(chunk->type == &stackChunkType);
194
195 /*
196 * Link into chain
197 */
198 *prev = nchunk;
199 prev = &nchunk->previous;
200 *prev = 0;
201 chunk = chunk->previous;
202 nchunk = 0;
203 }
204 STACK_ASSERT (new);
205 return new;
206 }
207
208 static void
stackMark(void * object)209 stackMark (void *object)
210 {
211 StackObject *stack = object;
212 StackChunk *chunk;
213 StackPointer stackPointer;
214
215 STACK_ASSERT (stack);
216 MemReference (stack->temp);
217 MemReference (stack->save);
218 chunk = stack->current;
219 if (chunk)
220 {
221 stackPointer = STACK_TOP(stack);
222 for (;;)
223 {
224 MemReference (chunk);
225 while (stackPointer != CHUNK_MAX(chunk))
226 MemReference (*stackPointer++);
227 chunk = chunk->previous;
228 if (!chunk)
229 break;
230 stackPointer = CHUNK_MIN(chunk);
231 }
232 }
233 }
234