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.

1168 lines
33 KiB

  1. /********************************** module *********************************/
  2. /* Copyright (c) 1993-2000 Microsoft Corporation */
  3. /* */
  4. /* cclex */
  5. /* lexical analyser for the C compiler */
  6. /* */
  7. /***************************************************************************/
  8. /* */
  9. /* @ Purpose: */
  10. /* */
  11. /* @ Functions included: */
  12. /* */
  13. /* */
  14. /* @ Author: Gerd Immeyer @ Version: */
  15. /* */
  16. /* @ Creation Date: 1987.02.09 @ Modification Date: */
  17. /* */
  18. /***************************************************************************/
  19. #pragma warning ( disable : 4514 4310 4710 )
  20. #include "nulldefs.h"
  21. extern "C" {
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. }
  27. #include "common.hxx"
  28. #include "errors.hxx"
  29. #include "midlnode.hxx"
  30. #include "listhndl.hxx"
  31. #include "filehndl.hxx"
  32. #include "lextable.hxx"
  33. #include "lexutils.hxx"
  34. #include "grammar.h"
  35. #include "gramutil.hxx"
  36. #include "cmdana.hxx"
  37. #include "mbcs.hxx"
  38. extern "C" {
  39. #include "lex.h"
  40. }
  41. extern void ParseError( STATUS_T, char *);
  42. extern NFA_INFO *pImportCntrl;
  43. extern lextype_t yylval;
  44. extern token_t toktyp_G; /* token type */
  45. extern short toklen_G; /* len of token string */
  46. extern char *tokptr_G; /* pointer to token string */
  47. extern long tokval_G; /* value of constant token */
  48. extern short curr_line_G;
  49. extern LexTable *pMidlLexTable;
  50. extern short CompileMode;
  51. extern CMD_ARG * pCommand;
  52. int chCached = 0;
  53. char NewCCputbackc( char ch )
  54. {
  55. if (chCached)
  56. {
  57. pImportCntrl->UnGetChar(short(chCached));
  58. }
  59. chCached = ch;
  60. if ( ch == '\n' )
  61. curr_line_G--;
  62. return ch;
  63. }
  64. /***** definition of state table fields ****/
  65. #define ERR 0x7f0c /* character not in character set */
  66. #define X10 0x0100
  67. #define X11 0x0101
  68. #define X20 0x0200
  69. #define X21 0x0201
  70. #define X23 0x0203
  71. #define X30 0x0300
  72. #define X40 0x0400
  73. #define X41 0x0401
  74. #define X43 0x0403
  75. #define X50 0x0500
  76. #define X51 0x0501
  77. #define X53 0x0503
  78. #define X62 0x0602
  79. #define X70 0x0700
  80. #define X71 0x0701
  81. #define X73 0x0703
  82. #define X82 0x0802
  83. #define X90 0x0900
  84. #define X91 0x0901
  85. #define XLQ 0x0a00
  86. #define XLD 0x0b00
  87. /*---- define of single operators ----*/
  88. #define O65 0x410d /* ' 65 */
  89. #define O43 ('(' * 256 + 12) /* ( 43 */
  90. #define O44 (')' * 256 + 12) /* ) 44 */
  91. #define O49 (',' *256 + 12) /* , 49 */
  92. #define O24 ('.' *256 + 10) /* . 24 */
  93. #define O14 (':' *256 + 12) /* : 14 */
  94. #define O50 (';' *256 + 12) /* ; 50 */
  95. #define O13 ('?' *256 + 12) /* ? 13 */
  96. #define O47 ('[' *256 + 12) /* [ 47 */
  97. #define O48 (']' *256 + 12) /* ] 48 */
  98. #define O45 ('{' *256 + 12) /* { 45 */
  99. #define O46 ('}' *256 + 12) /* } 46 */
  100. #define O23 ('~' *256 + 12) /* ~ 23 */
  101. #define OHS ('#' *256 + 12) /* # */
  102. #define O64 0x400e /* " 64 */
  103. #define O7d 0x0000 /* eol */
  104. #define O7e (short)0x9f0c /* eof */
  105. /*---- define of possible multi character operator ----*/
  106. #define D00 0x000b /* - 00 */
  107. #define D01 0x010c /* / 01 */
  108. #define D02 0x020c /* < 02 */
  109. #define D03 0x030c /* > 03 */
  110. #define D04 0x040c /* ! 04 */
  111. #define D05 0x050c /* % 05 */
  112. #define D06 0x060c /* & 06 */
  113. #define D07 0x070c /* * 07 */
  114. #define D08 0x080b /* + 08 */
  115. #define D09 0x090c /* = 09 */
  116. #define D0a 0x0a0c /* ^ 0a */
  117. #define D0b 0x0b0c /* | 0b */
  118. /***** character table *****/
  119. /* MIDL supports the ANSI character set as input */
  120. const extern short ct[256]= {
  121. /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
  122. O7e,ERR,ERR,ERR,ERR, 0,ERR,ERR,ERR, 0,O7d,ERR, 0, 0,ERR,ERR,
  123. /* 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f */
  124. ERR,ERR,ERR,ERR,ERR,ERR,ERR,ERR,ERR,ERR,O7e,ERR,ERR,ERR,ERR,ERR,
  125. /* ! " # $ % & ' ( ) * + , - . / */
  126. 0,D04,O64,OHS,ERR,D05,D06,O65,O43,O44,D07,D08,O49,D00,O24,D01,
  127. /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
  128. 7, 8, 8, 8, 8, 8, 8, 8, 9, 9,O14,O50,D02,D09,D03,O13,
  129. /* @ A B C D E F G H I J K L M N O */
  130. ERR, 1, 1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 15, 4, 4, 4,
  131. /* P Q R S T U V W X Y Z [ \ ] ^ _ */
  132. 4, 4, 4, 4, 4, 4, 4, 4, 6, 4, 4,O47,ERR,O48,D0a, 4,
  133. /* ` a b c d e f g h i j k l m n o */
  134. ERR, 1, 1, 1, 1, 2, 3, 4, 4, 4, 4, 4, 5, 4, 4, 4,
  135. /* p q r s t u v w x y z { | } ~ DEL */
  136. 4, 4, 4, 4, 4, 4, 4, 4, 6, 4, 4,O45,D0b,O46,O23,ERR,
  137. /* 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f */
  138. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  139. /* 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f */
  140. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  141. /* a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af */
  142. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  143. /* b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf */
  144. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  145. /* c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf */
  146. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  147. /* d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df */
  148. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  149. /* e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef */
  150. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  151. /* f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff */
  152. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
  153. /***** state transition table *****/
  154. const extern short st[ 13 ][ 16 ] = {
  155. // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  156. // spc a-d e f g-z l x 0 1-7 8-9 . + - op ' " L
  157. //
  158. /* start 0 */ 0, 1, 1, 1, 1, 1, 1, 2, 5, 5,X90,X90,X90,X90,X90, 12,
  159. /* name 1 */ X10, 1, 1, 1, 1, 1, 1, 1, 1, 1,X11,X11,X11,X11,X11, 1,
  160. /* 0 2 */ X20,X23, 9,X23,X23,X30, 3, 6, 6, 6,X23,X21,X21,X21,X21,X30,
  161. /* 0x 3 */ X53, 4, 4, 4,X53,X53,X53, 4, 4, 4,X53,X53,X53,X53,X53,X53,
  162. /* hex 4 */ X50, 4, 4, 4,X53,X53,X53, 4, 4, 4,X53,X51,X51,X51,X51,X53,
  163. /* int 5 */ X20,X23, 9,X23,X23,X23,X23, 5, 5, 5,X21,X21,X21,X21,X21,X23,
  164. /* oct 6 */ X70,X73, 9,X73,X73,X73,X73, 6, 6, 5, 8,X71,X71,X71,X71,X73,
  165. /* . 7 */ X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,X91,
  166. /* int. 8 */ X40,X43, 9,X43,X43,X43,X43, 8, 8, 8,X43,X41,X41,X41,X41,X43,
  167. /* .e 9 */ X40,X43,X43,X43,X43,X43,X43, 11, 11, 11,X43, 10,X41,X41,X41,X43,
  168. /* .e- 10*/ X43,X43,X43,X43,X43,X43,X43, 11, 11, 11,X43,X43,X43,X43,X43,X43,
  169. /* .e-i 11*/ X40,X43,X43,X43,X43,X43,X43, 11, 11, 11,X43,X41,X41,X41,X41,X43,
  170. /* L 12*/ X10, 1, 1, 1, 1, 1, 1, 1, 1, 1,X11,X11,X11,XLQ,XLD, 1
  171. };
  172. /***** multi character operator table *****/
  173. const token_t moptab[] = {
  174. /* 0 1 2 3 4 5 6 7 8 9 10 11 */
  175. /* - / < > ! % & * + = ^ | */
  176. /* */
  177. /* single */ MINUS,DIV,LT,GT,EXCLAIM, MOD,
  178. AND, MULT, PLUS, ASSIGN, XOR, OR,
  179. /* op = */ SUBASSIGN, DIVASSIGN, LTEQ, GTEQ, NOTEQ,
  180. MODASSIGN, ANDASSIGN, MULASSIGN, ADDASSIGN, EQUALS,
  181. XORASSIGN, ORASSIGN,
  182. /* op op */ DECOP, GARBAGETOKEN, LSHIFT, RSHIFT, 0, 0,
  183. ANDAND, 0, INCOP, EQUALS, 0, OROR };
  184. /***** define of the action routines *****/
  185. token_t name(void);
  186. token_t mulop(void);
  187. token_t character(void);
  188. token_t string(void);
  189. token_t ProcessHash();
  190. token_t ProcessComplexDefine( char *, char *, int );
  191. token_t LChar();
  192. token_t LStr();
  193. extern token_t ScanGuid( void );
  194. extern token_t ScanVersion( void );
  195. extern token_t ScanImplicitImports(void);
  196. typedef token_t (*TOKEN_PFN)(void);
  197. const static TOKEN_PFN action[] = {
  198. 0, /* unused */
  199. name, /* handle name token */
  200. cnv_int, /* convert integer token */
  201. cnv_int, /* convert integer token */
  202. cnv_hex, /* convert hex constant */
  203. cnv_hex, /* convert hex constant */
  204. cnv_octal, /* convert octal constant */
  205. cnv_octal, /* convert octal constant */
  206. cnv_float, /* convert floating point constant */
  207. mulop, /* handle multi character operator */
  208. LChar, /* wide character */
  209. LStr, /* wide character string */
  210. };
  211. /***** declare of global varables *****/
  212. static short ci; /* current state character index */
  213. static char ch; /* current character */
  214. static int pbch; /* flag describing whether to take the next char
  215. or not */
  216. char LastLexChar;
  217. unsigned short LexContext = LEX_NORMAL;
  218. #define MAX_LINE_SIZE 256
  219. static char tok_buffer[MAX_LINE_SIZE];
  220. token_t IsValidPragma( char *);
  221. /*............................. internal function ..........................*/
  222. /* */
  223. /* comment analyzer */
  224. /* */
  225. token_t comment()
  226. {
  227. BOOL fParseError = FALSE;
  228. for (;;)
  229. {
  230. ch = NewCCGetch();
  231. if (ch == 0)
  232. {
  233. fParseError = TRUE;
  234. break;
  235. }
  236. if (CurrentCharSet.IsMbcsLeadByte(ch))
  237. {
  238. NewCCGetch();
  239. }
  240. else if (ch == '*')
  241. {
  242. char chNext = NewCCGetch();
  243. if (chNext == 0)
  244. {
  245. fParseError = TRUE;
  246. break;
  247. }
  248. if (CurrentCharSet.IsMbcsLeadByte(chNext))
  249. {
  250. NewCCGetch();
  251. }
  252. else if (chNext == '/')
  253. {
  254. break;
  255. }
  256. else if (chNext == '*')
  257. {
  258. NewCCputbackc(chNext);
  259. }
  260. }
  261. }
  262. if (fParseError)
  263. {
  264. ParseError(EOF_IN_COMMENT, (char *)NULL); /* no end of comment operator */
  265. exit( EOF_IN_COMMENT );
  266. }
  267. return ( NOTOKEN );
  268. }
  269. token_t commentline()
  270. {
  271. for (;;)
  272. {
  273. ch = NewCCGetch();
  274. if( ch == 0 )
  275. {
  276. ParseError(EOF_IN_COMMENT, (char *)NULL);
  277. exit( EOF_IN_COMMENT );
  278. break;
  279. }
  280. else if (CurrentCharSet.IsMbcsLeadByte(ch))
  281. {
  282. NewCCGetch();
  283. }
  284. else if (ch == '\n')
  285. {
  286. break;
  287. }
  288. }
  289. return ( NOTOKEN ); /* get the next token */
  290. }
  291. /*............................. internal function ..........................*/
  292. /* */
  293. /* multi character operator */
  294. /* */
  295. const static token_t *snglop = &moptab[0]; /* adr of single character operator */
  296. const static token_t *assgop = &moptab[12]; /* adr of assignment operator */
  297. const static token_t *dblop = &moptab[24]; /* adr of double character operator */
  298. token_t mulop()
  299. {
  300. REG unsigned short i; /* index into multi operator table */
  301. REG char lstch;
  302. //printf ("in mulop ch = %c\n", ch);
  303. i = unsigned short(((unsigned short)ci) >> 8); /* get high byte of character index */
  304. if( i > 11 ) { /* is it a type specification ? */
  305. // check for EOI
  306. if ( ci == short(0x9f0c) )
  307. {
  308. if(pImportCntrl->GetLexLevel() == 0)
  309. {
  310. if(pImportCntrl->GetEOIFlag())
  311. return 0;
  312. else
  313. pImportCntrl->SetEOIFlag();
  314. }
  315. return EOI;
  316. }
  317. if( i == 64 ) /* character is " */
  318. return ( string() ); /* handle string token */
  319. if( i == 65 ) /* character is ' */
  320. return ( character() ); /* handle character constant */
  321. if( i == '#' )
  322. return ProcessHash(); /* process any hash tokens */
  323. if( i == '.' )
  324. {
  325. if( (ch = NewCCGetch()) == '.' )
  326. {
  327. return DOTDOT;
  328. }
  329. NewCCputbackc( ch );
  330. }
  331. if ( i == LBRACK )
  332. {
  333. inside_rpc++;
  334. return i;
  335. }
  336. if ( i == RBRACK )
  337. {
  338. inside_rpc--;
  339. return i;
  340. }
  341. return ( i ); /* return type of single operator */
  342. }
  343. lstch = ch; /* save entry character */
  344. ch = NewCCGetch(); /* get a new one */
  345. if (CurrentCharSet.IsMbcsLeadByte(ch))
  346. {
  347. toklen_G = 1;
  348. tokptr_G[1] = 0;
  349. NewCCputbackc(ch);
  350. return *(snglop+i);
  351. }
  352. tokptr_G[1] = ch; tokptr_G[2] = 0;
  353. toklen_G = 2; /* add to token string */
  354. if( ch == '=' ) { /* is next character an equal op. */
  355. return *(assgop+i); /* return an assign operator */
  356. }
  357. if( lstch == ch ) { /* is next char. = current char. ? */
  358. toktyp_G = *(dblop+i); /* yes, get its type */
  359. if( !toktyp_G ) { /* is it a doppel operator ? */
  360. toklen_G = 1; /* update token string */
  361. tokptr_G[1] = 0;
  362. NewCCputbackc(ch); /* deliberate, puback of EOF is ignored */
  363. return *(snglop+i); /* no, return single operator */
  364. }
  365. if( ch == '/' ) /* if the operator is double // */
  366. {
  367. // potentially an error
  368. // ParseError( SINGLE_LINE_COMMENT, (char *)0 );
  369. return(commentline()); /* the next line is a comment */
  370. }
  371. ch = NewCCGetch(); /* get next character */
  372. if (ch == '=') {
  373. tokptr_G[2] = '='; tokptr_G[3] = '\0';
  374. toklen_G = 3; /* update token string */
  375. if(toktyp_G == LSHIFT) { /* if shift op.and equal sign ? */
  376. return (LEFTASSIGN); /* return as assign operator */
  377. }
  378. if(toktyp_G == RSHIFT) {
  379. return (RIGHTASSIGN);
  380. }
  381. tokptr_G[2] = '\0'; toklen_G = 2;
  382. }
  383. NewCCputbackc(ch); /* put back unused character */
  384. return (toktyp_G); /* else return doppel char. operator */
  385. }
  386. if( lstch == '-' && ch == '>' ) { /* if structure operator */
  387. return (POINTSTO); /* return structure operator */
  388. }
  389. if( lstch == '/' && ch == '*' ) { /* if comment */
  390. return( comment() ); /* ignore the comment */
  391. }
  392. tokptr_G[1] = '\0'; toklen_G = 1; /* remove from token string */
  393. NewCCputbackc(ch); /* putback unused character */
  394. return *(snglop+i); /* return single character operator */
  395. }
  396. /*............................. internal function ..........................*/
  397. /* */
  398. /* convert escape (\) character */
  399. /* */
  400. char convesc()
  401. {
  402. unsigned short value = 0;
  403. unsigned short tmp;
  404. BOOL fConstantIsIllegal = FALSE;
  405. ch = NewCCGetch();
  406. if ( ch == 'n' )
  407. ch = 0xa;
  408. else if (ch == 't')
  409. ch = 0x9;
  410. else if (ch == 'v')
  411. ch = 0xb;
  412. else if (ch == 'b')
  413. ch = 0x8;
  414. else if( ch == 'r' )
  415. ch = 0xd;
  416. else if( ch == 'f' )
  417. ch = 0xc;
  418. else if( ch == 'a' )
  419. ch = 0x7;
  420. else if( (ch == 'x') || (ch == 'X') )
  421. {
  422. int i;
  423. for( i = 0, value = 0, fConstantIsIllegal = FALSE; i < 2; ++i )
  424. {
  425. tmp = ch = NewCCGetch();
  426. tmp = (unsigned short)toupper( tmp );
  427. if( isxdigit( tmp ) )
  428. {
  429. tmp = unsigned short( (tmp >= '0') && (tmp <= '9') ? (tmp - '0') : (tmp - 'A') + 0xa );
  430. }
  431. else if( ch == '\'' )
  432. {
  433. NewCCputbackc( ch );
  434. break;
  435. }
  436. else
  437. {
  438. fConstantIsIllegal = TRUE;
  439. }
  440. value = unsigned short( value * 16 + tmp );
  441. }
  442. if( fConstantIsIllegal || (value > (unsigned short) 0x00ff) )
  443. ParseError( ILLEGAL_CONSTANT, (char *)0 );
  444. ch = (char )value;
  445. }
  446. else if( (ch >= '0') && (ch <= '7'))
  447. {
  448. int i;
  449. value = unsigned short(ch - '0');
  450. // the limit for this for loop is 2 because we already saw 1 character
  451. for ( i = 0, value = unsigned short(ch - '0'), fConstantIsIllegal = FALSE; i < 2; ++i)
  452. {
  453. tmp = ch = NewCCGetch();
  454. if( (ch >= '0') && (ch <= '7'))
  455. {
  456. tmp = unsigned short(tmp - '0');
  457. value = unsigned short(value * 8 + tmp);
  458. }
  459. else if( ch == '\'' )
  460. {
  461. NewCCputbackc( ch );
  462. break;
  463. }
  464. else
  465. fConstantIsIllegal = TRUE;
  466. }
  467. if( fConstantIsIllegal || (value > (unsigned short) 0x00ff) )
  468. ParseError( ILLEGAL_CONSTANT, (char *)0 );
  469. ch = (char )value;
  470. }
  471. return ( ch );
  472. }
  473. /*............................. internal function ..........................*/
  474. /* */
  475. /* string analyzer */
  476. /* */
  477. token_t
  478. character()
  479. {
  480. ch = NewCCGetch();
  481. if (CurrentCharSet.IsMbcsLeadByte(ch))
  482. {
  483. tokptr_G[0] = ch;
  484. tokptr_G[1] = NewCCGetch();
  485. tokptr_G[2] = 0;
  486. toklen_G = 2;
  487. }
  488. else
  489. {
  490. if (ch == '\\')
  491. {
  492. ch = convesc();
  493. }
  494. tokptr_G[0] = ch;
  495. tokptr_G[1] = '\0';
  496. yylval.yy_numeric.Val = tokval_G = ch;
  497. }
  498. if (NewCCGetch() != '\'')
  499. {
  500. ParseError(CHAR_CONST_NOT_TERMINATED,(char *)NULL );
  501. exit( CHAR_CONST_NOT_TERMINATED );
  502. }
  503. return (CHARACTERCONSTANT);
  504. }
  505. // this rtn is called when the quote has been sensed.
  506. char* g_pchStrBuffer = 0;
  507. unsigned long g_ulStrBufferLen = 1024;
  508. //
  509. // Scan ahead in the current file to see if the next non-space character is a
  510. // quote. If it is then this is a string constant that is split into two
  511. // pieces (e.g. "this" ... " is a " ... "test"). If the next character is
  512. // not a quote reset the file back to where we started from.
  513. //
  514. // If this is a multi-string situation return MULTIPLE_PROPERTY_ATTRIBUTES.
  515. // This is a bit of a mis-use of that error code but it sounds nice.
  516. //
  517. // HACKHACK: The routine depends on internal knowledge of how NewCCGetch works.
  518. // Doing something similiar using the grammar was tried but failed
  519. // when processing imports because of details of how the trickery
  520. // played on the lexer works to get it to change streams in mid-go.
  521. //
  522. STATUS_T spacereadahead()
  523. {
  524. fpos_t fpos;
  525. short newlines = 0;
  526. int ch = ' ';
  527. if (0 != fgetpos(hFile_G, &fpos))
  528. return INPUT_READ;
  529. while (isspace(ch) && !feof(hFile_G))
  530. {
  531. ch = getc(hFile_G);
  532. if ( '\n' == ch )
  533. ++newlines;
  534. }
  535. if ('\"' == ch)
  536. {
  537. curr_line_G = (short) (curr_line_G + newlines);
  538. return MULTIPLE_PROPERTY_ATTRIBUTES;
  539. }
  540. else
  541. {
  542. if (0 != fsetpos(hFile_G, &fpos))
  543. return INPUT_READ;
  544. return STATUS_OK;
  545. }
  546. }
  547. token_t
  548. string()
  549. {
  550. STATUS_T Status = STATUS_OK;
  551. char * ptr;
  552. if ( !g_pchStrBuffer )
  553. {
  554. g_pchStrBuffer = ( char * )malloc( sizeof( char ) * g_ulStrBufferLen );
  555. if ( NULL == g_pchStrBuffer )
  556. {
  557. RpcError( 0, 0, OUT_OF_MEMORY, 0 );
  558. exit( OUT_OF_MEMORY );
  559. }
  560. }
  561. strncpy( g_pchStrBuffer, tokptr_G, toklen_G );
  562. ptr = g_pchStrBuffer;
  563. ch = 0;
  564. while( ( ch != '"' ) && ( Status == STATUS_OK ) )
  565. {
  566. if ( ( unsigned long ) ( ptr - g_pchStrBuffer ) > ( g_ulStrBufferLen - 3 ) )
  567. {
  568. char* pTempStrBuffer = ( char* ) realloc( g_pchStrBuffer, g_ulStrBufferLen * 2 );
  569. if ( pTempStrBuffer )
  570. {
  571. ptr = ( g_pchStrBuffer - ptr ) + pTempStrBuffer;
  572. g_pchStrBuffer = pTempStrBuffer;
  573. g_ulStrBufferLen = g_ulStrBufferLen * 2;
  574. }
  575. else
  576. {
  577. Status = STRING_TOO_LONG;
  578. }
  579. }
  580. ch = NewCCGetch();
  581. if( ch == 0 )
  582. {
  583. Status = EOF_IN_STRING;
  584. }
  585. else if ( ch == '\\' )
  586. {
  587. *ptr++ = ch;
  588. *ptr++ = NewCCGetch();
  589. ch = 0;
  590. }
  591. else if ( ch != '\"' )
  592. {
  593. *ptr++ = ch;
  594. if (CurrentCharSet.IsMbcsLeadByte(ch))
  595. *ptr++ = NewCCGetch();
  596. }
  597. else
  598. {
  599. Status = spacereadahead();
  600. if ( MULTIPLE_PROPERTY_ATTRIBUTES == Status )
  601. {
  602. Status = STATUS_OK;
  603. ch = 0;
  604. }
  605. }
  606. }
  607. *ptr = 0;
  608. if( Status != STATUS_OK )
  609. {
  610. ParseError( Status, (char *)0 );
  611. exit( Status );
  612. }
  613. yylval.yy_string = pMidlLexTable->LexInsert( g_pchStrBuffer );
  614. return ( STRING );
  615. }
  616. /****************************** external function ***************************/
  617. /* */
  618. /* lexical analyzer */
  619. /* */
  620. static BOOL fLastToken = 0;
  621. static BOOL fLineLengthError = 0;
  622. static token_t LastToken;
  623. void
  624. initlex()
  625. {
  626. fLastToken = 0;
  627. }
  628. void
  629. yyunlex( token_t T )
  630. {
  631. LastToken = T;
  632. fLastToken = 1;
  633. }
  634. token_t yylex()
  635. {
  636. REG short state; /* token state */
  637. REG char *ptr;
  638. if( fLastToken )
  639. {
  640. fLastToken = 0;
  641. return LastToken;
  642. }
  643. if ( LexContext != LEX_NORMAL )
  644. {
  645. switch ( LexContext )
  646. {
  647. case LEX_GUID:
  648. {
  649. LexContext = LEX_NORMAL;
  650. return ScanGuid();
  651. }
  652. case LEX_VERSION:
  653. {
  654. LexContext = LEX_NORMAL;
  655. return ScanVersion();
  656. }
  657. case LEX_ODL_BASE_IMPORT:
  658. case LEX_ODL_BASE_IMPORT2:
  659. {
  660. return ScanImplicitImports();
  661. break;
  662. }
  663. default:
  664. MIDL_ASSERT(0);
  665. }
  666. }
  667. again:
  668. state = 0; /* initial state */
  669. ptr = tokptr_G = tok_buffer; /* remember token begin position */
  670. toklen_G = 0;
  671. do
  672. {
  673. ci = ct[ (unsigned char) (ch=NewCCGetch()) ]; /* character index out of char.tab. */
  674. state = st[ state ][ ci & 0x00ff ]; /* determine new state */
  675. } while ( state == 0 ); /* skip white space */
  676. *(ptr++) = ch;
  677. toklen_G++; /* add chacter to token string */
  678. if (CurrentCharSet.IsMbcsLeadByte(ch))
  679. {
  680. *(ptr++) = NewCCGetch();
  681. toklen_G++;
  682. }
  683. while( state < 13 )
  684. { /* loop til end state */
  685. ci = ct[ (unsigned char) (ch=NewCCGetch()) ]; /* character index out of char.tab. */
  686. state = st[ state ][ ci & 0x00ff ]; /* determine new state */
  687. if (state < 13)
  688. { /* if still going, */
  689. if (toklen_G + 1 != MAX_LINE_SIZE) /* and the token isn't too large */
  690. {
  691. *(ptr++) = ch; toklen_G++; /* add chacter to token string */
  692. if (CurrentCharSet.IsMbcsLeadByte(ch))
  693. {
  694. *(ptr++) = NewCCGetch();
  695. toklen_G++;
  696. }
  697. }
  698. else
  699. {
  700. fLineLengthError = 1;
  701. }
  702. }
  703. };
  704. *ptr = '\0';
  705. LastLexChar = ch;
  706. if (fLineLengthError)
  707. {
  708. ParseError(IDENTIFIER_TOO_LONG, (char *)0 );
  709. fLineLengthError = 0;
  710. }
  711. switch( state & 0x00ff )
  712. {
  713. case 2: ch = NewCCGetch(); /* position to next character */
  714. break;
  715. case 3:
  716. case 1: NewCCputbackc(ch); /* position to current character */
  717. break;
  718. /* case 0 - do nothing */
  719. }
  720. //printf ("current ch = %c\n", ch);
  721. toktyp_G = (*action[ state >> 8 ])(); /* execute action */
  722. // skip fluff like #line
  723. if (toktyp_G == NOTOKEN)
  724. goto again;
  725. return(toktyp_G);
  726. }
  727. token_t
  728. LChar()
  729. {
  730. character();
  731. return WIDECHARACTERCONSTANT;
  732. }
  733. token_t
  734. LStr()
  735. {
  736. string();
  737. return WIDECHARACTERSTRING;
  738. }
  739. // process line number tokens
  740. token_t
  741. ProcessLine()
  742. {
  743. char * ptr = tokptr_G;
  744. curr_line_G = short( atoi( ptr ) - 1 );
  745. // skip spaces before file name
  746. while ( ( ch = NewCCGetch() ) == ' ' )
  747. ;
  748. ptr = tokptr_G;
  749. // see if we got a filename
  750. if ( ch == '\"' )
  751. {
  752. for (;;)
  753. {
  754. ch = NewCCGetch();
  755. *ptr++ = ch;
  756. if (CurrentCharSet.IsMbcsLeadByte(ch))
  757. {
  758. *ptr++ = NewCCGetch();
  759. }
  760. else if (ch == '\"')
  761. {
  762. break;
  763. }
  764. }
  765. *(--ptr) = '\0';
  766. StripSlashes( tokptr_G );
  767. pImportCntrl->SetLineFilename( tokptr_G );
  768. }
  769. // skip to end of line
  770. for (;;)
  771. {
  772. ch = NewCCGetch();
  773. if (ch == 0)
  774. {
  775. break;
  776. }
  777. else if (CurrentCharSet.IsMbcsLeadByte(ch))
  778. {
  779. ch = NewCCGetch();
  780. }
  781. else if (ch == '\n')
  782. {
  783. break;
  784. }
  785. }
  786. return NOTOKEN;
  787. }
  788. // process # <something>
  789. token_t
  790. ProcessHash()
  791. {
  792. char * ptr = tokptr_G,
  793. * ptrsave = ptr;
  794. token_t PragmaToken;
  795. do // eat spaces
  796. {
  797. ch = NewCCGetch();
  798. } while( isspace( ch ) );
  799. // collect first token
  800. while( !isspace( ch ) )
  801. {
  802. *ptr++ = ch;
  803. if (CurrentCharSet.IsMbcsLeadByte(ch))
  804. {
  805. *ptr++ = NewCCGetch();
  806. }
  807. ch = NewCCGetch();
  808. }
  809. *ptr = '\0';
  810. // is this hash a pragma starter ?
  811. #define PRAGMA_STRING ("pragma")
  812. #define LEN_PRAGMA_STRING (6)
  813. #define MIDL_PRAGMA_PREFIX ("midl_")
  814. #define LEN_MIDL_PRAGMA_PREFIX (5)
  815. #define LINE_STRING ("line")
  816. #define LEN_LINE_STRING (4)
  817. // we handle #pragma and #line directives
  818. // #line found
  819. if (strncmp( tokptr_G, LINE_STRING, LEN_LINE_STRING ) == 0 )
  820. {
  821. ptr = tokptr_G;
  822. // get the next token (the number)
  823. do // eat spaces
  824. {
  825. ch = NewCCGetch();
  826. } while( isspace( ch ) );
  827. // collect first token
  828. while( !isspace( ch ) )
  829. {
  830. *ptr++ = ch;
  831. if (CurrentCharSet.IsMbcsLeadByte(ch))
  832. {
  833. *ptr++ = NewCCGetch();
  834. }
  835. ch = NewCCGetch();
  836. }
  837. *ptr = '\0';
  838. return ProcessLine(); // this needs to be called with tokptr_G pointing after
  839. // the #line part
  840. }
  841. // # <number> found
  842. else if ( isdigit(*tokptr_G) )
  843. {
  844. *ptr = '\0';
  845. return ProcessLine();
  846. }
  847. else if( strncmp( tokptr_G, PRAGMA_STRING, LEN_PRAGMA_STRING ) == 0 )
  848. {
  849. // eat white space between #pragma and next word
  850. for(;;)
  851. {
  852. ch = NewCCGetch();
  853. if(!isspace(ch) ) break;
  854. *ptr++ = ch;
  855. }
  856. ptrsave = ptr;
  857. *ptr++ = ch;
  858. // pull next word in
  859. for(;;)
  860. {
  861. ch = NewCCGetch();
  862. if(!isalpha(ch) && (ch != '_') ) break;
  863. *ptr++ = ch;
  864. if (CurrentCharSet.IsMbcsLeadByte(ch))
  865. {
  866. *ptr++ = NewCCGetch();
  867. }
  868. }
  869. // put back next char (it may even be the \n)
  870. NewCCputbackc( ch );
  871. *ptr = 0;
  872. // check if it is a MIDL pragma or not
  873. if ( ( PragmaToken = IsValidPragma( ptrsave ) ) != 0 )
  874. {
  875. return PragmaToken;
  876. }
  877. // assume it is some other C pragma, so return the string
  878. for (;;)
  879. {
  880. ch = NewCCGetch();
  881. *ptr++ = ch;
  882. if (CurrentCharSet.IsMbcsLeadByte(ch))
  883. {
  884. *ptr++ = NewCCGetch();
  885. }
  886. else if (ch == '\n')
  887. {
  888. break;
  889. }
  890. }
  891. *(--ptr) = 0;
  892. yylval.yy_string = pMidlLexTable->LexInsert( ptrsave );
  893. return KWCPRAGMA;
  894. }
  895. else
  896. {
  897. // some graceful recovery by the parser
  898. return GARBAGETOKEN;
  899. }
  900. }
  901. token_t
  902. IsValidPragma(
  903. char * p )
  904. {
  905. static char * agPragmaNames[] = {
  906. "midl_import"
  907. ,"midl_echo"
  908. ,"midl_import_clnt_aux"
  909. ,"midl_import_srvr_aux"
  910. ,"pack"
  911. };
  912. static token_t agTokenVal[] = {
  913. KWMPRAGMAIMPORT
  914. ,KWMPRAGMAECHO
  915. ,KWMPRAGMAIMPORTCLNTAUX
  916. ,KWMPRAGMAIMPORTSRVRAUX
  917. ,KWCPRAGMAPACK
  918. };
  919. short Index = 0;
  920. while( Index < sizeof( agPragmaNames ) / sizeof(char *) )
  921. {
  922. if( !strcmp( p, agPragmaNames[ Index ] ) )
  923. return agTokenVal[ Index ];
  924. ++Index;
  925. }
  926. return 0;
  927. }
  928. token_t
  929. ScanGuid( void )
  930. {
  931. char c;
  932. char * p = tokptr_G;
  933. if( (c = NewCCGetch()) == '\"' )
  934. {
  935. string();
  936. ParseError( QUOTED_UUID_NOT_OSF, (char *)0 );
  937. return UUIDTOKEN;
  938. }
  939. NewCCputbackc( c );
  940. // remove leading spaces.
  941. while ( (c = NewCCGetch()) != 0 && isspace( c ) )
  942. ;
  943. while ( c && (c != ')') && (c != ',') && !isspace(c) )
  944. {
  945. *p++ = c;
  946. if (CurrentCharSet.IsMbcsLeadByte(c))
  947. {
  948. *p++ = NewCCGetch();
  949. }
  950. c = NewCCGetch();
  951. }
  952. NewCCputbackc( c );
  953. *p++ = 0;
  954. yylval.yy_string = pMidlLexTable->LexInsert(tokptr_G);
  955. return UUIDTOKEN;
  956. }
  957. token_t
  958. ScanVersion( void )
  959. {
  960. char c;
  961. char * p = tokptr_G;
  962. //
  963. // remove leading spaces.
  964. //
  965. while ( (c = NewCCGetch()) != 0 && isspace(c) )
  966. ;
  967. while ( c && (c != ')') && !isspace(c) )
  968. {
  969. *p++ = c;
  970. if (CurrentCharSet.IsMbcsLeadByte(c))
  971. {
  972. *p++ = NewCCGetch();
  973. }
  974. c = NewCCGetch();
  975. }
  976. NewCCputbackc( c );
  977. *p++ = 0;
  978. yylval.yy_string = pMidlLexTable->LexInsert(tokptr_G);
  979. return VERSIONTOKEN;
  980. }
  981. token_t
  982. ScanImplicitImports( void )
  983. {
  984. switch ( LexContext )
  985. {
  986. case LEX_ODL_BASE_IMPORT:
  987. {
  988. tokptr_G = "import";
  989. toktyp_G = KWIMPORTODLBASE;
  990. LexContext = LEX_ODL_BASE_IMPORT2;
  991. break;
  992. }
  993. case LEX_ODL_BASE_IMPORT2:
  994. {
  995. tokptr_G = "oaidl.idl";
  996. toktyp_G = STRING;
  997. yylval.yy_string = pMidlLexTable->LexInsert(tokptr_G);
  998. LexContext = LEX_NORMAL;
  999. break;
  1000. }
  1001. default:
  1002. MIDL_ASSERT(0);
  1003. }
  1004. return toktyp_G;
  1005. }