1 /*
2 * egman.c
3 *
4 * SOFTWARE RIGHTS
5 *
6 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
7 * Set (PCCTS) -- PCCTS is in the public domain. An individual or
8 * company may do whatever they wish with source code distributed with
9 * PCCTS or the code generated by PCCTS, including the incorporation of
10 * PCCTS, or its output, into commerical software.
11 *
12 * We encourage users to develop software with PCCTS. However, we do ask
13 * that credit is given to us for developing PCCTS. By "credit",
14 * we mean that if you incorporate our source code into one of your
15 * programs (commercial product, research project, or otherwise) that you
16 * acknowledge this fact somewhere in the documentation, research report,
17 * etc... If you like PCCTS and have developed a nice tool with the
18 * output, please mention that you developed it using PCCTS. In
19 * addition, we ask that this header remain intact in our source code.
20 * As long as these guidelines are kept, we expect to continue enhancing
21 * this system and expect to make other tools available as they are
22 * completed.
23 *
24 * ANTLR 1.33MR10
25 * 2001
26 *
27 */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "set.h"
33 #include "syn.h"
34 #include "hash.h"
35 #include "generic.h"
36 #include "proto.h"
37
38 static ExceptionGroup **egArray=NULL; /* ExceptionGroup by BlkLevel */
39 static LabelEntry **leArray=NULL; /* LabelEntry by BlkLevel */
40 static Junction **altArray=NULL; /* start of alternates */
41 static int arraySize=0;
42 static int highWater=0;
43 static ExceptionGroup *lastEG=NULL; /* used in altFixup() */
44 static int lastBlkLevel=0; /* used in altFixup() */
45
46 #ifdef __USE_PROTOS
47 static void arrayCheck(void);
48 #else
49 static void arrayCheck();
50 #endif
51
52 /* Called to add an exception group for an alternative EG */
53
54 #ifdef __USE_PROTOS
egAdd(ExceptionGroup * eg)55 void egAdd(ExceptionGroup * eg)
56 #else
57 void egAdd(eg)
58 ExceptionGroup *eg;
59 #endif
60 {
61 int i;
62
63 ExceptionGroup *nextEG;
64 ExceptionGroup *innerEG;
65
66 LabelEntry *nextLE;
67 LabelEntry *innerLE;
68
69 Junction *nextAlt;
70 Junction *innerAlt;
71
72 lastEG=eg;
73 lastBlkLevel=BlkLevel;
74
75 arrayCheck();
76 eg->pendingLink=egArray[BlkLevel];
77 egArray[BlkLevel]=eg;
78
79 /* EG for alternates already have their altID filled in */
80
81 for (i=BlkLevel+1; i<=highWater ; i++) {
82 for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) {
83 nextEG=innerEG->pendingLink;
84 innerEG->pendingLink=NULL;
85 innerEG->outerEG=eg;
86 };
87 egArray[i]=NULL;
88 };
89
90 /*
91 * for patching up the LabelEntry you might use an EG for the
92 * current alternative - unlike patching up an alternative EG
93 * i.e. start the loop at BlkLevel rather than (BlkLevel+1)
94 * fill it in only if the EG and the LE are for the very
95 * same alternative if they're at the same BlkLevel
96 * it's easier to leave the LE on this list (filled in) rather than
97 * trying to selectively remove it. It will eventually be
98 * removed anyway when the BlkLevel gets small enough.
99 */
100
101 for (i=BlkLevel; i<=highWater ; i++) {
102 for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) {
103 nextLE=innerLE->pendingLink;
104 if (BlkLevel != i ||
105 innerLE->curAltNum == CurAltNum_array[BlkLevel]) {
106 if (innerLE->outerEG == NULL) {
107 innerLE->outerEG=eg;
108 };
109 };
110 };
111 if (BlkLevel != i) leArray[i]=NULL;
112 };
113
114 /*
115 * For the start of alternatives it is necessary to make a
116 * distinction between the exception group for the current
117 * alternative and the "fallback" EG for the block which
118 * contains the alternative
119 *
120 * The fallback outerEG is used to handle the case where
121 * no alternative of a block matches. In that case the
122 * signal is "NoViableAlt" (or "NoSemViableAlt" and the
123 * generator needs the EG of the block CONTAINING the
124 * current one.
125 *
126 * rule: ( ( ( a
127 * | b
128 * )
129 * | c
130 * )
131 * | d
132 * );
133 */
134
135 for (i=BlkLevel; i <= highWater ; i++) {
136 for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) {
137 nextAlt=innerAlt->pendingLink;
138
139 /* first fill in the EG for the current alternative */
140 /* but leave it on the list in order to get the fallback EG */
141 /* if the EG is at the same LEVEL as the alternative then */
142 /* fill it in only if in the very same alternative */
143 /* */
144 /* rule: ( a */
145 /* | b */
146 /* | c exception ... */
147 /* ) */
148 /* */
149 /* if the EG is outside the alternative (e.g. BlkLevel < i) */
150 /* then it doesn't matter about the alternative */
151 /* */
152 /* rule: ( a */
153 /* | b */
154 /* | c */
155 /* ) exception ... */
156 /* */
157
158 #if 0
159 printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n",
160 BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID);
161 #endif
162 if (BlkLevel != i ||
163 innerAlt->curAltNum == CurAltNum_array[BlkLevel]) {
164 if (innerAlt->exception_label == NULL) {
165 innerAlt->exception_label=eg->altID;
166 };
167 };
168
169 /* ocurs at a later pass then for the exception_label */
170 /* if an outerEG has been found then fill in the outer EG */
171 /* remove if from the list when the BlkLevel gets smaller */
172
173 if (BlkLevel != i) {
174 if (innerAlt->outerEG == NULL) {
175 innerAlt->outerEG=eg;
176 };
177 };
178 };
179 if (BlkLevel != i) altArray[i]=NULL;
180 };
181 }
182
183 #ifdef __USE_PROTOS
leAdd(LabelEntry * le)184 void leAdd(LabelEntry * le)
185 #else
186 void leAdd(le)
187 LabelEntry *le;
188 #endif
189
190 {
191 arrayCheck();
192 le->pendingLink=leArray[BlkLevel];
193 le->curAltNum=CurAltNum_array[BlkLevel];
194 leArray[BlkLevel]=le;
195 }
196
197 #ifdef __USE_PROTOS
altAdd(Junction * alt)198 void altAdd(Junction *alt)
199 #else
200 void altAdd(alt)
201 Junction *alt;
202 #endif
203
204 {
205 arrayCheck();
206 #if 0
207 printf("BlkLevel=%d CurAltNum=%d\n",
208 BlkLevel,CurAltNum_array[BlkLevel]);
209 #endif
210 alt->curAltNum=CurAltNum_array[BlkLevel];
211 alt->pendingLink=altArray[BlkLevel];
212 altArray[BlkLevel]=alt;
213 }
214
215 static void
216 #ifdef __USE_PROTOS
arrayCheck(void)217 arrayCheck(void)
218 #else
219 arrayCheck()
220 #endif
221 {
222 ExceptionGroup **egArrayNew;
223 LabelEntry **leArrayNew;
224 Junction **altArrayNew;
225 int arraySizeNew;
226 int i;
227
228 if (BlkLevel > highWater) highWater=BlkLevel;
229
230 if (BlkLevel >= arraySize) {
231 arraySizeNew=BlkLevel+5; /* MR20 */
232 egArrayNew=(ExceptionGroup **)
233 calloc(arraySizeNew,sizeof(ExceptionGroup *));
234 leArrayNew=(LabelEntry **)
235 calloc(arraySizeNew,sizeof(LabelEntry *));
236 altArrayNew=(Junction **)
237 calloc(arraySizeNew,sizeof(Junction *));
238 for (i=0; i<arraySize ; i++) {
239 egArrayNew[i]=egArray[i];
240 leArrayNew[i]=leArray[i];
241 altArrayNew[i]=altArray[i];
242 };
243 arraySize=arraySizeNew;
244 if (egArray != NULL) free( (char *) egArray);
245 if (leArray != NULL) free( (char *) leArray);
246 if (altArray != NULL) free( (char *) altArray);
247 egArray=egArrayNew;
248 leArray=leArrayNew;
249 altArray=altArrayNew;
250 };
251 }
252
253 /* always call leFixup() BEFORE egFixup() */
254
255 void
256 #ifdef __USE_PROTOS
egFixup(void)257 egFixup(void)
258 #else
259 egFixup()
260 #endif
261 {
262 int i;
263 ExceptionGroup *nextEG;
264 ExceptionGroup *innerEG;
265
266 for (i=1; i<=highWater ; i++) {
267 for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) {
268 nextEG=innerEG->pendingLink;
269 innerEG->pendingLink=NULL;
270 };
271 egArray[i]=NULL;
272 };
273 lastEG=NULL;
274 lastBlkLevel=0;
275 }
276
277 /* always call leFixup() BEFORE egFixup() */
278
279 #ifdef __USE_PROTOS
leFixup(void)280 void leFixup(void)
281 #else
282 void leFixup()
283 #endif
284 {
285
286 int i;
287 LabelEntry *nextLE;
288 LabelEntry *innerLE;
289
290 for (i=BlkLevel; i<=highWater ; i++) {
291 for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) {
292 nextLE=innerLE->pendingLink;
293 innerLE->pendingLink=NULL;
294 };
295 leArray[i]=NULL;
296 };
297 }
298
299 /* always call altFixup() BEFORE egFixup() */
300
301 #ifdef __USE_PROTOS
altFixup(void)302 void altFixup(void)
303 #else
304 void altFixup()
305 #endif
306 {
307
308 int i;
309 Junction *nextAlt;
310 Junction *innerAlt;
311
312 for (i=BlkLevel; i<=highWater ; i++) {
313 for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) {
314
315 /* if an outerEG has been found then fill in the outer EG */
316
317 if (lastBlkLevel <= i) {
318 if (innerAlt->outerEG == NULL) {
319 innerAlt->outerEG=lastEG;
320 };
321 };
322 nextAlt=innerAlt->pendingLink;
323 innerAlt->pendingLink=NULL;
324 };
325 altArray[i]=NULL;
326 };
327 }
328
329