Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

807 lines
20 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
ebase.c
Abstract:
This file generates the error recovery data base.
Notes:
1. Inputs to this module are the extable.* files generated by yacc in
response to the s switch.
2. Take the state vs token index file ( extable.h3 ), and generate the
state vs token table using the token index to token value
translations provided by extable.h1
3. Take the state vs expected RHS file ( extable.h2 ) and generate a
data base of expected RHS in every state.
Author:
vibhasc 11-15-91
----------------------------------------------------------------------------*/
/*****************************************************************************
local defines and includes
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include "ebase.h"
#define STATE_VS_TOKEN_INDEX_FILE "extable.h3"
#define TOKEN_TRANSLATION_FILE "extable.h1"
#define STATE_VS_EXPECTED_FILE "extable.h2"
#define ISVALIDTOKEN( i ) (TRUE)
#define MAX_TRANSLATION_LINE_SIZE (512)
#define TRUE 1
#define FALSE 0
/* from winerror.h */
#define ERROR_INVALID_DATA 13
#define CHECK_FSCAN_STATUS( fscanfcall ) \
if ( EOF == (fscanfcall) ) \
{ \
fprintf( stderr, \
"\nmidleb : error MIDLEB%d : unexpected end of input stream", \
ERROR_INVALID_DATA ); \
exit( ERROR_INVALID_DATA ); \
}
typedef unsigned int BOOL;
typedef enum _status
{
STATUS_OK = 0,
OUT_OF_MEMORY,
CANT_OPEN_INPUT_FILE,
CANT_OPEN_OUTPUT_FILE,
WRONG_ARGUMENT_COUNT
} STATUS_T;
typedef struct _xlat
{
char * pIncoming;
char * pTranslated;
struct _xlat *pNext;
} XLAT;
typedef struct _DBENTRY
{
short State;
char * pTranslated;
} DBENTRY;
/*****************************************************************************
global data
*****************************************************************************/
FILE * hStateVsTokenIndexFile;
FILE * hStateVsExpectedFile;
FILE * hOutput;
FILE * hXlatFile;
FILE * hTokXlatHdl;
SGOTO ** pSGoto;
short * pSGotoCount;
short ** pTokVsState;
short * pTokVsStateIndex;
short ValidStates;
short ValidTokens;
char * pPrefix;
XLAT * pXlat = 0,
* pXlatCur = 0;
DBENTRY * pDataBase;
short NTOKENS;
short ACCEPTCODE;
short * TokVal;
short * TokCount;
short NSTATES;
short MAXTOKVSSTATE;
short MAXSTATEVSTOK;
short MAXTOKENVALUE;
short MAXSTATEVSEXPECTED;
/*****************************************************************************
external procedures
*****************************************************************************/
STATUS_T Init( char *, char * );
STATUS_T Generate( FILE * );
STATUS_T OpenFileForReadProcessing( FILE **, char * );
void Dump( void );
BOOL SearchForStateInTokenVsState( short, short );
void TranslateExpectedConstructs( void );
char * Translate( char * );
void
main(
int argc,
char *argv[] )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
the main routine.
Arguments:
Standard
Return Value:
Exit Status
Notes:
Usage : ebase <OutputFilename> <Xlatefile> <prefix>
Xlatefile is the file where production names to message translation
is specified.
prefix is idl or acf. The expected string array is created with a
standard name prefixed with the user specified prefix.
----------------------------------------------------------------------------*/
{
STATUS_T Status;
fprintf( stderr, "Error Recovery Data Base Generator\n" );
if( argc == 4 )
{
pPrefix = argv[ 3 ];
if( (Status = Init( argv[ 1 ], argv[ 2 ] )) == STATUS_OK )
{
Status = Generate( hStateVsTokenIndexFile );
}
Dump();
TranslateExpectedConstructs();
}
else
{
fprintf( stderr, "Wrong argument count\n" );
fprintf( stderr, "Usage : midleb <output file or - > <translation-file-name> <prefix>\n");
Status = WRONG_ARGUMENT_COUNT;
}
exit( Status );
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Initialize
Arguments:
OutputName : output file name
XlatFilename : the production/token name to error message translation.
Return Value:
STATUS_T - OUT_OF_MEMORY or
- CANT_OPEN_INPUT_FILE or
- STATUS_OK
Notes:
Sets up the file handles for all the files that need to be read from
----------------------------------------------------------------------------*/
STATUS_T
Init(
char * OutputFileName,
char * XlatFileName )
{
STATUS_T Status;
int i;
Status = OpenFileForReadProcessing(
&hStateVsTokenIndexFile,
STATE_VS_TOKEN_INDEX_FILE );
if( Status == STATUS_OK )
{
Status = OpenFileForReadProcessing(
&hStateVsExpectedFile,
STATE_VS_EXPECTED_FILE );
if( Status == STATUS_OK )
{
Status = OpenFileForReadProcessing(
&hTokXlatHdl,
TOKEN_TRANSLATION_FILE );
if( Status == STATUS_OK )
{
Status = OpenFileForReadProcessing( &hXlatFile, XlatFileName );
if( Status == STATUS_OK )
{
if( strcmp( OutputFileName, "-" ) == 0 )
hOutput = stdout;
else if( (hOutput = fopen( OutputFileName , "w" )) == (FILE *)0 )
{
Status = CANT_OPEN_OUTPUT_FILE;
};
}
}
}
}
if( Status != STATUS_OK )
return Status;
/** read in the required numbers from the TOKEN_TRANSLATION_FILE **/
CHECK_FSCAN_STATUS(
fscanf( hTokXlatHdl, "%hd %hd\n", &NTOKENS, &ACCEPTCODE ) );
/** read in the token translation table **/
TokVal = (short *)calloc( 1, NTOKENS * sizeof( short ) );
TokCount = (short *)calloc( 1, NTOKENS * sizeof( short ) );
if (!TokVal || !TokCount )
{
fprintf( stderr, "Out of memory.\n");
exit(OUT_OF_MEMORY);
}
for( i = 0;
i < NTOKENS;
i++ )
{
CHECK_FSCAN_STATUS(
fscanf( hTokXlatHdl, "%hd", &TokVal[ i ]) );
}
CHECK_FSCAN_STATUS(
fscanf( hTokXlatHdl, "\n" ) );
for( i = 0;
i < NTOKENS;
i++ )
{
CHECK_FSCAN_STATUS(
fscanf( hTokXlatHdl, "%hd", &TokCount[ i ]) );
}
CHECK_FSCAN_STATUS(
fscanf( hTokXlatHdl, "\n" ) );
CHECK_FSCAN_STATUS(
fscanf( hTokXlatHdl,
"%hd %hd %hd %hd %hd\n",
&NSTATES,
&MAXTOKVSSTATE,
&MAXSTATEVSTOK,
&MAXTOKENVALUE,
&MAXSTATEVSEXPECTED ) );
/** allocate memory now **/
pSGoto = (SGOTO **) calloc( 1,NSTATES * sizeof( SGOTO * ) );
pSGotoCount = (short *)calloc(1, NSTATES * sizeof( short ) );
pTokVsState = (short **)calloc( 1,(MAXTOKENVALUE+1) * sizeof( short * ) );
pTokVsStateIndex = (short *)calloc(1, (MAXTOKENVALUE+1) * sizeof( short ) );
pDataBase = ( DBENTRY * )calloc( 1, MAXSTATEVSEXPECTED * sizeof( DBENTRY ) );
if( !pSGoto || !pSGotoCount || !pTokVsState || !pTokVsStateIndex || !pDataBase )
{
fprintf( stderr, "Out of memory.\n");
exit(OUT_OF_MEMORY);
}
return Status;
}
STATUS_T
Generate(
FILE * hSVsTIndexFile )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Generate the state vs token table, given the state vs token index table
in extable.h3 and token vs token index translation of extable.h1.
Arguments:
hStateVsTokenIndexFile - handle to the file which has the state vs
token index info.
Return Value:
None.
Notes:
The state vs token index file has the goto info for every valid token,
For every state, this file contains the goto ( or none ) for every valid
token ( represented by the token index ). Thus for each state, we lookup
to see if the state has a goto for a given token index. If it does, then
we translate the token index into a token value, and mark the goto for the
state for that token in the state vs token table.
In the end we will have a very sparse array, which contains all the states
and the gotos for the state for each token ( or the absence of any goto ).
We will use this table to generate two tables:
1. The set of all states which have a goto on a token
2. The set of all tokens valid for any state.
The exception to this rule is the accept action which is treated like
an absence of goto.
----------------------------------------------------------------------------*/
{
short iState,i,j,Temp,SGotoCount;
SGOTO *p;
/** fixup pointers to token vs state pointer array **/
for( i = 0;
i < NTOKENS;
i++ )
{
if( TokCount[ i ] )
{
j = TokVal[ i ];
if( ISVALIDTOKEN( j ) )
{
pTokVsState[ j ] = calloc( 1, TokCount[ i ] * sizeof( short ) );
if (!pTokVsState[ j ])
{
fprintf( stderr, "Out of memory.\n" );
exit( OUT_OF_MEMORY );
}
}
}
}
for( iState = 0;
iState < NSTATES;
++iState )
{
/** ignore the state number */
CHECK_FSCAN_STATUS(
fscanf( hSVsTIndexFile,
"%hd %c",
&Temp,
&Temp ) );
/** get the count of number of state goto entries **/
CHECK_FSCAN_STATUS(
fscanf( hSVsTIndexFile,
"%hd %c",
&SGotoCount,
&Temp ) );
/** now read in the goto vs token pairs **/
if( SGotoCount )
{
p = pSGoto[ iState ] = calloc( 1, SGotoCount * sizeof( SGOTO ) );
if (!p)
{
fprintf( stderr, "Out of memory.\n" );
exit( OUT_OF_MEMORY );
}
for( j = 0;
j < SGotoCount;
++j )
{
CHECK_FSCAN_STATUS(
fscanf( hSVsTIndexFile,
"%hd%c %hd",
&p->Goto,
&Temp,
&p->Token ) );
Temp = TokVal[ p->Token ];
if( ISVALIDTOKEN( Temp ) )
{
if( !SearchForStateInTokenVsState( Temp, p->Goto ) )
{
i = pTokVsStateIndex[ Temp ];
pTokVsStateIndex[ Temp ]++;
*(pTokVsState[Temp] + i ) = p->Goto;
}
p++;
pSGotoCount[ iState ]++;
}
}
}
}
return STATUS_OK;
}
STATUS_T
OpenFileForReadProcessing(
FILE ** pHandle,
char * pName )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
This process opens a file for read processing, reports an error if
the file could not be opened.
Arguments:
pHandle - pointer to a file handle deposition area.
pName - pointer to a file name, null terminated.
Return Value:
STATUS_T - STATUS_OK if all is well.
- CANT_OPEN_INPUT_FILE otherwise.
Notes:
----------------------------------------------------------------------------*/
{
FILE *hF;
if( ( hF = fopen( pName, "r" ) ) == (FILE *)NULL )
{
fprintf( stderr, "Cannot open input file : %s\n", pName );
return CANT_OPEN_INPUT_FILE;
}
*pHandle = hF;
return STATUS_OK;
}
void
Dump( void )
{
SGOTO * p;
short iTemp, i,j;
/** dump the state goto table **/
for( iTemp = 0, ValidStates = 0;
iTemp < NSTATES;
++iTemp )
{
p = pSGoto[ iTemp ];
if( j = pSGotoCount[ iTemp ] )
{
fprintf( hOutput, "\n SGOTO _sG%s%.4hd [ %d ] = { ", pPrefix, iTemp, j );
for( i = 0;
i < j;
i++ )
{
fprintf( hOutput
, " {%hd, %hd} %c"
, p[ i ].Goto
, TokVal[ p[ i ].Token]
, ( (i+1 == j) ? ' ' : ',' ));
}
fprintf( hOutput, "};" );
ValidStates++;
}
}
/** now dump the array of pointers to this **/
fprintf( hOutput, "\n\n#define VALIDSTATES_%s %d\n", pPrefix, ValidStates );
fprintf( hOutput, "\n\nSGOTOVECTOR SGoto%s[ VALIDSTATES_%s ] = {\n",pPrefix, pPrefix);
for( i = 0;
i < NSTATES;
++i )
{
if( pSGotoCount[ i ] )
{
fprintf( hOutput, "\n{ %d, _sG%s%.4hd, %d }"
, i
,pPrefix
, i
, pSGotoCount[ i ] );
fprintf( hOutput,"%c", ((i + 1 == NSTATES) ? ' ' : ',' ));
}
}
fprintf( hOutput, "\n};\n\n" );
/** count the valid token entries. i.e tokens for which states exist **/
fprintf(hOutput, "#if 0\n");
for( ValidTokens = 0, i = 0;
i < MAXTOKENVALUE;
++i )
{
if( pTokVsStateIndex[ i ] )
ValidTokens++;
}
/** dump the token vs state table **/
for( iTemp = 0;
iTemp < NTOKENS;
++iTemp )
{
if( j = pTokVsStateIndex[ TokVal[ iTemp ] ] )
{
fprintf( hOutput, "short _tS%s%.4d[ %d ] = {", pPrefix, TokVal[ iTemp ], j );
for( i = 0;
i < j;
++i )
{
fprintf( hOutput, " %d %c", *(pTokVsState[ TokVal[ iTemp ] ]+i),
(( i + 1 == j ) ? ' ' : ',' ));
}
fprintf( hOutput, "};\n" );
}
}
/** dump the vectors to the token vs state table **/
fprintf(hOutput, "\n#define VALIDTOKENS %d\n", ValidTokens );
fprintf( hOutput, "\nTOKVSSTATEVECTOR TokVsState%s[ VALIDTOKENS ] = { \n",pPrefix);
for( i = 0;
i < MAXTOKENVALUE+1;
++i )
{
if( j = pTokVsStateIndex[ i ])
{
fprintf( hOutput, "\n{ %d, _tS%s%.4d, %d }",i, pPrefix, i, j );
fprintf(hOutput, "%c", (i + 1 == NTOKENS) ? ' ' : ',' );
}
}
fprintf( hOutput, "\n\n};\n" );
fprintf( hOutput, "\n" );
fprintf(hOutput, "#endif\n");
}
BOOL
SearchForStateInTokenVsState(
short TokenValue,
short Goto )
{
int i,j;
for( i = 0, j = pTokVsStateIndex[ TokenValue ];
i < j;
++i )
{
if( *(pTokVsState[ TokenValue ] + i) == Goto )
return TRUE;
}
return FALSE;
}
void
TranslateExpectedConstructs( void )
{
int i,State,Count,Temp;
char Buffer[ MAX_TRANSLATION_LINE_SIZE ];
char Buffer1[ MAX_TRANSLATION_LINE_SIZE ];
DBENTRY *p;
XLAT *pX;
/**
firstly, read in the translation data base, which shows the
expected token name vs the actual error string the compiler wants to
output.
**/
for(;;)
{
i = fscanf( hXlatFile,
"%[^ \t]%1s%[^\n]\n",
Buffer,
&Temp,
Buffer1 );
if( i == EOF || i == 0 )
break;
if( ( Buffer[0] != '$' ) && ( Buffer[1] != '$' ) )
{
pX = calloc( 1 , sizeof( XLAT ) );
if (!pX )
{
fprintf( stderr, "Out of memory!" );
exit(OUT_OF_MEMORY );
}
pX->pIncoming = malloc( strlen( Buffer ) + 1 );
if (!pX->pIncoming )
{
fprintf( stderr, "Out of memory!" );
exit(OUT_OF_MEMORY );
}
strcpy( pX->pIncoming, Buffer );
pX->pTranslated = malloc( strlen( Buffer1 ) + 1 );
if (!pX->pTranslated)
{
fprintf( stderr, "Out of memory!" );
exit(OUT_OF_MEMORY );
}
strcpy( pX->pTranslated, Buffer1 );
if( pXlatCur == 0 )
{
pXlatCur = pXlat = pX;
}
else
{
pXlatCur->pNext = pX;
pXlatCur = pX;
}
}
}
/**
Then read the STATE_VS_EXPECTED_FILE, and read in the expected
tokens/productions for each entry, as translated by looking up the
data base.
**/
p = pDataBase;
while( p < (pDataBase + MAXSTATEVSEXPECTED) )
{
CHECK_FSCAN_STATUS(
fscanf( hStateVsExpectedFile, "%d %c %d %c",
&State,
&Temp,
&Count,
&Temp,
Buffer ) );
if( Count )
{
CHECK_FSCAN_STATUS(
fscanf( hStateVsExpectedFile, " %[^\n]\n", Buffer ) );
p->State = (short) State;
p->pTranslated = Translate( Buffer );
p++;
}
else
CHECK_FSCAN_STATUS(
fscanf( hStateVsExpectedFile, "\n" ) );
}
/**
emit the state vs expected array with the proper prefix
**/
fprintf( hOutput, "\n#ifndef _DBENTRY_DEFINED\n" );
fprintf( hOutput, "\n#define _DBENTRY_DEFINED\n" );
fprintf( hOutput, "\ntypedef struct _DBENTRY {" );
fprintf( hOutput, "\n\t short State;");
fprintf( hOutput, "\n\t char * pTranslated;");
fprintf( hOutput, "\n} DBENTRY;\n");
fprintf( hOutput, "\n#endif\n" );
fprintf( hOutput, "\n#define MAXSTATEVSEXPECTED_SIZE_%s %d\n", pPrefix, MAXSTATEVSEXPECTED );
fprintf( hOutput, "\n DBENTRY %s_SyntaxErrorDB[ MAXSTATEVSEXPECTED_SIZE_%s ] = {\n", pPrefix, pPrefix);
for( p = pDataBase;
p < (pDataBase + MAXSTATEVSEXPECTED);
p++ )
{
fprintf( hOutput, "{ %d , \"%s\"},\n" , p->State, p->pTranslated );
}
fprintf( hOutput, "\n};\n" );
}
char *
Translate(
char *pIncoming )
{
char *p;
pXlatCur = pXlat;
while( pXlatCur )
{
if( strcmp( pXlatCur->pIncoming, pIncoming ) == 0 )
return pXlatCur->pTranslated;
pXlatCur = pXlatCur->pNext;
}
p = malloc( strlen( pIncoming ) + 1 );
if (!p )
{
fprintf( stderr, "Out of memory.\n" );
exit( OUT_OF_MEMORY );
}
strcpy( p, pIncoming );
return p;
}