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.

851 lines
21 KiB

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