// Copyright (c) 1993-1999 Microsoft Corporation /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The s switch has been introduced to allow yacc to generate extended tables for MIDL error recovery and reporting scheme. The following are the routines which take part in s switch processing: . EmitStateVsExpectedConstruct . EmitStateGotoTable . SSwitchInit . SSwitchExit The global int variable ssw is 0 if s switch is not specified, non-zero otherwise. This is set in ysetup.c If the sswitch is specified, the i switch is automatically enabled. ----------------------------------------------------------------------------*/ #include #include #include "y3.h" #include "y4.h" extern int ssw; FILE *tokxlathdl;/* token xlation file,token index vs value*/ FILE *stgotohdl; /* state goto table file handle */ FILE *stexhdl; /* state vs expected construct handle */ short MaxStateVsTokenCount = 0; short MaxTokenVsStateCount = 0; short *pTokenVsStateCount; SSIZE_T MaxTokenValue = 0; short NStates = 0; int StateVsExpectedCount = 0; void wrstate( int i) { /* writes state i */ register j0; SSIZE_T j1; register struct item *pp, *qq; register struct wset *u; if( foutput == NULL ) return; SSwitchInit(); fprintf( foutput, "\nstate %d\n",i); ITMLOOP(i,pp,qq) { fprintf( foutput, "\t%s\n", writem(pp->pitem)); EmitStateVsExpectedConstruct( i, pp->pitem ); } if( tystate[i] == MUSTLOOKAHEAD ) { /* print out empty productions in closure */ WSLOOP( wsets+(pstate[i+1]-pstate[i]), u ) { if( *(u->pitem) < 0 ) fprintf( foutput, "\t%s\n", writem(u->pitem) ); } } /* check for state equal to another */ TLOOP(j0) { if( (j1=temp1[j0]) != 0 ) { fprintf( foutput, "\n\t%s ", symnam(j0) ); if( j1>0 ) { /* shift, error, or accept */ if( j1 == ACCEPTCODE ) fprintf( foutput, "accept" ); else if( j1 == ERRCODE ) fprintf( foutput, "error" ); else fprintf( foutput, "shift %d", j1 ); } else fprintf( foutput, "reduce %d",-j1 ); } } /* output any s switch information */ EmitStateGotoTable( i ); /* output the final production */ if( lastred ) fprintf( foutput, "\n\t. reduce %d\n\n", lastred ); else fprintf( foutput, "\n\t. error\n\n" ); /* now, output nonterminal actions */ j1 = ntokens; for( j0 = 1; j0 <= nnonter; ++j0 ) { if( temp1[++j1] ) fprintf( foutput, "\t%s goto %d\n", symnam( j0+NTBASE), temp1[j1] ); } } void wdef( char *s, int n ) { /* output a definition of s to the value n */ fprintf( ftable, "# define %s %d\n", s, n ); } void EmitStateGotoTable( int i ) { register int j0; short count = 0; #define TLOOP_0(i) for(i=0;i<=ntokens;++i) if( ssw ) { NStates++; TLOOP_0( j0 ) { if( (temp1[ j0 ] > 0 ) && (temp1[ j0 ] != ACCEPTCODE ) ) count++; } if( count >= MaxStateVsTokenCount ) MaxStateVsTokenCount = count; fprintf( stgotohdl, "%.4d : %.4d : ", i, count ); TLOOP_0( j0 ) { if( (temp1[ j0 ] > 0 ) && (temp1[ j0 ] != ACCEPTCODE ) ) { fprintf( stgotohdl, " %.4d, %.4d", temp1[ j0 ], j0 ); pTokenVsStateCount[ j0 ] += 1; if( pTokenVsStateCount[ j0 ] >= MaxTokenVsStateCount ) MaxTokenVsStateCount = pTokenVsStateCount[ j0 ]; } } fprintf( stgotohdl, "\n"); } } void EmitStateVsExpectedConstruct( int state, SSIZE_T *pp ) { SSIZE_T i,*p; // char *q; int flag = 0; int Count; if( ssw ) { for( p=pp; *p>0 ; ++p ) ; p = prdptr[-*p]; // fprintf( stexhdl, " %s", nontrst[ *p-NTBASE ].name ); fprintf( stexhdl, " %.4d : ", state ); Count = CountStateVsExpectedConstruct( state, pp ); StateVsExpectedCount += Count; fprintf( stexhdl, " %.4d : ",Count ); for(;;) { if( ++p==pp ) { if( ( i = *p ) <= 0 ) { fprintf( stexhdl, "\n" ); return; } else fprintf( stexhdl, "%s\n", symnam(i) ); } if( p >= pp ) return; } } } int CountStateVsExpectedConstruct( int state, SSIZE_T *pp ) { SSIZE_T i,*p; int flag = 0; int Count = 0; if( ssw ) { for( p=pp; *p>0 ; ++p ) ; p = prdptr[-*p]; for(;;) { if( ++p==pp ) { if( ( i = *p ) <= 0 ) { return Count; } else ++Count; } if( p >= pp ) return Count; } } return Count; /* NOTREACHED */ } void SSwitchInit() { static sswitch_inited = 0; int i = 0; if( ssw && ! sswitch_inited ) { tokxlathdl = fopen( "extable.h1" , "w" ); if ( NULL == tokxlathdl ) {error("Unable to open tokxlathdl" );exit(0);} /* output the token index vs the token value table */ fprintf( tokxlathdl, "%d %d\n", ntokens+1, ACCEPTCODE ); while( i <= ntokens ) { fprintf( tokxlathdl , "%d ", tokset[ i ].value); if( tokset[ i ].value >= MaxTokenValue ) MaxTokenValue = tokset[ i ].value; ++i; } fprintf(tokxlathdl, "\n"); /* set up for the state vs expected construct */ stexhdl = fopen( "extable.h2", "w" ); if ( NULL == stexhdl ) error("Unable to open extable.h2"); /* set up for state goto table */ stgotohdl = fopen( "extable.h3", "w"); if ( NULL == stgotohdl ) error("Unable to open extable.h3"); /* set up state vs token count array */ pTokenVsStateCount = calloc( 1, (ntokens+1 ) * sizeof(short) ); if ( NULL == pTokenVsStateCount ) error("Out of memory"); sswitch_inited = 1; } } void SSwitchExit( void ) { int i; if( ssw ) { /** print the token index vs goto count **/ for( i = 0; i <= ntokens ; ++i ) { fprintf( tokxlathdl , "%d ", pTokenVsStateCount[ i ]); } fprintf( tokxlathdl, "\n"); fprintf( tokxlathdl, "%d %d %d %d %d \n", NStates, MaxTokenVsStateCount, MaxStateVsTokenCount, MaxTokenValue, StateVsExpectedCount ); fclose( tokxlathdl ); fclose( stexhdl ); fclose( stgotohdl ); } }