git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			329 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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;
 | |
|   };
 | |
| }
 | |
| 
 |