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.

911 lines
28 KiB

  1. /***********************************************************************
  2. * Microsoft (R) Windows (R) Resource Compiler
  3. *
  4. * Copyright (c) Microsoft Corporation. All rights reserved.
  5. *
  6. * File Comments:
  7. *
  8. *
  9. ***********************************************************************/
  10. #include "rc.h"
  11. #include <ddeml.h>
  12. /************************************************************************/
  13. /* Internal constants */
  14. /************************************************************************/
  15. #define GOT_IF 1 /* last nesting command was an if.. */
  16. #define GOT_ELIF 2 /* last nesting command was an if.. */
  17. #define GOT_ELSE 3 /* last nesting command was an else */
  18. #define GOT_ENDIF 4 /* found endif */
  19. #define ELSE_OR_ENDIF 5 /* skip to either #else or #endif */
  20. #define ENDIF_ONLY 6 /* skip to #endif -- #else is an error*/
  21. int ifstack[IFSTACK_SIZE];
  22. /************************************************************************/
  23. /* Local Function Prototypes */
  24. /************************************************************************/
  25. void chk_newline(const wchar_t *);
  26. void in_standard(void);
  27. int incr_ifstack(void);
  28. token_t next_control(void);
  29. unsigned long int pragma(void);
  30. int skipto(int);
  31. void skip_quoted(int);
  32. PWCHAR sysinclude(void);
  33. /************************************************************************/
  34. /* incr_ifstack - Increment the IF nesting stack */
  35. /************************************************************************/
  36. int
  37. incr_ifstack(
  38. void
  39. )
  40. {
  41. if(++Prep_ifstack >= IFSTACK_SIZE) {
  42. fatal(1052);
  43. }
  44. return(Prep_ifstack);
  45. }
  46. /************************************************************************
  47. * SYSINCLUDE - process a system include : #include <foo>
  48. *
  49. * ARGUMENTS - none
  50. *
  51. * RETURNS - none
  52. *
  53. * SIDE EFFECTS - none
  54. *
  55. * DESCRIPTION
  56. * Get the system include file name. Since the name is not a "string",
  57. * the name must be built much the same as the -E option rebuilds the text
  58. * by using the Tokstring expansion for tokens with no expansion already
  59. *
  60. * NOTE : IS THIS ANSI? note we're just reading chars, and not expanding
  61. * any macros. NO, it's not. it must expand the macros.
  62. * TODO : have it call yylex() unless and until it finds a '>' or a newline.
  63. * (probably have to set On_pound_line to have yylex return the newline.)
  64. *
  65. * AUTHOR
  66. * Ralph Ryan Sep. 1982
  67. *
  68. * MODIFICATIONS - none
  69. *
  70. *
  71. ************************************************************************/
  72. PWCHAR
  73. sysinclude(
  74. void
  75. )
  76. {
  77. REG int c;
  78. REG WCHAR *p_fname;
  79. p_fname = Reuse_W;
  80. c = skip_cwhite();
  81. if( c == L'\n' ) {
  82. UNGETCH();
  83. error(2012); /* missing name after '<' */
  84. return(NULL);
  85. }
  86. while( c != L'>' && c != L'\n' ) {
  87. *p_fname++ = (WCHAR)c; /* check for buffer overflow ??? */
  88. c = get_non_eof();
  89. }
  90. if( c == L'\n' ) {
  91. UNGETCH();
  92. error(2013); /* missing '>' */
  93. return(NULL);
  94. }
  95. if(p_fname != Reuse_W) {
  96. p_fname--;
  97. while((p_fname >= Reuse_W) && iswspace(*p_fname)) {
  98. p_fname--;
  99. }
  100. p_fname++;
  101. }
  102. *p_fname = L'\0';
  103. return(Reuse_W);
  104. }
  105. /************************************************************************
  106. ** preprocess : the scanner found a # which was the first non-white char
  107. ** on a line.
  108. ************************************************************************/
  109. void
  110. preprocess(
  111. void
  112. )
  113. {
  114. REG WCHAR c;
  115. long eval;
  116. int condition;
  117. token_t deftok;
  118. hln_t identifier;
  119. unsigned long int cp;
  120. if(Macro_depth != 0) { /* # only when not in a macro */
  121. return;
  122. }
  123. switch(CHARMAP(c = skip_cwhite())) {
  124. case LX_ID:
  125. getid(c);
  126. HLN_NAME(identifier) = Reuse_W;
  127. HLN_LENGTH(identifier) = (UINT)Reuse_W_length;
  128. HLN_HASH(identifier) = Reuse_W_hash;
  129. break;
  130. case LX_NL:
  131. UNGETCH();
  132. return;
  133. default:
  134. error(2019, c); /* unknown preprocessor command */
  135. skip_cnew(); /* finds a newline */
  136. return;
  137. }
  138. On_pound_line = TRUE;
  139. start:
  140. switch(deftok = is_pkeyword(HLN_IDENTP_NAME(&identifier))) {
  141. int old_prep;
  142. case P0_DEFINE :
  143. define();
  144. break;
  145. case P0_LINE :
  146. old_prep = Prep;
  147. Prep = FALSE;
  148. yylex();
  149. if(Basic_token != L_CINTEGER) { /* #line needs line number */
  150. error(2005, TS_STR(Basic_token)); /* unknown preprocessor command */
  151. Prep = old_prep;
  152. skip_cnew();
  153. On_pound_line = FALSE;
  154. return;
  155. }
  156. /*
  157. ** -1 because there's a newline at the end of this line
  158. ** which will be counted later when we find it.
  159. ** the #line says the next line is the number we've given
  160. */
  161. Linenumber = TR_LVALUE(yylval.yy_tree) - 1;
  162. yylex();
  163. Prep = old_prep;
  164. switch(Basic_token) {
  165. case L_STRING:
  166. if( wcscmp(Filename, yylval.yy_string.str_ptr) != 0) {
  167. wcsncpy(Filename,
  168. yylval.yy_string.str_ptr,
  169. sizeof(Filebuff) / sizeof(WCHAR)
  170. );
  171. }
  172. case L_NOTOKEN:
  173. break;
  174. default:
  175. error(2130, TS_STR(Basic_token)); /* #line needs a string */
  176. skip_cnew();
  177. On_pound_line = FALSE;
  178. return;
  179. }
  180. emit_line();
  181. chk_newline(L"#line");
  182. break;
  183. case P0_INCLUDE :
  184. old_prep = Prep;
  185. Prep = FALSE;
  186. InInclude = TRUE;
  187. yylex();
  188. InInclude = FALSE;
  189. Prep = old_prep;
  190. switch(Basic_token) {
  191. case L_LT:
  192. if((sysinclude()) == NULL) {
  193. skip_cnew();
  194. On_pound_line = FALSE;
  195. return;
  196. }
  197. yylval.yy_string.str_ptr = Reuse_W;
  198. break;
  199. case L_STRING:
  200. break;
  201. default:
  202. error(2006, TS_STR(Basic_token)); /* needs file name */
  203. skip_cnew();
  204. On_pound_line = FALSE;
  205. return;
  206. break;
  207. }
  208. wcscpy(Reuse_Include, yylval.yy_string.str_ptr);
  209. chk_newline(L"#include");
  210. if( wcschr(Path_chars, *yylval.yy_string.str_ptr) ||
  211. (wcschr(Path_chars, L':') && (yylval.yy_string.str_ptr[1] == L':'))) {
  212. /*
  213. ** we have a string which either has a 1st char which is a path
  214. ** delimiter or, if ':' is a path delimiter (DOS), which has
  215. ** "<drive letter>:" as the first two characters. Such names
  216. ** specify a fully qualified pathnames. Do not append the search
  217. ** list, just look it up.
  218. */
  219. if( ! newinput(yylval.yy_string.str_ptr, MAY_OPEN)) {
  220. fatal(1015, Reuse_W); /* can't find include file */
  221. }
  222. }
  223. else if( (Basic_token != L_STRING) || (! nested_include())) {
  224. in_standard();
  225. }
  226. break;
  227. case P0_IFDEF :
  228. case P0_IFNDEF :
  229. if(CHARMAP(c = skip_cwhite()) != LX_ID) {
  230. fatal(1016);
  231. }
  232. getid(c);
  233. eval = (get_defined()) ? TRUE : FALSE;
  234. chk_newline((deftok == P0_IFDEF) ? L"#ifdef" : L"#ifndef");
  235. if(deftok == P0_IFNDEF) {
  236. eval = ( ! eval );
  237. }
  238. if( eval || ((condition = skipto(ELSE_OR_ENDIF)) == GOT_ELSE) ) {
  239. /*
  240. ** expression is TRUE or when we skipped the false part
  241. ** we found a #else that will be expanded.
  242. */
  243. ifstack[incr_ifstack()] = GOT_IF;
  244. } else if(condition == GOT_ELIF) {
  245. /* hash is wrong, but it won't be used */
  246. HLN_NAME(identifier) = L"if"; /* sleazy HACK */
  247. goto start;
  248. }
  249. break;
  250. case P0_IF :
  251. old_prep = Prep;
  252. Prep = FALSE;
  253. InIf = TRUE;
  254. eval = do_constexpr();
  255. InIf = FALSE;
  256. Prep = old_prep;
  257. chk_newline(PPifel_str /* "#if/#elif" */);
  258. if((eval) || ((condition = skipto(ELSE_OR_ENDIF)) == GOT_ELSE) ) {
  259. /*
  260. ** expression is TRUE or when we skipped the false part
  261. ** we found a #else that will be expanded.
  262. */
  263. ifstack[incr_ifstack()] = GOT_IF;
  264. if(Eflag && !eval)
  265. emit_line();
  266. } else {
  267. /*
  268. ** here the #if's expression was false, so we skipped until we found
  269. ** an #elif. we'll restart and fake that we're processing a #if
  270. */
  271. if(Eflag)
  272. emit_line();
  273. if(condition == GOT_ELIF) {
  274. /* hash is wrong, but it won't be needed */
  275. HLN_NAME(identifier) = L"if"; /* sleazy HACK */
  276. goto start;
  277. }
  278. }
  279. break;
  280. case P0_ELIF :
  281. /*
  282. ** here, we have found a #elif. first check to make sure that
  283. ** this is not an occurrance of a #elif with no preceding #if.
  284. ** (if Prep_ifstack < 0) then there is no preceding #if.
  285. */
  286. if(Prep_ifstack-- < 0) {
  287. fatal(1018);
  288. }
  289. /*
  290. ** now, the preceding #if/#elif was true, and we've
  291. ** just found the next #elif. we want to skip all #else's
  292. ** and #elif's from here until we find the enclosing #endif
  293. */
  294. while(skipto(ELSE_OR_ENDIF) != GOT_ENDIF) {
  295. ;
  296. }
  297. if(Eflag)
  298. emit_line();
  299. break;
  300. case P0_ELSE : /* the preceding #if/#elif was true */
  301. if((Prep_ifstack < 0) || (ifstack[Prep_ifstack--] != GOT_IF)) {
  302. fatal(1019); /* make sure there was one */
  303. }
  304. chk_newline(PPelse_str /* "#else" */);
  305. skipto(ENDIF_ONLY);
  306. if(Eflag)
  307. emit_line();
  308. break;
  309. case P0_ENDIF : /* only way here is a lonely #endif */
  310. if(Prep_ifstack-- < 0) {
  311. fatal(1020);
  312. }
  313. if(Eflag)
  314. emit_line();
  315. chk_newline(PPendif_str /* "#endif" */);
  316. break;
  317. case P0_PRAGMA :
  318. cp = pragma();
  319. if (cp != 0) {
  320. if (cp == CP_WINUNICODE) {
  321. if (fWarnInvalidCodePage) {
  322. warning(4213);
  323. } else {
  324. fatal(4213);
  325. }
  326. break;
  327. }
  328. if (!IsValidCodePage(cp)) {
  329. if (fWarnInvalidCodePage) {
  330. warning(4214);
  331. } else {
  332. fatal(4214);
  333. }
  334. break;
  335. }
  336. if (cp != uiCodePage) {
  337. if (!io_restart(cp)) {
  338. fatal(1121);
  339. }
  340. uiCodePage = cp; // can't be set until now!
  341. }
  342. }
  343. break;
  344. case P0_UNDEF :
  345. if(CHARMAP(c = skip_cwhite()) != LX_ID) {
  346. warning(4006); /* missing identifier on #undef */
  347. } else {
  348. getid(c);
  349. undefine();
  350. }
  351. chk_newline(L"#undef");
  352. break;
  353. case P0_ERROR:
  354. {
  355. PWCHAR p;
  356. p = Reuse_W;
  357. while((c = get_non_eof()) != LX_EOS) {
  358. if(c == L'\n') {
  359. UNGETCH();
  360. break;
  361. }
  362. *p++ = c;
  363. }
  364. *p = L'\0';
  365. }
  366. error(2188, Reuse_W);
  367. chk_newline(L"#error");
  368. break;
  369. case P0_IDENT:
  370. old_prep = Prep ;
  371. Prep = FALSE;
  372. yylex();
  373. Prep = old_prep;
  374. if(Basic_token != L_STRING) {
  375. warning(4079, TS_STR(Basic_token));
  376. }
  377. chk_newline(L"#error");
  378. break;
  379. case P0_NOTOKEN:
  380. fatal(1021, HLN_IDENTP_NAME(&identifier));
  381. break;
  382. }
  383. On_pound_line = FALSE;
  384. }
  385. /************************************************************************
  386. * SKIPTO - skip code until the end of an undefined block is reached.
  387. *
  388. * ARGUMENTS
  389. * short key - skip to an ELSE or ENDIF or just an ENDIF
  390. *
  391. * RETURNS - none
  392. *
  393. * SIDE EFFECTS
  394. * - throws away input
  395. *
  396. * DESCRIPTION
  397. * The preprocessor is skipping code between failed ifdef, etc. and
  398. * the corresponding ELSE or ENDIF (when key == ELSE_OR_ENDIF).
  399. * Or it is skipping code between a failed ELSE and the ENDIF (when
  400. * key == ENDIF_ONLY).
  401. *
  402. * AUTHOR - Ralph Ryan, Sept. 16, 1982
  403. *
  404. * MODIFICATIONS - none
  405. *
  406. ************************************************************************/
  407. int
  408. skipto(
  409. int key
  410. )
  411. {
  412. REG int level;
  413. REG token_t tok;
  414. level = 0;
  415. tok = P0_NOTOKEN;
  416. for(;;) {
  417. /* make sure that IF [ELSE] ENDIF s are balanced */
  418. switch(next_control()) {
  419. case P0_IFDEF:
  420. case P0_IFNDEF:
  421. case P0_IF:
  422. level++;
  423. break;
  424. case P0_ELSE:
  425. tok = P0_ELSE;
  426. /*
  427. ** FALLTHROUGH
  428. */
  429. case P0_ELIF:
  430. /*
  431. ** we found a #else or a #elif. these have their only chance
  432. ** at being valid if they're at level 0.
  433. ** if we're at any other level,
  434. ** then this else/elif belongs to some other #if and we skip them.
  435. ** if we were looking for an endif, the we have an error.
  436. */
  437. if(level != 0) {
  438. tok = P0_NOTOKEN;
  439. break;
  440. }
  441. if(key == ENDIF_ONLY) {
  442. fatal(1022); /* expected #endif */
  443. } else if(tok == P0_ELSE) {
  444. chk_newline(PPelse_str /* "#else" */);
  445. return(GOT_ELSE);
  446. } else {
  447. return(GOT_ELIF);
  448. }
  449. break;
  450. case P0_ENDIF:
  451. if(level == 0) {
  452. chk_newline(PPendif_str /* "#endif" */);
  453. return(GOT_ENDIF);
  454. } else {
  455. level--;
  456. }
  457. break;
  458. }
  459. }
  460. }
  461. /*************************************************************************
  462. ** in_standard : search for the given file name in the directory list.
  463. ** Input : ptr to include file name.
  464. ** Output : fatal error if not found.
  465. *************************************************************************/
  466. void
  467. in_standard(
  468. void
  469. )
  470. {
  471. int i;
  472. int stop;
  473. WCHAR *p_dir;
  474. WCHAR *p_file;
  475. WCHAR *p_tmp;
  476. stop = Includes.li_top;
  477. for(i = MAXLIST-1; i >= stop; i--) {
  478. p_file = yylval.yy_string.str_ptr;
  479. if( ((p_dir = Includes.li_defns[i])!=0) &&(wcscmp(p_dir, L"./") != 0) ) {
  480. /*
  481. ** there is a directory to prepend and it's not './'
  482. */
  483. p_tmp = Exp_ptr;
  484. while((*p_tmp++ = *p_dir++) != 0)
  485. ;
  486. /*
  487. ** above loop increments p_tmp past null.
  488. ** this replaces that null with a '/' if needed. Not needed if the
  489. ** last character of the directory spec is a path delimiter.
  490. ** we then point to the char after the '/'
  491. */
  492. if(wcschr(Path_chars, p_dir[-2]) == 0) {
  493. p_tmp[-1] = L'/';
  494. } else {
  495. --p_tmp;
  496. }
  497. while((*p_tmp++ = *p_file++) != 0)
  498. ;
  499. p_file = Exp_ptr;
  500. }
  501. if(newinput(p_file,MAY_OPEN)) { /* this is the non-error way out */
  502. return;
  503. }
  504. }
  505. fatal(1015, yylval.yy_string.str_ptr); /* can't find include file */
  506. }
  507. /*************************************************************************
  508. ** chk_newline : check for whitespace only before a newline.
  509. ** eat the newline.
  510. *************************************************************************/
  511. void chk_newline(const wchar_t *cmd)
  512. {
  513. if(skip_cwhite() != L'\n') {
  514. warning(4067, cmd); /* cmd expected newline */
  515. skip_cnew();
  516. } else {
  517. UNGETCH();
  518. }
  519. }
  520. /*************************************************************************
  521. ** skip_quoted : skips chars until it finds a char which matches its arg.
  522. *************************************************************************/
  523. void
  524. skip_quoted(
  525. int sc
  526. )
  527. {
  528. REG WCHAR c;
  529. for(;;) {
  530. switch(CHARMAP(c = GETCH())) {
  531. case LX_NL:
  532. warning(4093);
  533. UNGETCH();
  534. return;
  535. break;
  536. case LX_DQUOTE:
  537. case LX_SQUOTE:
  538. if(c == (WCHAR)sc)
  539. return;
  540. break;
  541. case LX_EOS:
  542. if(handle_eos() == BACKSLASH_EOS) {
  543. SKIPCH(); /* might be /" !! */
  544. }
  545. break;
  546. case LX_LEADBYTE:
  547. get_non_eof();
  548. break;
  549. }
  550. }
  551. }
  552. /*************************************************************************
  553. ** next_control : find a newline. find a pound sign as the first non-white.
  554. ** find an id start char, build an id look it up and return the token.
  555. ** this knows about strings/char const and such.
  556. *************************************************************************/
  557. token_t
  558. next_control(
  559. void
  560. )
  561. {
  562. REG WCHAR c;
  563. for(;;) {
  564. c = skip_cwhite();
  565. first_switch:
  566. switch(CHARMAP(c)) {
  567. case LX_NL:
  568. Linenumber++;
  569. // must manually write '\r' with '\n' when writing 16-bit strings
  570. if(Prep) {
  571. myfwrite(L"\r\n", 2 * sizeof(WCHAR), 1, OUTPUTFILE);
  572. }
  573. if((c = skip_cwhite()) == L'#') {
  574. if(LX_IS_IDENT(c = skip_cwhite())) {
  575. /*
  576. ** this is the only way to return to the caller.
  577. */
  578. getid(c);
  579. return(is_pkeyword(Reuse_W)); /* if its predefined */
  580. }
  581. }
  582. goto first_switch;
  583. break;
  584. case LX_DQUOTE:
  585. case LX_SQUOTE:
  586. skip_quoted(c);
  587. break;
  588. case LX_EOS:
  589. if(handle_eos() == BACKSLASH_EOS) {
  590. SKIPCH(); /* might be \" !! */
  591. }
  592. break;
  593. }
  594. }
  595. }
  596. /*************************************************************************
  597. ** do_defined : does the work for the defined(id)
  598. ** should parens be counted, or just be used as delimiters (ie the
  599. ** first open paren matches the first close paren)? If this is ever
  600. ** an issue, it really means that there is not a legal identifier
  601. ** between the parens, causing an error anyway, but consider:
  602. ** #if (defined(2*(x-1))) || 1
  603. ** #endif
  604. ** It is friendlier to allow compilation to continue
  605. *************************************************************************/
  606. int
  607. do_defined(
  608. PWCHAR p_tmp
  609. )
  610. {
  611. REG UINT c;
  612. REG int value=0;
  613. int paren_level = 0;
  614. /*
  615. ** we want to allow:
  616. ** #define FOO defined
  617. ** #define BAR(a,b) a FOO | b
  618. ** #define SNAFOO 0
  619. ** #if FOO BAR
  620. ** print("BAR is defined");
  621. ** #endif
  622. ** #if BAR(defined, SNAFOO)
  623. ** print("FOO is defined");
  624. ** #endif
  625. */
  626. if(wcscmp(p_tmp,L"defined") != 0) {
  627. return(0);
  628. }
  629. if((!can_get_non_white()) && (Tiny_lexer_nesting == 0)) {
  630. /* NL encountered */
  631. return(value);
  632. }
  633. if((c = CHECKCH())== L'(') { /* assumes no other CHARMAP form of OPAREN */
  634. *Exp_ptr++ = (WCHAR)c;
  635. SKIPCH();
  636. paren_level++;
  637. if((!can_get_non_white()) && (Tiny_lexer_nesting == 0)) {
  638. /* NL encountered */
  639. return(value);
  640. }
  641. }
  642. if(Tiny_lexer_nesting>0) {
  643. if((CHARMAP((WCHAR)(c=CHECKCH()))==LX_MACFORMAL) || (CHARMAP((WCHAR)c)==LX_ID)) {
  644. SKIPCH();
  645. tl_getid((UCHAR)c);
  646. }
  647. } else {
  648. if(LX_IS_IDENT(((WCHAR)(c = CHECKCH())))) {
  649. SKIPCH();
  650. if(Macro_depth >0) {
  651. lex_getid((WCHAR)c);
  652. } else {
  653. getid((WCHAR)c);
  654. }
  655. value = (get_defined()) ? TRUE : FALSE;
  656. } else {
  657. if(paren_level==0) {
  658. error(2003);
  659. } else {
  660. error(2004);
  661. }
  662. }
  663. }
  664. if((CHARMAP(((WCHAR)(c = CHECKCH()))) == LX_WHITE) || (CHARMAP((WCHAR)c) == LX_EOS)) {
  665. if( ! can_get_non_white()) {
  666. return(value);
  667. }
  668. }
  669. if(paren_level) {
  670. if((CHARMAP(((WCHAR)(c = CHECKCH()))) == LX_CPAREN)) {
  671. SKIPCH();
  672. paren_level--;
  673. *Exp_ptr++ = (WCHAR)c;
  674. }
  675. }
  676. if((paren_level > 0) && (Tiny_lexer_nesting == 0)) {
  677. warning(4004);
  678. }
  679. return(value);
  680. }
  681. /*************************************************************************
  682. * NEXTIS - The lexical interface for #if expression parsing.
  683. * If the next token does not match what is wanted, return FALSE.
  684. * otherwise Set Currtok to L_NOTOKEN to force scanning on the next call.
  685. * Return TRUE.
  686. * will leave a newline as next char if it finds one.
  687. *************************************************************************/
  688. int
  689. nextis(
  690. register token_t tok
  691. )
  692. {
  693. if(Currtok != L_NOTOKEN) {
  694. if(tok == Currtok) {
  695. Currtok = L_NOTOKEN; /* use up the token */
  696. return(TRUE);
  697. } else {
  698. return(FALSE);
  699. }
  700. }
  701. switch(yylex()) { /* acquire a new token */
  702. case 0:
  703. break;
  704. case L_CONSTANT:
  705. if( ! IS_INTEGRAL(TR_BTYPE(yylval.yy_tree))) {
  706. fatal(1017);
  707. } else {
  708. Currval = TR_LVALUE(yylval.yy_tree);
  709. }
  710. if(tok == L_CINTEGER) {
  711. return(TRUE);
  712. }
  713. Currtok = L_CINTEGER;
  714. break;
  715. case L_IDENT:
  716. Currval = do_defined(HLN_IDENTP_NAME(&yylval.yy_ident));
  717. if(tok == L_CINTEGER) {
  718. return(TRUE);
  719. }
  720. Currtok = L_CINTEGER;
  721. break;
  722. default:
  723. if(tok == Basic_token) {
  724. return(TRUE);
  725. }
  726. Currtok = Basic_token;
  727. break;
  728. }
  729. return(FALSE);
  730. }
  731. /************************************************************************
  732. ** skip_cnew : reads up to and including the next newline.
  733. ************************************************************************/
  734. void
  735. skip_cnew(
  736. void
  737. )
  738. {
  739. for(;;) {
  740. switch(CHARMAP(GETCH())) {
  741. case LX_NL:
  742. UNGETCH();
  743. return;
  744. case LX_SLASH:
  745. skip_comment();
  746. break;
  747. case LX_EOS:
  748. handle_eos();
  749. break;
  750. }
  751. }
  752. }
  753. /************************************************************************
  754. ** skip_NLonly : reads up to the next newline, disallowing comments
  755. ************************************************************************/
  756. void
  757. skip_NLonly(
  758. void
  759. )
  760. {
  761. for(;;) {
  762. switch(CHARMAP(GETCH())) {
  763. case LX_NL:
  764. UNGETCH();
  765. return;
  766. case LX_EOS:
  767. handle_eos();
  768. break;
  769. }
  770. }
  771. }
  772. /************************************************************************
  773. ** pragma : handle processing the pragma directive
  774. ** called by preprocess() after we have seen the #pragma
  775. ** and are ready to handle the keyword which follows.
  776. ************************************************************************/
  777. unsigned long
  778. pragma(
  779. void
  780. )
  781. {
  782. WCHAR c;
  783. unsigned long int cp=0;
  784. c = skip_cwhite();
  785. if (c != L'\n') {
  786. getid(c);
  787. _wcsupr(Reuse_W);
  788. if (wcscmp(L"CODE_PAGE", Reuse_W) == 0) {
  789. if ((c = skip_cwhite()) == L'(') {
  790. c = skip_cwhite(); // peek token
  791. if (iswdigit(c)) {
  792. token_t tok;
  793. int old_prep = Prep;
  794. Prep = FALSE;
  795. tok = getnum(c);
  796. Prep = old_prep;
  797. switch(tok) {
  798. default:
  799. case L_CFLOAT:
  800. case L_CDOUBLE:
  801. case L_CLDOUBLE:
  802. case L_FLOAT:
  803. case L_DOUBLE:
  804. break;
  805. case L_CINTEGER:
  806. case L_LONGINT:
  807. case L_CUNSIGNED:
  808. case L_LONGUNSIGNED:
  809. case L_SHORT:
  810. case L_LONG:
  811. case L_SIGNED:
  812. case L_UNSIGNED:
  813. cp = TR_LVALUE(yylval.yy_tree);
  814. break;
  815. }
  816. }
  817. if (cp == 0) {
  818. getid(c);
  819. _wcsupr(Reuse_W);
  820. if (wcscmp(L"DEFAULT", Reuse_W) == 0) {
  821. cp = uiDefaultCodePage;
  822. } else {
  823. error(4212, Reuse_W);
  824. }
  825. }
  826. if ((c = skip_cwhite()) != L')') {
  827. UNGETCH();
  828. error(4211);
  829. }
  830. } else {
  831. UNGETCH();
  832. error(4210);
  833. }
  834. swprintf(Reuse_W, L"#pragma code_page %d\r\n", cp);
  835. myfwrite(Reuse_W, wcslen(Reuse_W) * sizeof(WCHAR), 1, OUTPUTFILE);
  836. }
  837. }
  838. // Skip #pragma statements
  839. while((c = get_non_eof()) != L'\n');
  840. UNGETCH();
  841. return cp;
  842. }