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

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. ebase.c
  5. Abstract:
  6. This file generates the error recovery data base.
  7. Notes:
  8. 1. Inputs to this module are the extable.* files generated by yacc in
  9. response to the s switch.
  10. 2. Take the state vs token index file ( extable.h3 ), and generate the
  11. state vs token table using the token index to token value
  12. translations provided by extable.h1
  13. 3. Take the state vs expected RHS file ( extable.h2 ) and generate a
  14. data base of expected RHS in every state.
  15. Author:
  16. vibhasc 11-15-91
  17. ----------------------------------------------------------------------------*/
  18. /*****************************************************************************
  19. local defines and includes
  20. *****************************************************************************/
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <assert.h>
  24. #include <malloc.h>
  25. #include <string.h>
  26. #include "ebase.h"
  27. #define STATE_VS_TOKEN_INDEX_FILE "extable.h3"
  28. #define TOKEN_TRANSLATION_FILE "extable.h1"
  29. #define STATE_VS_EXPECTED_FILE "extable.h2"
  30. #define ISVALIDTOKEN( i ) (TRUE)
  31. #define MAX_TRANSLATION_LINE_SIZE (512)
  32. #define TRUE 1
  33. #define FALSE 0
  34. /* from winerror.h */
  35. #define ERROR_INVALID_DATA 13
  36. #define CHECK_FSCAN_STATUS( fscanfcall ) \
  37. if ( EOF == (fscanfcall) ) \
  38. { \
  39. fprintf( stderr, \
  40. "\nmidleb : error MIDLEB%d : unexpected end of input stream", \
  41. ERROR_INVALID_DATA ); \
  42. exit( ERROR_INVALID_DATA ); \
  43. }
  44. typedef unsigned int BOOL;
  45. typedef enum _status
  46. {
  47. STATUS_OK = 0,
  48. OUT_OF_MEMORY,
  49. CANT_OPEN_INPUT_FILE,
  50. CANT_OPEN_OUTPUT_FILE,
  51. WRONG_ARGUMENT_COUNT
  52. } STATUS_T;
  53. typedef struct _xlat
  54. {
  55. char * pIncoming;
  56. char * pTranslated;
  57. struct _xlat *pNext;
  58. } XLAT;
  59. typedef struct _DBENTRY
  60. {
  61. short State;
  62. char * pTranslated;
  63. } DBENTRY;
  64. /*****************************************************************************
  65. global data
  66. *****************************************************************************/
  67. FILE * hStateVsTokenIndexFile;
  68. FILE * hStateVsExpectedFile;
  69. FILE * hOutput;
  70. FILE * hXlatFile;
  71. FILE * hTokXlatHdl;
  72. SGOTO ** pSGoto;
  73. short * pSGotoCount;
  74. short ** pTokVsState;
  75. short * pTokVsStateIndex;
  76. short ValidStates;
  77. short ValidTokens;
  78. char * pPrefix;
  79. XLAT * pXlat = 0,
  80. * pXlatCur = 0;
  81. DBENTRY * pDataBase;
  82. short NTOKENS;
  83. short ACCEPTCODE;
  84. short * TokVal;
  85. short * TokCount;
  86. short NSTATES;
  87. short MAXTOKVSSTATE;
  88. short MAXSTATEVSTOK;
  89. short MAXTOKENVALUE;
  90. short MAXSTATEVSEXPECTED;
  91. /*****************************************************************************
  92. external procedures
  93. *****************************************************************************/
  94. STATUS_T Init( char *, char * );
  95. STATUS_T Generate( FILE * );
  96. STATUS_T OpenFileForReadProcessing( FILE **, char * );
  97. void Dump( void );
  98. BOOL SearchForStateInTokenVsState( short, short );
  99. void TranslateExpectedConstructs( void );
  100. char * Translate( char * );
  101. void
  102. main(
  103. int argc,
  104. char *argv[] )
  105. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  106. Routine Description:
  107. the main routine.
  108. Arguments:
  109. Standard
  110. Return Value:
  111. Exit Status
  112. Notes:
  113. Usage : ebase <OutputFilename> <Xlatefile> <prefix>
  114. Xlatefile is the file where production names to message translation
  115. is specified.
  116. prefix is idl or acf. The expected string array is created with a
  117. standard name prefixed with the user specified prefix.
  118. ----------------------------------------------------------------------------*/
  119. {
  120. STATUS_T Status;
  121. fprintf( stderr, "Error Recovery Data Base Generator\n" );
  122. if( argc == 4 )
  123. {
  124. pPrefix = argv[ 3 ];
  125. if( (Status = Init( argv[ 1 ], argv[ 2 ] )) == STATUS_OK )
  126. {
  127. Status = Generate( hStateVsTokenIndexFile );
  128. }
  129. Dump();
  130. TranslateExpectedConstructs();
  131. }
  132. else
  133. {
  134. fprintf( stderr, "Wrong argument count\n" );
  135. fprintf( stderr, "Usage : midleb <output file or - > <translation-file-name> <prefix>\n");
  136. Status = WRONG_ARGUMENT_COUNT;
  137. }
  138. exit( Status );
  139. }
  140. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  141. Routine Description:
  142. Initialize
  143. Arguments:
  144. OutputName : output file name
  145. XlatFilename : the production/token name to error message translation.
  146. Return Value:
  147. STATUS_T - OUT_OF_MEMORY or
  148. - CANT_OPEN_INPUT_FILE or
  149. - STATUS_OK
  150. Notes:
  151. Sets up the file handles for all the files that need to be read from
  152. ----------------------------------------------------------------------------*/
  153. STATUS_T
  154. Init(
  155. char * OutputFileName,
  156. char * XlatFileName )
  157. {
  158. STATUS_T Status;
  159. int i;
  160. Status = OpenFileForReadProcessing(
  161. &hStateVsTokenIndexFile,
  162. STATE_VS_TOKEN_INDEX_FILE );
  163. if( Status == STATUS_OK )
  164. {
  165. Status = OpenFileForReadProcessing(
  166. &hStateVsExpectedFile,
  167. STATE_VS_EXPECTED_FILE );
  168. if( Status == STATUS_OK )
  169. {
  170. Status = OpenFileForReadProcessing(
  171. &hTokXlatHdl,
  172. TOKEN_TRANSLATION_FILE );
  173. if( Status == STATUS_OK )
  174. {
  175. Status = OpenFileForReadProcessing( &hXlatFile, XlatFileName );
  176. if( Status == STATUS_OK )
  177. {
  178. if( strcmp( OutputFileName, "-" ) == 0 )
  179. hOutput = stdout;
  180. else if( (hOutput = fopen( OutputFileName , "w" )) == (FILE *)0 )
  181. {
  182. Status = CANT_OPEN_OUTPUT_FILE;
  183. };
  184. }
  185. }
  186. }
  187. }
  188. if( Status != STATUS_OK )
  189. return Status;
  190. /** read in the required numbers from the TOKEN_TRANSLATION_FILE **/
  191. CHECK_FSCAN_STATUS(
  192. fscanf( hTokXlatHdl, "%hd %hd\n", &NTOKENS, &ACCEPTCODE ) );
  193. /** read in the token translation table **/
  194. TokVal = (short *)calloc( 1, NTOKENS * sizeof( short ) );
  195. TokCount = (short *)calloc( 1, NTOKENS * sizeof( short ) );
  196. if (!TokVal || !TokCount )
  197. {
  198. fprintf( stderr, "Out of memory.\n");
  199. exit(OUT_OF_MEMORY);
  200. }
  201. for( i = 0;
  202. i < NTOKENS;
  203. i++ )
  204. {
  205. CHECK_FSCAN_STATUS(
  206. fscanf( hTokXlatHdl, "%hd", &TokVal[ i ]) );
  207. }
  208. CHECK_FSCAN_STATUS(
  209. fscanf( hTokXlatHdl, "\n" ) );
  210. for( i = 0;
  211. i < NTOKENS;
  212. i++ )
  213. {
  214. CHECK_FSCAN_STATUS(
  215. fscanf( hTokXlatHdl, "%hd", &TokCount[ i ]) );
  216. }
  217. CHECK_FSCAN_STATUS(
  218. fscanf( hTokXlatHdl, "\n" ) );
  219. CHECK_FSCAN_STATUS(
  220. fscanf( hTokXlatHdl,
  221. "%hd %hd %hd %hd %hd\n",
  222. &NSTATES,
  223. &MAXTOKVSSTATE,
  224. &MAXSTATEVSTOK,
  225. &MAXTOKENVALUE,
  226. &MAXSTATEVSEXPECTED ) );
  227. /** allocate memory now **/
  228. pSGoto = (SGOTO **) calloc( 1,NSTATES * sizeof( SGOTO * ) );
  229. pSGotoCount = (short *)calloc(1, NSTATES * sizeof( short ) );
  230. pTokVsState = (short **)calloc( 1,(MAXTOKENVALUE+1) * sizeof( short * ) );
  231. pTokVsStateIndex = (short *)calloc(1, (MAXTOKENVALUE+1) * sizeof( short ) );
  232. pDataBase = ( DBENTRY * )calloc( 1, MAXSTATEVSEXPECTED * sizeof( DBENTRY ) );
  233. if( !pSGoto || !pSGotoCount || !pTokVsState || !pTokVsStateIndex || !pDataBase )
  234. {
  235. fprintf( stderr, "Out of memory.\n");
  236. exit(OUT_OF_MEMORY);
  237. }
  238. return Status;
  239. }
  240. STATUS_T
  241. Generate(
  242. FILE * hSVsTIndexFile )
  243. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  244. Routine Description:
  245. Generate the state vs token table, given the state vs token index table
  246. in extable.h3 and token vs token index translation of extable.h1.
  247. Arguments:
  248. hStateVsTokenIndexFile - handle to the file which has the state vs
  249. token index info.
  250. Return Value:
  251. None.
  252. Notes:
  253. The state vs token index file has the goto info for every valid token,
  254. For every state, this file contains the goto ( or none ) for every valid
  255. token ( represented by the token index ). Thus for each state, we lookup
  256. to see if the state has a goto for a given token index. If it does, then
  257. we translate the token index into a token value, and mark the goto for the
  258. state for that token in the state vs token table.
  259. In the end we will have a very sparse array, which contains all the states
  260. and the gotos for the state for each token ( or the absence of any goto ).
  261. We will use this table to generate two tables:
  262. 1. The set of all states which have a goto on a token
  263. 2. The set of all tokens valid for any state.
  264. The exception to this rule is the accept action which is treated like
  265. an absence of goto.
  266. ----------------------------------------------------------------------------*/
  267. {
  268. short iState,i,j,Temp,SGotoCount;
  269. SGOTO *p;
  270. /** fixup pointers to token vs state pointer array **/
  271. for( i = 0;
  272. i < NTOKENS;
  273. i++ )
  274. {
  275. if( TokCount[ i ] )
  276. {
  277. j = TokVal[ i ];
  278. if( ISVALIDTOKEN( j ) )
  279. {
  280. pTokVsState[ j ] = calloc( 1, TokCount[ i ] * sizeof( short ) );
  281. if (!pTokVsState[ j ])
  282. {
  283. fprintf( stderr, "Out of memory.\n" );
  284. exit( OUT_OF_MEMORY );
  285. }
  286. }
  287. }
  288. }
  289. for( iState = 0;
  290. iState < NSTATES;
  291. ++iState )
  292. {
  293. /** ignore the state number */
  294. CHECK_FSCAN_STATUS(
  295. fscanf( hSVsTIndexFile,
  296. "%hd %c",
  297. &Temp,
  298. &Temp ) );
  299. /** get the count of number of state goto entries **/
  300. CHECK_FSCAN_STATUS(
  301. fscanf( hSVsTIndexFile,
  302. "%hd %c",
  303. &SGotoCount,
  304. &Temp ) );
  305. /** now read in the goto vs token pairs **/
  306. if( SGotoCount )
  307. {
  308. p = pSGoto[ iState ] = calloc( 1, SGotoCount * sizeof( SGOTO ) );
  309. if (!p)
  310. {
  311. fprintf( stderr, "Out of memory.\n" );
  312. exit( OUT_OF_MEMORY );
  313. }
  314. for( j = 0;
  315. j < SGotoCount;
  316. ++j )
  317. {
  318. CHECK_FSCAN_STATUS(
  319. fscanf( hSVsTIndexFile,
  320. "%hd%c %hd",
  321. &p->Goto,
  322. &Temp,
  323. &p->Token ) );
  324. Temp = TokVal[ p->Token ];
  325. if( ISVALIDTOKEN( Temp ) )
  326. {
  327. if( !SearchForStateInTokenVsState( Temp, p->Goto ) )
  328. {
  329. i = pTokVsStateIndex[ Temp ];
  330. pTokVsStateIndex[ Temp ]++;
  331. *(pTokVsState[Temp] + i ) = p->Goto;
  332. }
  333. p++;
  334. pSGotoCount[ iState ]++;
  335. }
  336. }
  337. }
  338. }
  339. return STATUS_OK;
  340. }
  341. STATUS_T
  342. OpenFileForReadProcessing(
  343. FILE ** pHandle,
  344. char * pName )
  345. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  346. Routine Description:
  347. This process opens a file for read processing, reports an error if
  348. the file could not be opened.
  349. Arguments:
  350. pHandle - pointer to a file handle deposition area.
  351. pName - pointer to a file name, null terminated.
  352. Return Value:
  353. STATUS_T - STATUS_OK if all is well.
  354. - CANT_OPEN_INPUT_FILE otherwise.
  355. Notes:
  356. ----------------------------------------------------------------------------*/
  357. {
  358. FILE *hF;
  359. if( ( hF = fopen( pName, "r" ) ) == (FILE *)NULL )
  360. {
  361. fprintf( stderr, "Cannot open input file : %s\n", pName );
  362. return CANT_OPEN_INPUT_FILE;
  363. }
  364. *pHandle = hF;
  365. return STATUS_OK;
  366. }
  367. void
  368. Dump( void )
  369. {
  370. SGOTO * p;
  371. short iTemp, i,j;
  372. /** dump the state goto table **/
  373. for( iTemp = 0, ValidStates = 0;
  374. iTemp < NSTATES;
  375. ++iTemp )
  376. {
  377. p = pSGoto[ iTemp ];
  378. if( j = pSGotoCount[ iTemp ] )
  379. {
  380. fprintf( hOutput, "\n SGOTO _sG%s%.4hd [ %d ] = { ", pPrefix, iTemp, j );
  381. for( i = 0;
  382. i < j;
  383. i++ )
  384. {
  385. fprintf( hOutput
  386. , " {%hd, %hd} %c"
  387. , p[ i ].Goto
  388. , TokVal[ p[ i ].Token]
  389. , ( (i+1 == j) ? ' ' : ',' ));
  390. }
  391. fprintf( hOutput, "};" );
  392. ValidStates++;
  393. }
  394. }
  395. /** now dump the array of pointers to this **/
  396. fprintf( hOutput, "\n\n#define VALIDSTATES_%s %d\n", pPrefix, ValidStates );
  397. fprintf( hOutput, "\n\nSGOTOVECTOR SGoto%s[ VALIDSTATES_%s ] = {\n",pPrefix, pPrefix);
  398. for( i = 0;
  399. i < NSTATES;
  400. ++i )
  401. {
  402. if( pSGotoCount[ i ] )
  403. {
  404. fprintf( hOutput, "\n{ %d, _sG%s%.4hd, %d }"
  405. , i
  406. ,pPrefix
  407. , i
  408. , pSGotoCount[ i ] );
  409. fprintf( hOutput,"%c", ((i + 1 == NSTATES) ? ' ' : ',' ));
  410. }
  411. }
  412. fprintf( hOutput, "\n};\n\n" );
  413. /** count the valid token entries. i.e tokens for which states exist **/
  414. fprintf(hOutput, "#if 0\n");
  415. for( ValidTokens = 0, i = 0;
  416. i < MAXTOKENVALUE;
  417. ++i )
  418. {
  419. if( pTokVsStateIndex[ i ] )
  420. ValidTokens++;
  421. }
  422. /** dump the token vs state table **/
  423. for( iTemp = 0;
  424. iTemp < NTOKENS;
  425. ++iTemp )
  426. {
  427. if( j = pTokVsStateIndex[ TokVal[ iTemp ] ] )
  428. {
  429. fprintf( hOutput, "short _tS%s%.4d[ %d ] = {", pPrefix, TokVal[ iTemp ], j );
  430. for( i = 0;
  431. i < j;
  432. ++i )
  433. {
  434. fprintf( hOutput, " %d %c", *(pTokVsState[ TokVal[ iTemp ] ]+i),
  435. (( i + 1 == j ) ? ' ' : ',' ));
  436. }
  437. fprintf( hOutput, "};\n" );
  438. }
  439. }
  440. /** dump the vectors to the token vs state table **/
  441. fprintf(hOutput, "\n#define VALIDTOKENS %d\n", ValidTokens );
  442. fprintf( hOutput, "\nTOKVSSTATEVECTOR TokVsState%s[ VALIDTOKENS ] = { \n",pPrefix);
  443. for( i = 0;
  444. i < MAXTOKENVALUE+1;
  445. ++i )
  446. {
  447. if( j = pTokVsStateIndex[ i ])
  448. {
  449. fprintf( hOutput, "\n{ %d, _tS%s%.4d, %d }",i, pPrefix, i, j );
  450. fprintf(hOutput, "%c", (i + 1 == NTOKENS) ? ' ' : ',' );
  451. }
  452. }
  453. fprintf( hOutput, "\n\n};\n" );
  454. fprintf( hOutput, "\n" );
  455. fprintf(hOutput, "#endif\n");
  456. }
  457. BOOL
  458. SearchForStateInTokenVsState(
  459. short TokenValue,
  460. short Goto )
  461. {
  462. int i,j;
  463. for( i = 0, j = pTokVsStateIndex[ TokenValue ];
  464. i < j;
  465. ++i )
  466. {
  467. if( *(pTokVsState[ TokenValue ] + i) == Goto )
  468. return TRUE;
  469. }
  470. return FALSE;
  471. }
  472. void
  473. TranslateExpectedConstructs( void )
  474. {
  475. int i,State,Count,Temp;
  476. char Buffer[ MAX_TRANSLATION_LINE_SIZE ];
  477. char Buffer1[ MAX_TRANSLATION_LINE_SIZE ];
  478. DBENTRY *p;
  479. XLAT *pX;
  480. /**
  481. firstly, read in the translation data base, which shows the
  482. expected token name vs the actual error string the compiler wants to
  483. output.
  484. **/
  485. for(;;)
  486. {
  487. i = fscanf( hXlatFile,
  488. "%[^ \t]%1s%[^\n]\n",
  489. Buffer,
  490. &Temp,
  491. Buffer1 );
  492. if( i == EOF || i == 0 )
  493. break;
  494. if( ( Buffer[0] != '$' ) && ( Buffer[1] != '$' ) )
  495. {
  496. pX = calloc( 1 , sizeof( XLAT ) );
  497. if (!pX )
  498. {
  499. fprintf( stderr, "Out of memory!" );
  500. exit(OUT_OF_MEMORY );
  501. }
  502. pX->pIncoming = malloc( strlen( Buffer ) + 1 );
  503. if (!pX->pIncoming )
  504. {
  505. fprintf( stderr, "Out of memory!" );
  506. exit(OUT_OF_MEMORY );
  507. }
  508. strcpy( pX->pIncoming, Buffer );
  509. pX->pTranslated = malloc( strlen( Buffer1 ) + 1 );
  510. if (!pX->pTranslated)
  511. {
  512. fprintf( stderr, "Out of memory!" );
  513. exit(OUT_OF_MEMORY );
  514. }
  515. strcpy( pX->pTranslated, Buffer1 );
  516. if( pXlatCur == 0 )
  517. {
  518. pXlatCur = pXlat = pX;
  519. }
  520. else
  521. {
  522. pXlatCur->pNext = pX;
  523. pXlatCur = pX;
  524. }
  525. }
  526. }
  527. /**
  528. Then read the STATE_VS_EXPECTED_FILE, and read in the expected
  529. tokens/productions for each entry, as translated by looking up the
  530. data base.
  531. **/
  532. p = pDataBase;
  533. while( p < (pDataBase + MAXSTATEVSEXPECTED) )
  534. {
  535. CHECK_FSCAN_STATUS(
  536. fscanf( hStateVsExpectedFile, "%d %c %d %c",
  537. &State,
  538. &Temp,
  539. &Count,
  540. &Temp,
  541. Buffer ) );
  542. if( Count )
  543. {
  544. CHECK_FSCAN_STATUS(
  545. fscanf( hStateVsExpectedFile, " %[^\n]\n", Buffer ) );
  546. p->State = (short) State;
  547. p->pTranslated = Translate( Buffer );
  548. p++;
  549. }
  550. else
  551. CHECK_FSCAN_STATUS(
  552. fscanf( hStateVsExpectedFile, "\n" ) );
  553. }
  554. /**
  555. emit the state vs expected array with the proper prefix
  556. **/
  557. fprintf( hOutput, "\n#ifndef _DBENTRY_DEFINED\n" );
  558. fprintf( hOutput, "\n#define _DBENTRY_DEFINED\n" );
  559. fprintf( hOutput, "\ntypedef struct _DBENTRY {" );
  560. fprintf( hOutput, "\n\t short State;");
  561. fprintf( hOutput, "\n\t char * pTranslated;");
  562. fprintf( hOutput, "\n} DBENTRY;\n");
  563. fprintf( hOutput, "\n#endif\n" );
  564. fprintf( hOutput, "\n#define MAXSTATEVSEXPECTED_SIZE_%s %d\n", pPrefix, MAXSTATEVSEXPECTED );
  565. fprintf( hOutput, "\n DBENTRY %s_SyntaxErrorDB[ MAXSTATEVSEXPECTED_SIZE_%s ] = {\n", pPrefix, pPrefix);
  566. for( p = pDataBase;
  567. p < (pDataBase + MAXSTATEVSEXPECTED);
  568. p++ )
  569. {
  570. fprintf( hOutput, "{ %d , \"%s\"},\n" , p->State, p->pTranslated );
  571. }
  572. fprintf( hOutput, "\n};\n" );
  573. }
  574. char *
  575. Translate(
  576. char *pIncoming )
  577. {
  578. char *p;
  579. pXlatCur = pXlat;
  580. while( pXlatCur )
  581. {
  582. if( strcmp( pXlatCur->pIncoming, pIncoming ) == 0 )
  583. return pXlatCur->pTranslated;
  584. pXlatCur = pXlatCur->pNext;
  585. }
  586. p = malloc( strlen( pIncoming ) + 1 );
  587. if (!p )
  588. {
  589. fprintf( stderr, "Out of memory.\n" );
  590. exit( OUT_OF_MEMORY );
  591. }
  592. strcpy( p, pIncoming );
  593. return p;
  594. }