Leaked source code of windows server 2003
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.

388 lines
8.0 KiB

  1. /*****************************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1987-1999 **/
  4. /*****************************************************************************/
  5. /*****************************************************************************
  6. File : erep.cxx
  7. Title : error reporting and recovery utility routines
  8. Description : contains associated routines for the grammar (pass 1)
  9. History :
  10. 02-Jan-1992 VibhasC Created
  11. *****************************************************************************/
  12. #pragma warning ( disable : 4514 )
  13. /****************************************************************************
  14. * include files
  15. ***************************************************************************/
  16. #include "nulldefs.h"
  17. extern "C" {
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <string.h>
  21. #include "ebase.h"
  22. #include "idlerec.h"
  23. #include "acferec.h"
  24. #include "grammar.h"
  25. }
  26. #include <limits.h>
  27. #include "common.hxx"
  28. #include "errors.hxx"
  29. #include "filehndl.hxx"
  30. #include "control.hxx"
  31. /****************************************************************************
  32. * external data
  33. ***************************************************************************/
  34. extern CCONTROL * pCompiler;
  35. /****************************************************************************
  36. * external functions
  37. ***************************************************************************/
  38. /****************************************************************************
  39. * local functions
  40. ***************************************************************************/
  41. /****************************************************************************
  42. * local definitions
  43. ***************************************************************************/
  44. #define IDENTIFIER_WEIGHT (6)
  45. #define NUMBER_WEIGHT (6)
  46. #define LBRACE_WEIGHT (5)
  47. #define RBRACE_WEIGHT (5)
  48. #define RBRACK_WEIGHT (4)
  49. #define LBRACK_WEIGHT (4)
  50. #define SEMI_WEIGHT (3)
  51. #define LPARAN_WEIGHT (2)
  52. #define RPARAN_WEIGHT (2)
  53. #define COMMA_WEIGHT (1)
  54. #define NO_WEIGHT (0)
  55. short TokenWeight( short );
  56. typedef short ELEMTYPE;
  57. #define COMPARE_LESS( a, b ) ( TokenWeight(a) < TokenWeight(b) )
  58. #define COMPARE_GREATER( a, b ) ( TokenWeight(a) > TokenWeight(b) )
  59. extern char * GetExpectedSyntax( char *, short );
  60. void qsort( ELEMTYPE a[], int l, int r );
  61. int SearchForGotoStates( short, SGOTO ** );
  62. BOOL IsValidTokenInState( SGOTO *, short );
  63. /*
  64. search in the state vs token table to see if a possible missing token
  65. can be detected. This routine is called when there is a syntax error, and
  66. a missing token may be the case. A token is a missing token, if the current
  67. state has a goto where the current token is valid.
  68. For each state in the goto entries for the current state, check if the
  69. current token is a valid token. If it is , then this is a possible missing
  70. token.
  71. After the list of possinble missing tokens has been made, the tough part
  72. is deciding which is the best possible token. Im afraid, the only simple
  73. thing right now is to decide on the token, on some kind of priority basis.
  74. Later we might extend the parser semantic actions to indicate which token
  75. is the token of choice. But for now, this stays.
  76. */
  77. short
  78. PossibleMissingToken(
  79. short State,
  80. short CurrentToken)
  81. {
  82. short Token;
  83. short * pToken;
  84. short * pTokenSave;
  85. SGOTO * pSGoto;
  86. int Count, i;
  87. /*
  88. * search for the states goto array
  89. */
  90. Count = SearchForGotoStates( State, &pSGoto );
  91. if( !Count ) return -1;
  92. pToken = pTokenSave = new short[ Count ];
  93. /*
  94. for each goto in the array, search for the state where the current
  95. token is valid.
  96. */
  97. for( i = 0;
  98. i < Count;
  99. i++ )
  100. {
  101. if( IsValidTokenInState( pSGoto + i, CurrentToken ))
  102. {
  103. Token = (pSGoto+i)->Token;
  104. if( (Token < 128 ) ||
  105. (Token == IDENTIFIER) ||
  106. (Token == NUMERICCONSTANT))
  107. {
  108. *pToken++ = Token;
  109. }
  110. }
  111. }
  112. /*
  113. if we cannot make any intelligent decision about the lookahead token
  114. pick up the ones in the current lookahead set
  115. */
  116. if( (pToken - pTokenSave) == 0 )
  117. {
  118. delete pTokenSave;
  119. return -1;
  120. }
  121. if( pCompiler->GetPassNumber() == IDL_PASS )
  122. {
  123. if( (pToken - pTokenSave) == 0 )
  124. {
  125. for( i = 0;
  126. i < Count;
  127. i++ )
  128. {
  129. Token = (pSGoto+i)->Token;
  130. if( (Token < 128 ) ||
  131. (Token == IDENTIFIER) ||
  132. (Token == NUMERICCONSTANT))
  133. {
  134. *pToken++ = Token;
  135. }
  136. }
  137. }
  138. }
  139. /*
  140. We now have a list of possible tokens. Sort them in the order of
  141. priority.
  142. */
  143. if( pToken - pTokenSave )
  144. {
  145. MIDL_ASSERT( (pToken - pTokenSave - 1) <= INT_MAX );
  146. qsort( pTokenSave, 0, (int) (pToken - pTokenSave - 1));
  147. /* return the first in the list */
  148. CurrentToken = *pTokenSave;
  149. }
  150. else
  151. CurrentToken = -1;
  152. delete pTokenSave;
  153. return CurrentToken;
  154. }
  155. int
  156. SearchForGotoStates(
  157. short State,
  158. SGOTO ** ppSGoto)
  159. {
  160. int i;
  161. SGOTOVECTOR * p = SGotoIDL;
  162. short ValidStates;
  163. if( (pCompiler->GetPassNumber() == IDL_PASS ) )
  164. {
  165. ValidStates = VALIDSTATES_IDL;
  166. p = SGotoIDL;
  167. }
  168. else
  169. {
  170. ValidStates = VALIDSTATES_ACF;
  171. p = SGotoACF;
  172. }
  173. for( i = 0; i < ValidStates; ++i,++p )
  174. {
  175. if( p->State == State )
  176. {
  177. *ppSGoto = p->pSGoto;
  178. return p->Count;
  179. }
  180. }
  181. return 0;
  182. }
  183. BOOL
  184. IsValidTokenInState(
  185. SGOTO * pSGoto,
  186. short Token )
  187. {
  188. int Count,i;
  189. SGOTO * p;
  190. short State = pSGoto->Goto;
  191. Count = SearchForGotoStates( State, &p );
  192. if( !Count )
  193. {
  194. if( pCompiler->GetPassNumber() == IDL_PASS )
  195. {
  196. if( ( (pSGoto->Token == IDENTIFIER ) ||
  197. (pSGoto->Token == NUMERICCONSTANT) &&
  198. (Token == (short) ';' )) )
  199. {
  200. return TRUE;
  201. }
  202. }
  203. return FALSE;
  204. }
  205. for( i = 0; i < Count; ++i, ++p )
  206. {
  207. if( p->Token == Token )
  208. return TRUE;
  209. }
  210. return FALSE;
  211. }
  212. void
  213. qsort(
  214. ELEMTYPE a[],
  215. int l,
  216. int r )
  217. {
  218. ELEMTYPE v, t;
  219. int i, j;
  220. if( r > l )
  221. {
  222. v = a[ r ];
  223. i = l - 1;
  224. j = r;
  225. for (;; )
  226. {
  227. /** sort in reverse order of token weight **/
  228. while( COMPARE_GREATER( a[ ++i ], v ) );
  229. while( COMPARE_LESS( a[ --j ], v ) );
  230. if( i >= j ) break;
  231. t = a[ i ];
  232. a[ i ] = a[ j ];
  233. a[ j ] = t;
  234. }
  235. t = a[ i ];
  236. a[ i ] = a[ r ];
  237. a[ r ] = t;
  238. qsort( a, l, i - 1 );
  239. qsort( a, i+1, r );
  240. }
  241. }
  242. char *
  243. GetExpectedSyntax(
  244. char * pBuffer,
  245. short state )
  246. {
  247. int i = 0;
  248. int Max;
  249. DBENTRY * pDB;
  250. if( (pCompiler->GetPassNumber() == IDL_PASS ) )
  251. {
  252. pDB = IDL_SyntaxErrorDB;
  253. Max = MAXSTATEVSEXPECTED_SIZE_IDL;
  254. }
  255. else
  256. {
  257. pDB = ACF_SyntaxErrorDB;
  258. Max = MAXSTATEVSEXPECTED_SIZE_ACF;
  259. }
  260. while( i < Max )
  261. {
  262. if( pDB[ i ].State == state )
  263. {
  264. char fFirst = 1;
  265. strcpy( pBuffer , "expecting ");
  266. while( pDB[ i ].State == state )
  267. {
  268. // make sure not to report the same translated string twice, when two non-terminals
  269. // have the same translated string
  270. if ( !strstr( pBuffer, pDB[ i ].pTranslated ) )
  271. {
  272. if( !fFirst )
  273. strcat( pBuffer, " or ");
  274. fFirst = 0;
  275. strcat( pBuffer, pDB[ i ].pTranslated );
  276. }
  277. i++;
  278. }
  279. return pBuffer;
  280. }
  281. else
  282. i++;
  283. }
  284. return (char *)NULL;
  285. }
  286. short
  287. TokenWeight(
  288. short Token)
  289. {
  290. switch( Token )
  291. {
  292. case IDENTIFIER: return IDENTIFIER_WEIGHT;
  293. case NUMERICCONSTANT: return NUMBER_WEIGHT;
  294. case (short)(']'): return RBRACK_WEIGHT;
  295. case (short)('['): return LBRACK_WEIGHT;
  296. case (short)('{'): return LBRACE_WEIGHT;
  297. case (short)('}'): return RBRACE_WEIGHT;
  298. case (short)(';'): return SEMI_WEIGHT;
  299. case (short)('('): return LPARAN_WEIGHT;
  300. case (short)(')'): return RPARAN_WEIGHT;
  301. case (short)(','): return COMMA_WEIGHT;
  302. default: return NO_WEIGHT;
  303. }
  304. }