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.

721 lines
19 KiB

  1. // Copyright (c) 1993-1999 Microsoft Corporation
  2. /*
  3. ** helper functions for Gerd Immeyer's grammar
  4. **
  5. */
  6. /****************************************************************************
  7. * include files
  8. ***************************************************************************/
  9. #pragma warning ( disable : 4514 4710 )
  10. #include "nulldefs.h"
  11. extern "C" {
  12. #include <stdio.h>
  13. #include <io.h>
  14. #include <process.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. }
  18. #include "common.hxx"
  19. #include "errors.hxx"
  20. #include "midlnode.hxx"
  21. #include "listhndl.hxx"
  22. #include "filehndl.hxx"
  23. #include "lextable.hxx"
  24. #include "lexutils.hxx"
  25. #include "grammar.h"
  26. #include "gramutil.hxx"
  27. #include "cmdana.hxx"
  28. #include "control.hxx"
  29. #include "tlgen.hxx"
  30. #include <float.h>
  31. extern "C" {
  32. #include "lex.h"
  33. }
  34. /****************************************************************************
  35. * local definitions and macros
  36. ***************************************************************************/
  37. #define warning(p) /* temp defintion to get rid of compiler probs */
  38. #define MAX_ID_LENGTH (31)
  39. #define MAX_DECIMAL_LENGTH (10)
  40. #define MAX_HEX_LENGTH (8)
  41. #define MAX_OCTAL_LENGTH (25)
  42. /***************************************************************************
  43. * local data
  44. ***************************************************************************/
  45. /***************************************************************************
  46. * local procedures
  47. ***************************************************************************/
  48. long convert(char *, short, short);
  49. token_t cnv_int(void);
  50. token_t cnv_hex(void);
  51. token_t cnv_octal(void);
  52. token_t cnv_float(void);
  53. inline token_t GetNextToken() {return yylex();}
  54. inline void UngetToken(token_t token) {yyunlex(token);}
  55. token_t name(void);
  56. token_t map_token(token_t token);
  57. void lex_error(int number);
  58. /***************************************************************************
  59. * global data
  60. ***************************************************************************/
  61. // token_t TokenMap[LASTTOKEN];
  62. short handle_import;
  63. short inside_rpc;
  64. lextype_t yylval;
  65. token_t toktyp_G; /* token type */
  66. short toklen_G; /* len of token string */
  67. char *tokptr_G; /* pointer to token string */
  68. short curr_line_G; /* current line in file */
  69. char *curr_file_G; /* current file name */
  70. long tokval_G; /* value of constant token */
  71. FILE *hFile_G; /* current file */
  72. BOOL fAbandonNumberLengthLimits;
  73. /***************************************************************************
  74. * external data
  75. ***************************************************************************/
  76. extern short DebugLine;
  77. extern NFA_INFO *pImportCntrl;
  78. extern LexTable * pMidlLexTable;
  79. extern short CompileMode;
  80. extern SymTable * pBaseSymTbl;
  81. extern CMD_ARG * pCommand;
  82. extern ccontrol * pCompiler;
  83. extern char LastLexChar;
  84. /***************************************************************************
  85. * external procedures
  86. ***************************************************************************/
  87. token_t is_keyword( char *, short);
  88. /***************************************************************************/
  89. const extern short st[ 13 ][ 16 ];
  90. const extern short ct[256];
  91. // Used to disable identifier to keyword mapping for declspec parsing.
  92. BOOL IdToKeywordMapping = TRUE;
  93. #define __isdigit(c) (((c) >= '0' && (c) <= '9'))
  94. token_t cnv_int(void)
  95. {
  96. LastLexChar = NewCCGetch();
  97. int chBeyond = NewCCGetch();
  98. NewCCputbackc((char)chBeyond);
  99. if( LastLexChar == '.' && chBeyond!= '.')
  100. {
  101. STATUS_T Status = STATUS_OK;
  102. short LengthCollected = (short)strlen(tokptr_G);
  103. char * ptr = &tokptr_G[LengthCollected];
  104. char ch = LastLexChar;
  105. *ptr++ = ch;
  106. *ptr++ = ch = NewCCGetch();
  107. if (__isdigit(ch))
  108. {
  109. *ptr++ = ch = NewCCGetch();
  110. while (__isdigit(ch))
  111. {
  112. *ptr++ = ch = NewCCGetch();
  113. }
  114. if (ch == 'e' || ch == 'E')
  115. {
  116. *ptr++ = ch = NewCCGetch();
  117. if (ch == '-' || ch == '+')
  118. {
  119. *ptr++ = ch = NewCCGetch();
  120. if (__isdigit(ch))
  121. {
  122. *ptr++ = ch = NewCCGetch();
  123. while (__isdigit(ch))
  124. {
  125. *ptr++ = ch = NewCCGetch();
  126. }
  127. }
  128. else
  129. {
  130. Status = ERROR_PARSING_NUMERICAL;
  131. }
  132. }
  133. else if (__isdigit(ch))
  134. {
  135. *ptr++ = ch = NewCCGetch();
  136. while (__isdigit(ch))
  137. {
  138. *ptr++ = ch = NewCCGetch();
  139. }
  140. }
  141. }
  142. }
  143. else
  144. {
  145. Status = ERROR_PARSING_NUMERICAL;
  146. }
  147. if (Status != STATUS_OK)
  148. {
  149. ParseError( Status, (char *)0 );
  150. exit( Status );
  151. }
  152. *ptr = 0;
  153. token_t tokenType = DOUBLECONSTANT;
  154. double d = atof(tokptr_G);
  155. if (ch != 'l' && ch != 'L')
  156. {
  157. NewCCputbackc(ch);
  158. *(ptr-1) = 0;
  159. tokenType = unsigned short( (d < FLT_MAX || d > FLT_MIN) ? FLOATCONSTANT : DOUBLECONSTANT );
  160. }
  161. else
  162. {
  163. NewCCputbackc(NewCCGetch());
  164. }
  165. if ( tokenType == DOUBLECONSTANT )
  166. {
  167. yylval.yy_numeric.dVal = d;
  168. }
  169. else
  170. {
  171. yylval.yy_numeric.fVal = (float) d;
  172. }
  173. yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G);
  174. return tokenType;
  175. }
  176. else
  177. {
  178. token_t Tok = NUMERICCONSTANT;
  179. yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G);
  180. yylval.yy_numeric.Val = tokval_G = convert(tokptr_G, 10, MAX_DECIMAL_LENGTH );
  181. if( (LastLexChar == 'L') || (LastLexChar == 'l'))
  182. {
  183. Tok = NUMERICLONGCONSTANT;
  184. }
  185. else
  186. {
  187. if( (LastLexChar == 'U') || (LastLexChar == 'u'))
  188. {
  189. Tok = NUMERICULONGCONSTANT;
  190. if( ((LastLexChar = NewCCGetch()) != 'L') && (LastLexChar != 'l'))
  191. {
  192. NewCCputbackc(LastLexChar);
  193. Tok = NUMERICUCONSTANT;
  194. }
  195. }
  196. else
  197. {
  198. NewCCputbackc( LastLexChar );
  199. return NUMERICCONSTANT;
  200. }
  201. }
  202. return Tok;
  203. }
  204. }
  205. token_t cnv_hex(void)
  206. {
  207. token_t Tok = HEXCONSTANT;
  208. unsigned long Val;
  209. yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G);
  210. tokptr_G += 2; /* skip 0x */
  211. Val = yylval.yy_numeric.Val = tokval_G = convert(tokptr_G, 16, MAX_HEX_LENGTH);
  212. tokptr_G -= 2;
  213. LastLexChar = NewCCGetch();
  214. if( (LastLexChar == 'L') || (LastLexChar == 'l'))
  215. {
  216. Tok = HEXLONGCONSTANT;
  217. }
  218. else
  219. {
  220. // LastLexChar = NewCCGetch();
  221. if( (LastLexChar == 'U') || (LastLexChar == 'u'))
  222. {
  223. Tok = HEXULONGCONSTANT;
  224. if( ((LastLexChar = NewCCGetch()) != 'L') && (LastLexChar != 'l'))
  225. {
  226. NewCCputbackc(LastLexChar);
  227. Tok = HEXUCONSTANT;
  228. }
  229. }
  230. else
  231. {
  232. NewCCputbackc(LastLexChar);
  233. return HEXCONSTANT;
  234. }
  235. }
  236. return Tok;
  237. }
  238. token_t cnv_octal(void)
  239. {
  240. token_t Tok = OCTALCONSTANT;
  241. unsigned long Val;
  242. yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G);
  243. Val = yylval.yy_numeric.Val = tokval_G = convert(tokptr_G, 8, MAX_OCTAL_LENGTH);
  244. LastLexChar = NewCCGetch();
  245. if( (LastLexChar == 'L') || (LastLexChar == 'l'))
  246. {
  247. Tok = OCTALLONGCONSTANT;
  248. }
  249. else
  250. {
  251. // LastLexChar = NewCCGetch();
  252. if( (LastLexChar == 'U') || (LastLexChar == 'u'))
  253. {
  254. Tok = OCTALULONGCONSTANT;
  255. if( ((LastLexChar = NewCCGetch()) != 'L') && (LastLexChar != 'l'))
  256. {
  257. NewCCputbackc(LastLexChar);
  258. Tok = OCTALUCONSTANT;
  259. }
  260. }
  261. else
  262. {
  263. NewCCputbackc(LastLexChar);
  264. return OCTALCONSTANT;
  265. }
  266. }
  267. return Tok;
  268. }
  269. token_t cnv_float(void)
  270. {
  271. warning("floating point constants not allowed");
  272. yylval.yy_numeric.Val = tokval_G = 0;
  273. lex_error(101);
  274. yylval.yy_numeric.pValStr = pMidlLexTable->LexInsert(tokptr_G);
  275. return NUMERICCONSTANT;
  276. }
  277. long convert(char *ptr, short base, short MaxSize)
  278. {
  279. REG long answer = 0;
  280. REG char ch;
  281. BOOL fZeroIsNotALeadingZeroAnymore = FALSE;
  282. short count = 0;
  283. while ((ch = *ptr++) != 0)
  284. {
  285. if ((ch & 0x5f) >= 'A')
  286. answer = answer * base + (ch & 0x5f) - 'A'+ 10;
  287. else
  288. answer = answer * base + ch - '0';
  289. if( ch == '0')
  290. {
  291. if( fZeroIsNotALeadingZeroAnymore )
  292. count++;
  293. }
  294. else
  295. {
  296. fZeroIsNotALeadingZeroAnymore = TRUE;
  297. count++;
  298. }
  299. }
  300. if( ( count > MaxSize ) && !fAbandonNumberLengthLimits )
  301. {
  302. ParseError( CONSTANT_TOO_BIG, (char *)NULL );
  303. }
  304. return answer;
  305. }
  306. void SkipToToken(token_t token)
  307. {
  308. token_t NextToken;
  309. do {
  310. NextToken = GetNextToken();
  311. } while( ( token != NextToken) && (EOI != NextToken) );
  312. }
  313. MODIFIER_SET ParseUnknownDeclSpecItem(char *pIdentifier)
  314. {
  315. INITIALIZED_MODIFIER_SET ModifierSet;
  316. unsigned long Level = 0;
  317. char AppendTxt[512];
  318. unsigned int CurChar = 0;
  319. memset( AppendTxt, '\0', sizeof(AppendTxt) );
  320. const unsigned int MaxCurChar = 512 - 1 - sizeof(')') - sizeof(' ') - sizeof('\0');
  321. char ch;
  322. short ci;
  323. for(;;) // skip white space
  324. {
  325. ci = ct[ (unsigned char)(ch = NewCCGetch()) ];
  326. if (0 == st[ 0 ][ ci & 0x00ff ])
  327. {
  328. AppendTxt[CurChar++] = ch;
  329. if ( CurChar >= MaxCurChar )
  330. {
  331. ParseError(SYNTAX_ERROR, "Invalid _declspec");
  332. return ModifierSet;
  333. }
  334. }
  335. else
  336. break;
  337. }
  338. if ('(' == ch)
  339. {
  340. // identifier(...) form
  341. Level++;
  342. AppendTxt[CurChar++] = '(';
  343. do
  344. {
  345. ch = NewCCGetch();
  346. switch(ch)
  347. {
  348. case 0:
  349. //end of file
  350. goto Exit;
  351. case '(':
  352. Level++;
  353. break;
  354. case ')':
  355. Level--;
  356. break;
  357. }
  358. AppendTxt[CurChar++] = ch;
  359. if ( CurChar >= MaxCurChar )
  360. {
  361. ParseError(SYNTAX_ERROR, "Invalid _declspec");
  362. return ModifierSet;
  363. }
  364. }
  365. while ( Level );
  366. }
  367. else
  368. {
  369. NewCCputbackc(ch);
  370. }
  371. Exit:
  372. AppendTxt[CurChar++] = ')';
  373. AppendTxt[CurChar++] = ' ';
  374. size_t StringLength = sizeof("__declspec(") + strlen(pIdentifier) + CurChar + sizeof('\0');
  375. char *UnknownDeclspec = new char[StringLength];
  376. strcpy( UnknownDeclspec, "__declspec(");
  377. strcat( UnknownDeclspec, pIdentifier );
  378. strcat( UnknownDeclspec, AppendTxt);
  379. ModifierSet.SetDeclspecUnknown( UnknownDeclspec );
  380. delete[] UnknownDeclspec;
  381. return ModifierSet;
  382. }
  383. #pragma warning(push)
  384. #pragma warning( disable : 4244 ) // disable long to short conversion warning
  385. MODIFIER_SET ParseDeclSpecAlign()
  386. {
  387. unsigned short AlignmentValue = 8;
  388. toktyp_G = GetNextToken();
  389. if (toktyp_G != '(')
  390. {
  391. ParseError( BENIGN_SYNTAX_ERROR, "( expected after _declspec( align");
  392. UngetToken(toktyp_G);
  393. goto exit;
  394. }
  395. toktyp_G = GetNextToken();
  396. switch(toktyp_G)
  397. {
  398. case NUMERICCONSTANT:
  399. case NUMERICLONGCONSTANT:
  400. case HEXCONSTANT:
  401. case HEXLONGCONSTANT:
  402. case OCTALCONSTANT:
  403. case OCTALLONGCONSTANT:
  404. case NUMERICUCONSTANT:
  405. case NUMERICULONGCONSTANT:
  406. case HEXUCONSTANT:
  407. case HEXULONGCONSTANT:
  408. case OCTALUCONSTANT:
  409. case OCTALULONGCONSTANT:
  410. break; //valid case
  411. default:
  412. ParseError( MSCDECL_INVALID_ALIGN, NULL);
  413. SkipToToken(')');
  414. goto exit;
  415. }
  416. //Check if value is nonzero power of 2 <= 8192
  417. switch((long)tokval_G)
  418. {
  419. case 1:
  420. case 2:
  421. case 4:
  422. case 8:
  423. case 16:
  424. case 32:
  425. case 64:
  426. case 128:
  427. case 256:
  428. case 512:
  429. case 1024:
  430. case 2048:
  431. case 4096:
  432. case 8192:
  433. AlignmentValue = (unsigned short)tokval_G;
  434. break; //valid case
  435. default:
  436. ParseError( MSCDECL_INVALID_ALIGN, NULL);
  437. AlignmentValue = 8;
  438. break;
  439. }
  440. toktyp_G = GetNextToken();
  441. if (toktyp_G != ')')
  442. {
  443. ParseError( BENIGN_SYNTAX_ERROR, ") expected to follow _declspec(align(N \n");
  444. SkipToToken(')');
  445. }
  446. exit:
  447. INITIALIZED_MODIFIER_SET ModifierSet;
  448. ModifierSet.SetDeclspecAlign(AlignmentValue);
  449. ParseError( BENIGN_SYNTAX_ERROR, "_declspec(align()) is not supported." );
  450. return ModifierSet;
  451. }
  452. #pragma warning(pop)
  453. token_t ParseDeclSpec()
  454. {
  455. /* Parses the MS_VC declspec() syntax.
  456. syntax: _declspec(declspeclist )
  457. declspeclist: declspecitemlist declspecitem |
  458. declspecitem |
  459. nothing
  460. declspecitem: identifier |
  461. identifier(...)
  462. */
  463. token_t LParen = GetNextToken();
  464. if ('(' != LParen)
  465. {
  466. ParseError( BENIGN_SYNTAX_ERROR, "( expected after _declspec");
  467. return LParen;
  468. }
  469. // Disable ID to keyword mapping.
  470. BOOL OldIdToKeywordMapping = IdToKeywordMapping;
  471. IdToKeywordMapping = FALSE;
  472. INITIALIZED_MODIFIER_SET ModifierSet;
  473. for(;;)
  474. {
  475. // VC skips comma, so we skip commas.
  476. while(',' == (toktyp_G = GetNextToken()));
  477. if (')' == toktyp_G)
  478. {
  479. break;
  480. }
  481. if (IDENTIFIER == toktyp_G || TYPENAME == toktyp_G || LIBNAME == toktyp_G)
  482. {
  483. if (strcmp( tokptr_G, "dllimport") == 0)
  484. {
  485. ModifierSet.SetModifier(ATTR_DLLIMPORT);
  486. }
  487. else if (strcmp( tokptr_G, "dllexport") == 0)
  488. {
  489. ModifierSet.SetModifier(ATTR_DLLEXPORT);
  490. }
  491. else if (strcmp( tokptr_G, "align") == 0)
  492. {
  493. ModifierSet.Merge(ParseDeclSpecAlign());
  494. }
  495. else
  496. {
  497. ModifierSet.Merge(ParseUnknownDeclSpecItem(tokptr_G));
  498. }
  499. }
  500. else
  501. {
  502. ParseError( BENIGN_SYNTAX_ERROR, "Invalid _declspec" );
  503. SkipToToken(')');
  504. break;
  505. }
  506. }
  507. IdToKeywordMapping = OldIdToKeywordMapping;
  508. yylval.yy_modifiers = ModifierSet;
  509. return (toktyp_G = KWMSCDECLSPEC);
  510. }
  511. const extern short ct[256];
  512. const extern short st[13][16];
  513. token_t name(void)
  514. {
  515. /* have received a name from the input file, first we */
  516. /* check to see if it is a keyword. */
  517. short InBracket = short( inside_rpc ? INBRACKET : 0 );
  518. if ( IdToKeywordMapping )
  519. toktyp_G = is_keyword(tokptr_G, InBracket);
  520. else
  521. toktyp_G = IDENTIFIER;
  522. if (KWMSCDECLSPEC == toktyp_G)
  523. {
  524. return ParseDeclSpec();
  525. }
  526. if( KWSAFEARRAY == toktyp_G)
  527. {
  528. /* SAFEARRAY is a special case
  529. * In order to correctly parse the ODL SAFEARRAY syntax:
  530. * SAFEARRAY ( FOO * ) BAR;
  531. * we look ahead at the next non white space character
  532. * to see if it's an open parenthasis. If it is then we eat
  533. * the character and return KWSAFEARRAY, otherwise we
  534. * put the character back into the stream and return the
  535. * string "SAFEARRAY" as an IDENTIFIER.
  536. */
  537. char ch;
  538. short ci;
  539. do
  540. ci = ct[ (unsigned char)(ch = NewCCGetch()) ];
  541. while (0 == st[ 0 ][ ci & 0x00ff ]); /* skip white space */
  542. if ('(' != ch)
  543. {
  544. NewCCputbackc(ch);
  545. toktyp_G = IDENTIFIER;
  546. }
  547. }
  548. if (toktyp_G == IDENTIFIER)
  549. {
  550. if( strlen( tokptr_G ) > MAX_ID_LENGTH )
  551. {
  552. ParseError( ID_TRUNCATED, tokptr_G );
  553. // tokptr_G[ MAX_ID_LENGTH ] = '\0'; // dont truncate
  554. }
  555. /* We need to know if the identifier is followed by a period.
  556. * If it is, it may be a library name and so we need to check
  557. * the libary name table to see if we should return LIBNAME
  558. * instead of TYPENAME or IDENTIFIER.
  559. * We look ahead to the next non white space character as above;
  560. * the difference being that we do not consume the non whitespace
  561. * character as we would for "SAFEARRAY(".
  562. */
  563. char ch;
  564. short ci;
  565. do
  566. ci = ct[ (unsigned char)(ch = NewCCGetch()) ];
  567. while (0 == st[ 0 ][ ci & 0x00ff ]); /* skip white space */
  568. NewCCputbackc(ch);
  569. if( '.' == ch )
  570. {
  571. // we need to check to see if the identifier is a library name
  572. if (FIsLibraryName(tokptr_G))
  573. {
  574. toktyp_G = LIBNAME;
  575. yylval.yy_pSymName = new char [toklen_G + 1];
  576. strcpy(yylval.yy_pSymName, tokptr_G);
  577. return toktyp_G;
  578. }
  579. }
  580. /* Check the symbol table to see if the identifier
  581. * is a TYPENAME.
  582. */
  583. #ifdef unique_lextable
  584. // all names go in the lex table -- this is important for the symtable search
  585. yylval.yy_pSymName = pMidlLexTable->LexInsert(tokptr_G);
  586. // see if the name corresponds to a base level typedef
  587. SymKey SKey( yylval.yy_pSymName, NAME_DEF );
  588. if( pBaseSymTbl->SymSearch( SKey ) )
  589. {
  590. toktyp_G = TYPENAME;
  591. }
  592. }
  593. #else // unique_lextable
  594. // see if the name corresponds to a base level typedef
  595. SymKey SKey( tokptr_G, NAME_DEF );
  596. named_node * pNode;
  597. if ( ( pNode = pBaseSymTbl->SymSearch( SKey ) ) != 0 )
  598. {
  599. char * szTemp = new char[toklen_G + 1];
  600. strcpy(szTemp, tokptr_G);
  601. pNode->SetCurrentSpelling(szTemp);
  602. toktyp_G = TYPENAME;
  603. yylval.yy_graph = pNode;
  604. }
  605. else
  606. {
  607. yylval.yy_pSymName = pMidlLexTable->LexInsert(tokptr_G);
  608. }
  609. }
  610. #endif // unique_lextable
  611. return toktyp_G;
  612. }
  613. void lex_error(int number)
  614. {
  615. printf("lex error : %d\n", number);
  616. }