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