cc_macro.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /* Copyright (C) 2021 Sanne Wouda
  2. * Copyright (C) 2021 Andrius Štikonas <andrius@stikonas.eu>
  3. * Copyright (C) 2022 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  4. * This file is part of M2-Planet.
  5. *
  6. * M2-Planet is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * M2-Planet is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with M2-Planet. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "cc.h"
  20. #include "gcc_req.h"
  21. void require(int bool, char* error);
  22. int strtoint(char* a);
  23. void line_error_token(struct token_list* list);
  24. struct token_list* eat_token(struct token_list* head);
  25. struct conditional_inclusion
  26. {
  27. struct conditional_inclusion* prev;
  28. int include; /* 1 == include, 0 == skip */
  29. int previous_condition_matched; /* 1 == all subsequent conditions treated as FALSE */
  30. };
  31. struct macro_list
  32. {
  33. struct macro_list* next;
  34. char* symbol;
  35. struct token_list* expansion;
  36. };
  37. struct macro_list* macro_env;
  38. struct conditional_inclusion* conditional_inclusion_top;
  39. /* point where we are currently modifying the global_token list */
  40. struct token_list* macro_token;
  41. void init_macro_env(char* sym, char* value, char* source, int num)
  42. {
  43. struct macro_list* hold = macro_env;
  44. macro_env = calloc(1, sizeof(struct macro_list));
  45. macro_env->symbol = sym;
  46. macro_env->next = hold;
  47. macro_env->expansion = calloc(1, sizeof(struct token_list));
  48. macro_env->expansion->s = value;
  49. macro_env->expansion->filename = source;
  50. macro_env->expansion->linenumber = num;
  51. }
  52. void eat_current_token()
  53. {
  54. int update_global_token = FALSE;
  55. if (macro_token == global_token)
  56. update_global_token = TRUE;
  57. macro_token = eat_token(macro_token);
  58. if(update_global_token)
  59. global_token = macro_token;
  60. }
  61. void eat_newline_tokens()
  62. {
  63. macro_token = global_token;
  64. while(TRUE)
  65. {
  66. if(NULL == macro_token) return;
  67. if(match("\n", macro_token->s))
  68. {
  69. eat_current_token();
  70. }
  71. else
  72. {
  73. macro_token = macro_token->next;
  74. }
  75. }
  76. }
  77. /* returns the first token inserted; inserts *before* point */
  78. struct token_list* insert_tokens(struct token_list* point, struct token_list* token)
  79. {
  80. struct token_list* copy;
  81. struct token_list* first = NULL;
  82. while (NULL != token)
  83. {
  84. copy = calloc(1, sizeof(struct token_list));
  85. copy->s = token->s;
  86. copy->filename = token->filename;
  87. copy->linenumber = token->linenumber;
  88. if(NULL == first)
  89. {
  90. first = copy;
  91. }
  92. copy->next = point;
  93. if (NULL != point)
  94. {
  95. copy->prev = point->prev;
  96. if(NULL != point->prev)
  97. {
  98. point->prev->next = copy;
  99. }
  100. point->prev = copy;
  101. }
  102. token = token->next;
  103. }
  104. return first;
  105. }
  106. struct macro_list* lookup_macro(struct token_list* token)
  107. {
  108. if(NULL == token)
  109. {
  110. line_error_token(macro_token);
  111. fputs("null token received in lookup_macro\n", stderr);
  112. exit(EXIT_FAILURE);
  113. }
  114. struct macro_list* hold = macro_env;
  115. while (NULL != hold)
  116. {
  117. if (match(token->s, hold->symbol))
  118. {
  119. /* found! */
  120. return hold;
  121. }
  122. hold = hold->next;
  123. }
  124. /* not found! */
  125. return NULL;
  126. }
  127. void remove_macro(struct token_list* token)
  128. {
  129. if(NULL == token)
  130. {
  131. line_error_token(macro_token);
  132. fputs("received a null in remove_macro\n", stderr);
  133. exit(EXIT_FAILURE);
  134. }
  135. struct macro_list* hold = macro_env;
  136. struct macro_list* temp;
  137. /* Deal with the first element */
  138. if (match(token->s, hold->symbol)) {
  139. macro_env = hold->next;
  140. free(hold);
  141. return;
  142. }
  143. /* Remove element form the middle of linked list */
  144. while (NULL != hold->next)
  145. {
  146. if (match(token->s, hold->next->symbol))
  147. {
  148. temp = hold->next;
  149. hold->next = hold->next->next;
  150. free(temp);
  151. return;
  152. }
  153. hold = hold->next;
  154. }
  155. /* nothing to undefine */
  156. return;
  157. }
  158. int macro_expression();
  159. int macro_variable()
  160. {
  161. int value = 0;
  162. struct macro_list* hold = lookup_macro(macro_token);
  163. if (NULL != hold)
  164. {
  165. if(NULL == hold->expansion)
  166. {
  167. line_error_token(macro_token);
  168. fputs("hold->expansion is a null\n", stderr);
  169. exit(EXIT_FAILURE);
  170. }
  171. value = strtoint(hold->expansion->s);
  172. }
  173. eat_current_token();
  174. return value;
  175. }
  176. int macro_number()
  177. {
  178. int result = strtoint(macro_token->s);
  179. eat_current_token();
  180. return result;
  181. }
  182. int macro_primary_expr()
  183. {
  184. int defined_has_paren = FALSE;
  185. int hold;
  186. require(NULL != macro_token, "got an EOF terminated macro primary expression\n");
  187. if('-' == macro_token->s[0])
  188. {
  189. eat_current_token();
  190. return -macro_primary_expr();
  191. }
  192. else if('!' == macro_token->s[0])
  193. {
  194. eat_current_token();
  195. return !macro_primary_expr();
  196. }
  197. else if('(' == macro_token->s[0])
  198. {
  199. eat_current_token();
  200. hold = macro_expression();
  201. require(')' == macro_token->s[0], "missing ) in macro expression\n");
  202. eat_current_token();
  203. return hold;
  204. }
  205. else if(match("defined", macro_token->s))
  206. {
  207. eat_current_token();
  208. require(NULL != macro_token, "got an EOF terminated macro defined expression\n");
  209. if('(' == macro_token->s[0])
  210. {
  211. defined_has_paren = TRUE;
  212. eat_current_token();
  213. }
  214. if (NULL != lookup_macro(macro_token))
  215. {
  216. hold = TRUE;
  217. }
  218. else
  219. {
  220. hold = FALSE;
  221. }
  222. eat_current_token();
  223. if(TRUE == defined_has_paren)
  224. {
  225. if(NULL == macro_token)
  226. {
  227. line_error_token(macro_token);
  228. fputs("unterminated define ( statement\n", stderr);
  229. exit(EXIT_FAILURE);
  230. }
  231. require(')' == macro_token->s[0], "missing close parenthesis for defined()\n");
  232. eat_current_token();
  233. }
  234. return hold;
  235. }
  236. else if(in_set(macro_token->s[0], "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"))
  237. {
  238. return macro_variable();
  239. }
  240. else if(in_set(macro_token->s[0], "0123456789"))
  241. {
  242. return macro_number();
  243. }
  244. else
  245. {
  246. return 0; /* FIXME: error handling */
  247. }
  248. }
  249. int macro_additive_expr()
  250. {
  251. int lhs = macro_primary_expr();
  252. int hold;
  253. require(NULL != macro_token, "got an EOF terminated macro additive expression\n");
  254. if(match("+", macro_token->s))
  255. {
  256. eat_current_token();
  257. return lhs + macro_additive_expr();
  258. }
  259. else if(match("-", macro_token->s))
  260. {
  261. eat_current_token();
  262. return lhs - macro_additive_expr();
  263. }
  264. else if(match("*", macro_token->s))
  265. {
  266. eat_current_token();
  267. return lhs * macro_additive_expr();
  268. }
  269. else if(match("/", macro_token->s))
  270. {
  271. eat_current_token();
  272. hold = macro_additive_expr();
  273. require(0 != hold, "divide by zero not valid even in C macros\n");
  274. return lhs / hold;
  275. }
  276. else if(match("%", macro_token->s))
  277. {
  278. eat_current_token();
  279. hold = macro_additive_expr();
  280. require(0 != hold, "modulus by zero not valid even in C macros\n");
  281. return lhs % hold;
  282. }
  283. else if(match(">>", macro_token->s))
  284. {
  285. eat_current_token();
  286. return lhs >> macro_additive_expr();
  287. }
  288. else if(match("<<", macro_token->s))
  289. {
  290. eat_current_token();
  291. return lhs << macro_additive_expr();
  292. }
  293. else
  294. {
  295. return lhs;
  296. }
  297. }
  298. int macro_relational_expr()
  299. {
  300. int lhs = macro_additive_expr();
  301. if(match("<", macro_token->s))
  302. {
  303. eat_current_token();
  304. return lhs < macro_relational_expr();
  305. }
  306. else if(match("<=", macro_token->s))
  307. {
  308. eat_current_token();
  309. return lhs <= macro_relational_expr();
  310. }
  311. else if(match(">=", macro_token->s))
  312. {
  313. eat_current_token();
  314. return lhs >= macro_relational_expr();
  315. }
  316. else if(match(">", macro_token->s))
  317. {
  318. eat_current_token();
  319. return lhs > macro_relational_expr();
  320. }
  321. else if(match("==", macro_token->s))
  322. {
  323. eat_current_token();
  324. return lhs == macro_relational_expr();
  325. }
  326. else if(match("!=", macro_token->s))
  327. {
  328. eat_current_token();
  329. return lhs != macro_relational_expr();
  330. }
  331. else
  332. {
  333. return lhs;
  334. }
  335. }
  336. int macro_bitwise_expr()
  337. {
  338. int rhs;
  339. int lhs = macro_relational_expr();
  340. if(match("&", macro_token->s))
  341. {
  342. eat_current_token();
  343. return lhs & macro_bitwise_expr();
  344. }
  345. else if(match("&&", macro_token->s))
  346. {
  347. eat_current_token();
  348. rhs = macro_bitwise_expr();
  349. return lhs && rhs;
  350. }
  351. else if(match("|", macro_token->s))
  352. {
  353. eat_current_token();
  354. rhs = macro_bitwise_expr();
  355. return lhs | rhs;
  356. }
  357. else if(match("||", macro_token->s))
  358. {
  359. eat_current_token();
  360. rhs = macro_bitwise_expr();
  361. return lhs || rhs;
  362. }
  363. else if(match("^", macro_token->s))
  364. {
  365. eat_current_token();
  366. rhs = macro_bitwise_expr();
  367. return lhs ^ rhs;
  368. }
  369. else
  370. {
  371. return lhs;
  372. }
  373. }
  374. int macro_expression()
  375. {
  376. return macro_bitwise_expr();
  377. }
  378. void handle_define()
  379. {
  380. struct macro_list* hold;
  381. struct token_list* expansion_end = NULL;
  382. /* don't use #define statements from non-included blocks */
  383. int conditional_define = TRUE;
  384. if(NULL != conditional_inclusion_top)
  385. {
  386. if(FALSE == conditional_inclusion_top->include)
  387. {
  388. conditional_define = FALSE;
  389. }
  390. }
  391. eat_current_token();
  392. require(NULL != macro_token, "got an EOF terminated #define\n");
  393. require('\n' != macro_token->s[0], "unexpected newline after #define\n");
  394. /* insert new macro */
  395. hold = calloc(1, sizeof(struct macro_list));
  396. hold->symbol = macro_token->s;
  397. hold->next = macro_env;
  398. /* provided it isn't in a non-included block */
  399. if(conditional_define) macro_env = hold;
  400. /* discard the macro name */
  401. eat_current_token();
  402. while (TRUE)
  403. {
  404. require(NULL != macro_token, "got an EOF terminated #define\n");
  405. if ('\n' == macro_token->s[0])
  406. {
  407. if(NULL == expansion_end)
  408. {
  409. hold->expansion = NULL;
  410. expansion_end = macro_token;
  411. return;
  412. }
  413. expansion_end->next = NULL;
  414. return;
  415. }
  416. require(NULL != hold, "#define got something it can't handle\n");
  417. expansion_end = macro_token;
  418. /* in the first iteration, we set the first token of the expansion, if
  419. it exists */
  420. if (NULL == hold->expansion)
  421. {
  422. hold->expansion = macro_token;
  423. }
  424. /* throw away if not used */
  425. if(!conditional_define && (NULL != hold))
  426. {
  427. free(hold);
  428. hold = NULL;
  429. }
  430. eat_current_token();
  431. }
  432. }
  433. void handle_undef()
  434. {
  435. eat_current_token();
  436. remove_macro(macro_token);
  437. eat_current_token();
  438. }
  439. void handle_error(int warning_p)
  440. {
  441. /* don't use #error statements from non-included blocks */
  442. int conditional_error = TRUE;
  443. if(NULL != conditional_inclusion_top)
  444. {
  445. if(FALSE == conditional_inclusion_top->include)
  446. {
  447. conditional_error = FALSE;
  448. }
  449. }
  450. eat_current_token();
  451. /* provided it isn't in a non-included block */
  452. if(conditional_error)
  453. {
  454. line_error_token(macro_token);
  455. if(warning_p) fputs(" warning: #warning ", stderr);
  456. else fputs(" error: #error ", stderr);
  457. while (TRUE)
  458. {
  459. require(NULL != macro_token, "\nFailed to properly terminate error message with \\n\n");
  460. if ('\n' == macro_token->s[0]) break;
  461. fputs(macro_token->s, stderr);
  462. macro_token = macro_token->next;
  463. fputs(" ", stderr);
  464. }
  465. fputs("\n", stderr);
  466. if(!warning_p) exit(EXIT_FAILURE);
  467. }
  468. while (TRUE)
  469. {
  470. require(NULL != macro_token, "\nFailed to properly terminate error message with \\n\n");
  471. /* discard the error */
  472. if ('\n' == macro_token->s[0])
  473. {
  474. return;
  475. }
  476. eat_current_token();
  477. }
  478. }
  479. void eat_block();
  480. void macro_directive()
  481. {
  482. struct conditional_inclusion *t;
  483. int result;
  484. /* FIXME: whitespace is allowed between "#"" and "if" */
  485. if(match("#if", macro_token->s))
  486. {
  487. eat_current_token();
  488. /* evaluate constant integer expression */
  489. result = macro_expression();
  490. /* push conditional inclusion */
  491. t = calloc(1, sizeof(struct conditional_inclusion));
  492. t->prev = conditional_inclusion_top;
  493. conditional_inclusion_top = t;
  494. t->include = TRUE;
  495. if(FALSE == result)
  496. {
  497. t->include = FALSE;
  498. eat_block();
  499. }
  500. t->previous_condition_matched = t->include;
  501. }
  502. else if(match("#ifdef", macro_token->s))
  503. {
  504. eat_current_token();
  505. require(NULL != macro_token, "got an EOF terminated macro defined expression\n");
  506. if (NULL != lookup_macro(macro_token))
  507. {
  508. result = TRUE;
  509. eat_current_token();
  510. }
  511. else
  512. {
  513. result = FALSE;
  514. eat_block();
  515. }
  516. /* push conditional inclusion */
  517. t = calloc(1, sizeof(struct conditional_inclusion));
  518. t->prev = conditional_inclusion_top;
  519. conditional_inclusion_top = t;
  520. t->include = TRUE;
  521. if(FALSE == result)
  522. {
  523. t->include = FALSE;
  524. }
  525. t->previous_condition_matched = t->include;
  526. }
  527. else if(match("#ifndef", macro_token->s))
  528. {
  529. eat_current_token();
  530. require(NULL != macro_token, "got an EOF terminated macro defined expression\n");
  531. if (NULL != lookup_macro(macro_token))
  532. {
  533. result = FALSE;
  534. }
  535. else
  536. {
  537. result = TRUE;
  538. eat_current_token();
  539. }
  540. /* push conditional inclusion */
  541. t = calloc(1, sizeof(struct conditional_inclusion));
  542. t->prev = conditional_inclusion_top;
  543. conditional_inclusion_top = t;
  544. t->include = TRUE;
  545. if(FALSE == result)
  546. {
  547. t->include = FALSE;
  548. eat_block();
  549. }
  550. t->previous_condition_matched = t->include;
  551. }
  552. else if(match("#elif", macro_token->s))
  553. {
  554. eat_current_token();
  555. result = macro_expression();
  556. require(NULL != conditional_inclusion_top, "#elif without leading #if\n");
  557. conditional_inclusion_top->include = result && !conditional_inclusion_top->previous_condition_matched;
  558. conditional_inclusion_top->previous_condition_matched =
  559. conditional_inclusion_top->previous_condition_matched || conditional_inclusion_top->include;
  560. if(FALSE == result)
  561. {
  562. eat_block();
  563. }
  564. }
  565. else if(match("#else", macro_token->s))
  566. {
  567. eat_current_token();
  568. require(NULL != conditional_inclusion_top, "#else without leading #if\n");
  569. conditional_inclusion_top->include = !conditional_inclusion_top->previous_condition_matched;
  570. if(FALSE == conditional_inclusion_top->include)
  571. {
  572. eat_block();
  573. }
  574. }
  575. else if(match("#endif", macro_token->s))
  576. {
  577. if(NULL == conditional_inclusion_top)
  578. {
  579. line_error_token(macro_token);
  580. fputs("unexpected #endif\n", stderr);
  581. exit(EXIT_FAILURE);
  582. }
  583. eat_current_token();
  584. /* pop conditional inclusion */
  585. t = conditional_inclusion_top;
  586. conditional_inclusion_top = conditional_inclusion_top->prev;
  587. free(t);
  588. }
  589. else if(match("#define", macro_token->s))
  590. {
  591. handle_define();
  592. }
  593. else if(match("#undef", macro_token->s))
  594. {
  595. handle_undef();
  596. }
  597. else if(match("#error", macro_token->s))
  598. {
  599. handle_error(FALSE);
  600. }
  601. else if(match("#warning", macro_token->s))
  602. {
  603. handle_error(TRUE);
  604. }
  605. else
  606. {
  607. if(!match("#include", macro_token->s))
  608. {
  609. /* Put a big fat warning but see if we can just ignore */
  610. fputs(">>WARNING<<\n>>WARNING<<\n", stderr);
  611. line_error_token(macro_token);
  612. fputs("feature: ", stderr);
  613. fputs(macro_token->s, stderr);
  614. fputs(" unsupported in M2-Planet\nIgnoring line, may result in bugs\n>>WARNING<<\n>>WARNING<<\n\n", stderr);
  615. }
  616. /* unhandled macro directive; let's eat until a newline; om nom nom */
  617. while(TRUE)
  618. {
  619. if(NULL == macro_token)
  620. {
  621. return;
  622. }
  623. if('\n' == macro_token->s[0])
  624. {
  625. return;
  626. }
  627. eat_current_token();
  628. }
  629. }
  630. }
  631. void eat_until_endif()
  632. {
  633. /* This #if block is nested inside of an #if block that needs to be dropped, lose EVERYTHING */
  634. do
  635. {
  636. require(NULL != macro_token, "Unterminated #if block\n");
  637. if(match("#if", macro_token->s) || match("#ifdef", macro_token->s) || match("#ifndef", macro_token->s))
  638. {
  639. eat_current_token();
  640. eat_until_endif();
  641. }
  642. eat_current_token();
  643. require(NULL != macro_token, "Unterminated #if block\n");
  644. } while(!match("#endif", macro_token->s));
  645. }
  646. void eat_block()
  647. {
  648. /* This conditional #if block is wrong, drop everything until the #elif/#else/#endif */
  649. do
  650. {
  651. if(match("#if", macro_token->s) || match("#ifdef", macro_token->s) || match("#ifndef", macro_token->s))
  652. {
  653. eat_current_token();
  654. eat_until_endif();
  655. }
  656. eat_current_token();
  657. require(NULL != macro_token, "Unterminated #if block\n");
  658. if(match("#elif", macro_token->s)) break;
  659. if(match("#else", macro_token->s)) break;
  660. if(match("#endif", macro_token->s)) break;
  661. } while(TRUE);
  662. require(NULL != macro_token->prev, "impossible #if block\n");
  663. /* rewind the newline */
  664. if(match("\n", macro_token->prev->s)) macro_token = macro_token->prev;
  665. }
  666. struct token_list* maybe_expand(struct token_list* token)
  667. {
  668. if(NULL == token)
  669. {
  670. line_error_token(macro_token);
  671. fputs("maybe_expand passed a null token\n", stderr);
  672. exit(EXIT_FAILURE);
  673. }
  674. struct macro_list* hold = lookup_macro(token);
  675. struct token_list* hold2;
  676. if(NULL == token->next)
  677. {
  678. line_error_token(macro_token);
  679. fputs("we can't expand a null token: ", stderr);
  680. fputs(token->s, stderr);
  681. fputc('\n', stderr);
  682. exit(EXIT_FAILURE);
  683. }
  684. if (NULL == hold)
  685. {
  686. return token->next;
  687. }
  688. token = eat_token(token);
  689. if (NULL == hold->expansion)
  690. {
  691. return token->next;
  692. }
  693. hold2 = insert_tokens(token, hold->expansion);
  694. return hold2->next;
  695. }
  696. void preprocess()
  697. {
  698. int start_of_line = TRUE;
  699. macro_token = global_token;
  700. while(NULL != macro_token)
  701. {
  702. if(start_of_line && '#' == macro_token->s[0])
  703. {
  704. macro_directive();
  705. if(macro_token)
  706. {
  707. if('\n' != macro_token->s[0])
  708. {
  709. line_error_token(macro_token);
  710. fputs("newline expected at end of macro directive\n", stderr);
  711. fputs("found: '", stderr);
  712. fputs(macro_token->s, stderr);
  713. fputs("'\n", stderr);
  714. exit(EXIT_FAILURE);
  715. }
  716. }
  717. }
  718. else if('\n' == macro_token->s[0])
  719. {
  720. start_of_line = TRUE;
  721. macro_token = macro_token->next;
  722. }
  723. else
  724. {
  725. start_of_line = FALSE;
  726. if(NULL == conditional_inclusion_top)
  727. {
  728. macro_token = maybe_expand(macro_token);
  729. }
  730. else if(!conditional_inclusion_top->include)
  731. {
  732. /* rewrite the token stream to exclude the current token */
  733. eat_block();
  734. start_of_line = TRUE;
  735. }
  736. else
  737. {
  738. macro_token = maybe_expand(macro_token);
  739. }
  740. }
  741. }
  742. }