| /* | |
| * egman.c | |
| * | |
| * SOFTWARE RIGHTS | |
| * | |
| * We reserve no LEGAL rights to the Purdue Compiler Construction Tool | |
| * Set (PCCTS) -- PCCTS is in the public domain. An individual or | |
| * company may do whatever they wish with source code distributed with | |
| * PCCTS or the code generated by PCCTS, including the incorporation of | |
| * PCCTS, or its output, into commerical software. | |
| * | |
| * We encourage users to develop software with PCCTS. However, we do ask | |
| * that credit is given to us for developing PCCTS. By "credit", | |
| * we mean that if you incorporate our source code into one of your | |
| * programs (commercial product, research project, or otherwise) that you | |
| * acknowledge this fact somewhere in the documentation, research report, | |
| * etc... If you like PCCTS and have developed a nice tool with the | |
| * output, please mention that you developed it using PCCTS. In | |
| * addition, we ask that this header remain intact in our source code. | |
| * As long as these guidelines are kept, we expect to continue enhancing | |
| * this system and expect to make other tools available as they are | |
| * completed. | |
| * | |
| * ANTLR 1.33MR10 | |
| * 2001 | |
| * | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include "set.h" | |
| #include "syn.h" | |
| #include "hash.h" | |
| #include "generic.h" | |
| #include "proto.h" | |
| static ExceptionGroup **egArray=NULL; /* ExceptionGroup by BlkLevel */ | |
| static LabelEntry **leArray=NULL; /* LabelEntry by BlkLevel */ | |
| static Junction **altArray=NULL; /* start of alternates */ | |
| static int arraySize=0; | |
| static int highWater=0; | |
| static ExceptionGroup *lastEG=NULL; /* used in altFixup() */ | |
| static int lastBlkLevel=0; /* used in altFixup() */ | |
| #ifdef __USE_PROTOS | |
| static void arrayCheck(void); | |
| #else | |
| static void arrayCheck(); | |
| #endif | |
| /* Called to add an exception group for an alternative EG */ | |
| #ifdef __USE_PROTOS | |
| void egAdd(ExceptionGroup * eg) | |
| #else | |
| void egAdd(eg) | |
| ExceptionGroup *eg; | |
| #endif | |
| { | |
| int i; | |
| ExceptionGroup *nextEG; | |
| ExceptionGroup *innerEG; | |
| LabelEntry *nextLE; | |
| LabelEntry *innerLE; | |
| Junction *nextAlt; | |
| Junction *innerAlt; | |
| lastEG=eg; | |
| lastBlkLevel=BlkLevel; | |
| arrayCheck(); | |
| eg->pendingLink=egArray[BlkLevel]; | |
| egArray[BlkLevel]=eg; | |
| /* EG for alternates already have their altID filled in */ | |
| for (i=BlkLevel+1; i<=highWater ; i++) { | |
| for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) { | |
| nextEG=innerEG->pendingLink; | |
| innerEG->pendingLink=NULL; | |
| innerEG->outerEG=eg; | |
| }; | |
| egArray[i]=NULL; | |
| }; | |
| /* | |
| * for patching up the LabelEntry you might use an EG for the | |
| * current alternative - unlike patching up an alternative EG | |
| * i.e. start the loop at BlkLevel rather than (BlkLevel+1) | |
| * fill it in only if the EG and the LE are for the very | |
| * same alternative if they're at the same BlkLevel | |
| * it's easier to leave the LE on this list (filled in) rather than | |
| * trying to selectively remove it. It will eventually be | |
| * removed anyway when the BlkLevel gets small enough. | |
| */ | |
| for (i=BlkLevel; i<=highWater ; i++) { | |
| for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { | |
| nextLE=innerLE->pendingLink; | |
| if (BlkLevel != i || | |
| innerLE->curAltNum == CurAltNum_array[BlkLevel]) { | |
| if (innerLE->outerEG == NULL) { | |
| innerLE->outerEG=eg; | |
| }; | |
| }; | |
| }; | |
| if (BlkLevel != i) leArray[i]=NULL; | |
| }; | |
| /* | |
| * For the start of alternatives it is necessary to make a | |
| * distinction between the exception group for the current | |
| * alternative and the "fallback" EG for the block which | |
| * contains the alternative | |
| * | |
| * The fallback outerEG is used to handle the case where | |
| * no alternative of a block matches. In that case the | |
| * signal is "NoViableAlt" (or "NoSemViableAlt" and the | |
| * generator needs the EG of the block CONTAINING the | |
| * current one. | |
| * | |
| * rule: ( ( ( a | |
| * | b | |
| * ) | |
| * | c | |
| * ) | |
| * | d | |
| * ); | |
| */ | |
| for (i=BlkLevel; i <= highWater ; i++) { | |
| for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { | |
| nextAlt=innerAlt->pendingLink; | |
| /* first fill in the EG for the current alternative */ | |
| /* but leave it on the list in order to get the fallback EG */ | |
| /* if the EG is at the same LEVEL as the alternative then */ | |
| /* fill it in only if in the very same alternative */ | |
| /* */ | |
| /* rule: ( a */ | |
| /* | b */ | |
| /* | c exception ... */ | |
| /* ) */ | |
| /* */ | |
| /* if the EG is outside the alternative (e.g. BlkLevel < i) */ | |
| /* then it doesn't matter about the alternative */ | |
| /* */ | |
| /* rule: ( a */ | |
| /* | b */ | |
| /* | c */ | |
| /* ) exception ... */ | |
| /* */ | |
| #if 0 | |
| printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n", | |
| BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID); | |
| #endif | |
| if (BlkLevel != i || | |
| innerAlt->curAltNum == CurAltNum_array[BlkLevel]) { | |
| if (innerAlt->exception_label == NULL) { | |
| innerAlt->exception_label=eg->altID; | |
| }; | |
| }; | |
| /* ocurs at a later pass then for the exception_label */ | |
| /* if an outerEG has been found then fill in the outer EG */ | |
| /* remove if from the list when the BlkLevel gets smaller */ | |
| if (BlkLevel != i) { | |
| if (innerAlt->outerEG == NULL) { | |
| innerAlt->outerEG=eg; | |
| }; | |
| }; | |
| }; | |
| if (BlkLevel != i) altArray[i]=NULL; | |
| }; | |
| } | |
| #ifdef __USE_PROTOS | |
| void leAdd(LabelEntry * le) | |
| #else | |
| void leAdd(le) | |
| LabelEntry *le; | |
| #endif | |
| { | |
| arrayCheck(); | |
| le->pendingLink=leArray[BlkLevel]; | |
| le->curAltNum=CurAltNum_array[BlkLevel]; | |
| leArray[BlkLevel]=le; | |
| } | |
| #ifdef __USE_PROTOS | |
| void altAdd(Junction *alt) | |
| #else | |
| void altAdd(alt) | |
| Junction *alt; | |
| #endif | |
| { | |
| arrayCheck(); | |
| #if 0 | |
| printf("BlkLevel=%d CurAltNum=%d\n", | |
| BlkLevel,CurAltNum_array[BlkLevel]); | |
| #endif | |
| alt->curAltNum=CurAltNum_array[BlkLevel]; | |
| alt->pendingLink=altArray[BlkLevel]; | |
| altArray[BlkLevel]=alt; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| arrayCheck(void) | |
| #else | |
| arrayCheck() | |
| #endif | |
| { | |
| ExceptionGroup **egArrayNew; | |
| LabelEntry **leArrayNew; | |
| Junction **altArrayNew; | |
| int arraySizeNew; | |
| int i; | |
| if (BlkLevel > highWater) highWater=BlkLevel; | |
| if (BlkLevel >= arraySize) { | |
| arraySizeNew=BlkLevel+5; /* MR20 */ | |
| egArrayNew=(ExceptionGroup **) | |
| calloc(arraySizeNew,sizeof(ExceptionGroup *)); | |
| leArrayNew=(LabelEntry **) | |
| calloc(arraySizeNew,sizeof(LabelEntry *)); | |
| altArrayNew=(Junction **) | |
| calloc(arraySizeNew,sizeof(Junction *)); | |
| for (i=0; i<arraySize ; i++) { | |
| egArrayNew[i]=egArray[i]; | |
| leArrayNew[i]=leArray[i]; | |
| altArrayNew[i]=altArray[i]; | |
| }; | |
| arraySize=arraySizeNew; | |
| if (egArray != NULL) free( (char *) egArray); | |
| if (leArray != NULL) free( (char *) leArray); | |
| if (altArray != NULL) free( (char *) altArray); | |
| egArray=egArrayNew; | |
| leArray=leArrayNew; | |
| altArray=altArrayNew; | |
| }; | |
| } | |
| /* always call leFixup() BEFORE egFixup() */ | |
| void | |
| #ifdef __USE_PROTOS | |
| egFixup(void) | |
| #else | |
| egFixup() | |
| #endif | |
| { | |
| int i; | |
| ExceptionGroup *nextEG; | |
| ExceptionGroup *innerEG; | |
| for (i=1; i<=highWater ; i++) { | |
| for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) { | |
| nextEG=innerEG->pendingLink; | |
| innerEG->pendingLink=NULL; | |
| }; | |
| egArray[i]=NULL; | |
| }; | |
| lastEG=NULL; | |
| lastBlkLevel=0; | |
| } | |
| /* always call leFixup() BEFORE egFixup() */ | |
| #ifdef __USE_PROTOS | |
| void leFixup(void) | |
| #else | |
| void leFixup() | |
| #endif | |
| { | |
| int i; | |
| LabelEntry *nextLE; | |
| LabelEntry *innerLE; | |
| for (i=BlkLevel; i<=highWater ; i++) { | |
| for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { | |
| nextLE=innerLE->pendingLink; | |
| innerLE->pendingLink=NULL; | |
| }; | |
| leArray[i]=NULL; | |
| }; | |
| } | |
| /* always call altFixup() BEFORE egFixup() */ | |
| #ifdef __USE_PROTOS | |
| void altFixup(void) | |
| #else | |
| void altFixup() | |
| #endif | |
| { | |
| int i; | |
| Junction *nextAlt; | |
| Junction *innerAlt; | |
| for (i=BlkLevel; i<=highWater ; i++) { | |
| for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { | |
| /* if an outerEG has been found then fill in the outer EG */ | |
| if (lastBlkLevel <= i) { | |
| if (innerAlt->outerEG == NULL) { | |
| innerAlt->outerEG=lastEG; | |
| }; | |
| }; | |
| nextAlt=innerAlt->pendingLink; | |
| innerAlt->pendingLink=NULL; | |
| }; | |
| altArray[i]=NULL; | |
| }; | |
| } | |