c_preproc.g 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. # This file is part of asmc, a bootstrapping OS with minimal seed
  2. # Copyright (C) 2018 Giovanni Mascellani <gio@debian.org>
  3. # https://gitlab.com/giomasce/asmc
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. $fd_in
  15. $read_char
  16. $char_given_back
  17. const SUBST_IS_FUNCTION 0 # bool
  18. const SUBST_PARAMETERS 4 # vector of char*
  19. const SUBST_REPLACEMENT 8 # vector of char*
  20. const SIZEOF_SUBST 12
  21. fun subst_init 0 {
  22. $ptr
  23. @ptr SIZEOF_SUBST malloc = ;
  24. ptr SUBST_IS_FUNCTION take_addr 0 = ;
  25. ptr SUBST_PARAMETERS take_addr 4 vector_init = ;
  26. ptr SUBST_REPLACEMENT take_addr 4 vector_init = ;
  27. ptr ret ;
  28. }
  29. fun subst_destroy 1 {
  30. $ptr
  31. @ptr 0 param = ;
  32. ptr SUBST_PARAMETERS take free_vect_of_ptrs ;
  33. ptr SUBST_REPLACEMENT take free_vect_of_ptrs ;
  34. ptr free ;
  35. }
  36. const PPCTX_DEFINES 0
  37. const SIZEOF_PPCTX 4
  38. fun ppctx_init 0 {
  39. $ptr
  40. @ptr SIZEOF_PPCTX malloc = ;
  41. ptr PPCTX_DEFINES take_addr map_init = ;
  42. ptr ret ;
  43. }
  44. fun ppctx_destroy 1 {
  45. $ptr
  46. @ptr 0 param = ;
  47. $defs
  48. @defs ptr PPCTX_DEFINES take = ;
  49. $i
  50. @i 0 = ;
  51. while i defs map_size < {
  52. if defs i map_has_idx {
  53. defs i map_at_idx subst_destroy ;
  54. }
  55. @i i 1 + = ;
  56. }
  57. defs map_destroy ;
  58. ptr free ;
  59. }
  60. fun give_back_char 0 {
  61. @char_given_back 1 = ;
  62. }
  63. fun get_char 0 {
  64. if char_given_back {
  65. @char_given_back 0 = ;
  66. } else {
  67. @read_char fd_in platform_read_char = ;
  68. }
  69. read_char ret
  70. }
  71. fun is_valid_2_char_token 1 {
  72. $first
  73. $second
  74. @first 0 param **c = ;
  75. @second 0 param 1 + **c = ;
  76. if first '+' == second '+' == && { 1 ret ; }
  77. if first '-' == second '-' == && { 1 ret ; }
  78. if first '=' == second '=' == && { 1 ret ; }
  79. if first '!' == second '=' == && { 1 ret ; }
  80. if first '<' == second '=' == && { 1 ret ; }
  81. if first '>' == second '=' == && { 1 ret ; }
  82. if first '<' == second '<' == && { 1 ret ; }
  83. if first '>' == second '>' == && { 1 ret ; }
  84. if first '&' == second '&' == && { 1 ret ; }
  85. if first '|' == second '|' == && { 1 ret ; }
  86. 0 ret ;
  87. }
  88. fun is_c_comment 1 {
  89. $first
  90. $second
  91. @first 0 param **c = ;
  92. @second 0 param 1 + **c = ;
  93. if first '/' == second '*' == && { 1 ret ; }
  94. 0 ret ;
  95. }
  96. fun is_cpp_comment 1 {
  97. $first
  98. $second
  99. @first 0 param **c = ;
  100. @second 0 param 1 + **c = ;
  101. if first '/' == second '/' == && { 1 ret ; }
  102. 0 ret ;
  103. }
  104. fun is_line_escape 1 {
  105. $first
  106. $second
  107. @first 0 param **c = ;
  108. @second 0 param 1 + **c = ;
  109. if first '\\' == second '\n' == && { 1 ret ; }
  110. 0 ret ;
  111. }
  112. fun get_token 0 {
  113. $token_buf
  114. $token_buf_len
  115. @token_buf_len 32 = ;
  116. @token_buf token_buf_len malloc = ;
  117. $state
  118. @state 0 = ;
  119. $token_type
  120. $token_len
  121. @token_len 0 = ;
  122. $cont
  123. @cont 1 = ;
  124. while cont {
  125. $c
  126. @c get_char = ;
  127. @cont c 0xffffffff != = ;
  128. if cont {
  129. $save_char
  130. @save_char 0 = ;
  131. $type
  132. @type c get_char_type = ;
  133. $enter_state
  134. @enter_state state = ;
  135. # Normal code
  136. if enter_state 0 == {
  137. @save_char 1 = ;
  138. }
  139. # C++ style comment
  140. if enter_state 1 == {
  141. if c '\n' == {
  142. token_buf ' ' =c ;
  143. @token_len 1 = ;
  144. @state 0 = ;
  145. @cont 0 = ;
  146. give_back_char ;
  147. }
  148. }
  149. # C style comment
  150. if enter_state 2 == {
  151. if c '*' == {
  152. @state 3 = ;
  153. }
  154. }
  155. # C style comment after star
  156. if enter_state 3 == {
  157. if c '/' == {
  158. token_buf ' ' =c ;
  159. @token_len 1 = ;
  160. @state 0 = ;
  161. @cont 0 = ;
  162. }
  163. if c '*' != {
  164. @state 2 = ;
  165. }
  166. }
  167. # String
  168. if enter_state 4 == {
  169. @save_char 1 = ;
  170. if c '\\' == {
  171. @state 5 = ;
  172. }
  173. if c '"' == {
  174. @state 0 = ;
  175. @cont 0 = ;
  176. }
  177. }
  178. # String after backslash
  179. if enter_state 5 == {
  180. @save_char 1 = ;
  181. @state 4 = ;
  182. }
  183. # Character
  184. if enter_state 6 == {
  185. @save_char 1 = ;
  186. if c '\\' == {
  187. @state 7 = ;
  188. }
  189. if c '\'' == {
  190. @state 0 = ;
  191. @cont 0 = ;
  192. }
  193. }
  194. # Character after backslash
  195. if enter_state 7 == {
  196. @save_char 1 = ;
  197. @state 6 = ;
  198. }
  199. token_buf token_len + c =c ;
  200. if save_char {
  201. if token_len 0 == {
  202. @token_len token_len 1 + = ;
  203. @token_type type = ;
  204. if c '"' == {
  205. @state 4 = ;
  206. @token_type 0 = ;
  207. }
  208. if c '\'' == {
  209. @state 6 = ;
  210. @token_type 0 = ;
  211. }
  212. if c '\n' == {
  213. @cont 0 = ;
  214. }
  215. } else {
  216. if token_buf is_line_escape {
  217. @token_len 0 = ;
  218. } else {
  219. if token_type type == token_type 0 == || {
  220. @token_len token_len 1 + = ;
  221. if token_type 4 == {
  222. $done
  223. @done 0 = ;
  224. if token_buf is_c_comment {
  225. @state 2 = ;
  226. @done 1 = ;
  227. }
  228. if token_buf is_cpp_comment {
  229. @state 1 = ;
  230. @done 1 = ;
  231. }
  232. if token_buf is_valid_2_char_token {
  233. @token_len token_len 1 + = ;
  234. @cont 0 = ;
  235. @done 1 = ;
  236. }
  237. if done ! {
  238. give_back_char ;
  239. @token_len 1 = ;
  240. @cont 0 = ;
  241. }
  242. }
  243. } else {
  244. give_back_char ;
  245. @cont 0 = ;
  246. }
  247. }
  248. }
  249. }
  250. if token_len 1 + token_buf_len >= {
  251. @token_buf_len token_buf_len 2 * = ;
  252. @token_buf token_buf_len token_buf realloc = ;
  253. }
  254. }
  255. }
  256. if token_type 2 == {
  257. token_buf ' ' =c ;
  258. @token_len 1 = ;
  259. }
  260. token_buf token_len + 0 =c ;
  261. token_buf ret ;
  262. }
  263. fun tokenize_file 1 {
  264. @fd_in 0 param platform_open_file = ;
  265. $tok
  266. $cont
  267. @cont 1 = ;
  268. $token_vect
  269. @token_vect 4 vector_init = ;
  270. while cont {
  271. @tok get_token = ;
  272. @cont tok "" strcmp 0 != = ;
  273. if cont {
  274. token_vect tok vector_push_back ;
  275. } else {
  276. tok free ;
  277. }
  278. }
  279. token_vect ret ;
  280. }
  281. fun discard_until_newline 2 {
  282. $tokens
  283. $iptr
  284. @iptr 0 param = ;
  285. @tokens 1 param = ;
  286. $cont
  287. @cont 1 = ;
  288. while cont {
  289. @cont tokens iptr ** vector_at "\n" strcmp 0 != = ;
  290. if cont {
  291. iptr iptr ** 1 + = ;
  292. iptr ** tokens vector_size < "discard_white_token: stream end was found" assert_msg ;
  293. }
  294. }
  295. }
  296. fun discard_white_tokens 2 {
  297. $tokens
  298. $iptr
  299. @iptr 0 param = ;
  300. @tokens 1 param = ;
  301. $cont
  302. @cont 1 = ;
  303. while cont {
  304. iptr iptr ** 1 + = ;
  305. iptr ** tokens vector_size < "discard_white_token: stream end was found" assert_msg ;
  306. @cont tokens iptr ** vector_at " " strcmp 0 == = ;
  307. }
  308. }
  309. fun process_token 4 {
  310. $ctx
  311. $tokens
  312. $intoks
  313. $iptr
  314. @iptr 0 param = ;
  315. @intoks 1 param = ;
  316. @tokens 2 param = ;
  317. @ctx 3 param = ;
  318. $tok
  319. @tok intoks iptr ** vector_at = ;
  320. # Search the token in the context defines
  321. $changed
  322. @changed 0 = ;
  323. if ctx PPCTX_DEFINES take tok map_has {
  324. @changed 1 = ;
  325. #"Expanding: " 1 platform_log ;
  326. #tok 1 platform_log ;
  327. #"\n" 1 platform_log ;
  328. $subst
  329. @subst ctx PPCTX_DEFINES take tok map_at = ;
  330. $repl
  331. @repl subst SUBST_REPLACEMENT take = ;
  332. if subst SUBST_IS_FUNCTION take {
  333. # TODO
  334. 0 "process_token: not implemented yet" assert_msg ;
  335. } else {
  336. $j
  337. @j 0 = ;
  338. while j repl vector_size < {
  339. tokens repl j vector_at strdup vector_push_back ;
  340. @j j 1 + = ;
  341. }
  342. }
  343. } else {
  344. tokens tok strdup vector_push_back ;
  345. }
  346. changed ret ;
  347. }
  348. fun preproc_replace_int 3 {
  349. $ctx
  350. $intoks
  351. $outtoks
  352. @ctx 2 param = ;
  353. @intoks 1 param = ;
  354. @outtoks 0 param = ;
  355. $changed
  356. @changed 0 = ;
  357. $i
  358. @i 0 = ;
  359. while i intoks vector_size < {
  360. @changed changed ctx outtoks intoks @i process_token || = ;
  361. @i i 1 + = ;
  362. }
  363. changed ret ;
  364. }
  365. fun preproc_replace 2 {
  366. $ctx
  367. $intoks
  368. @ctx 1 param = ;
  369. @intoks 0 param = ;
  370. $changed
  371. @changed 1 = ;
  372. @intoks intoks dup_vect_of_ptrs = ;
  373. while changed {
  374. $outtoks
  375. @outtoks 4 vector_init = ;
  376. @changed ctx intoks outtoks preproc_replace_int = ;
  377. intoks free_vect_of_ptrs ;
  378. @intoks outtoks = ;
  379. }
  380. intoks ret ;
  381. }
  382. fun preproc_expand 3 {
  383. $ctx
  384. $intoks
  385. $outtoks
  386. @ctx 2 param = ;
  387. @intoks 1 param = ;
  388. @outtoks 0 param = ;
  389. $replaced
  390. @replaced ctx intoks preproc_replace = ;
  391. $i
  392. @i 0 = ;
  393. while i replaced vector_size < {
  394. outtoks replaced i vector_at vector_push_back ;
  395. @i i 1 + = ;
  396. }
  397. replaced vector_destroy ;
  398. }
  399. fun preproc_process_define 4 {
  400. $ctx
  401. $tokens
  402. $intoks
  403. $iptr
  404. @ctx 3 param = ;
  405. @tokens 2 param = ;
  406. @intoks 1 param = ;
  407. @iptr 0 param = ;
  408. intoks iptr discard_white_tokens ;
  409. $ident
  410. @ident intoks iptr ** vector_at = ;
  411. ident "\n" strcmp 0 != "preproc_process_define: newline found" assert_msg ;
  412. iptr iptr ** 1 + = ;
  413. iptr ** intoks vector_size < "preproc_process_define: end of stream found" assert_msg ;
  414. $tok
  415. @tok intoks iptr ** vector_at = ;
  416. $is_func
  417. @is_func tok "(" strcmp 0 == = ;
  418. $subst
  419. @subst subst_init = ;
  420. subst SUBST_IS_FUNCTION take_addr is_func = ;
  421. if is_func {
  422. # TODO
  423. 0 assert ;
  424. } else {
  425. while tok "\n" strcmp 0 != {
  426. subst SUBST_REPLACEMENT take tok strdup vector_push_back ;
  427. iptr iptr ** 1 + = ;
  428. iptr ** intoks vector_size < "preproc_process_define: end of stream found" assert_msg ;
  429. @tok intoks iptr ** vector_at = ;
  430. }
  431. }
  432. if ctx PPCTX_DEFINES take ident map_has {
  433. $subst
  434. @subst ctx PPCTX_DEFINES take tok map_at = ;
  435. subst subst_destroy ;
  436. ctx PPCTX_DEFINES take tok map_erase ;
  437. }
  438. ctx PPCTX_DEFINES take ident subst map_set ;
  439. }
  440. fun preproc_process_undef 4 {
  441. $ctx
  442. $tokens
  443. $intoks
  444. $iptr
  445. @ctx 3 param = ;
  446. @tokens 2 param = ;
  447. @intoks 1 param = ;
  448. @iptr 0 param = ;
  449. intoks iptr discard_white_tokens ;
  450. $tok
  451. @tok intoks iptr ** vector_at = ;
  452. # If this definition is known, erase it
  453. if ctx PPCTX_DEFINES take tok map_has {
  454. $subst
  455. @subst ctx PPCTX_DEFINES take tok map_at = ;
  456. subst subst_destroy ;
  457. ctx PPCTX_DEFINES take tok map_erase ;
  458. }
  459. intoks iptr discard_white_tokens ;
  460. }
  461. ifun preproc_file 3
  462. fun preproc_process_include 4 {
  463. $ctx
  464. $tokens
  465. $intoks
  466. $iptr
  467. @ctx 3 param = ;
  468. @tokens 2 param = ;
  469. @intoks 1 param = ;
  470. @iptr 0 param = ;
  471. intoks iptr discard_white_tokens ;
  472. $tok
  473. @tok intoks iptr ** vector_at = ;
  474. $filename
  475. @filename "" strdup = ;
  476. if tok "<" strcmp 0 == {
  477. iptr iptr ** 1 + = ;
  478. @tok intoks iptr ** vector_at = ;
  479. while tok ">" strcmp 0 != {
  480. @filename filename tok append_to_str = ;
  481. iptr iptr ** 1 + = ;
  482. @tok intoks iptr ** vector_at = ;
  483. }
  484. } else {
  485. tok **c '"' == "preproc_process_include: syntax error in inclusion directive" assert_msg ;
  486. filename free ;
  487. @filename tok 1 + strdup = ;
  488. filename filename strlen 1 - + '\0' =c ;
  489. }
  490. "Including file " 1 platform_log ;
  491. filename 1 platform_log ;
  492. "\n" 1 platform_log ;
  493. tokens ctx filename preproc_file ;
  494. filename free ;
  495. intoks iptr discard_white_tokens ;
  496. }
  497. fun preproc_eval 2 {
  498. $ctx
  499. $ast
  500. @ctx 1 param = ;
  501. @ast 0 param = ;
  502. $defs
  503. @defs ctx PPCTX_DEFINES take = ;
  504. $name
  505. @name ast AST_NAME take = ;
  506. if ast AST_TYPE take 0 == {
  507. # Operand
  508. if defs name map_has {
  509. # TODO
  510. } else {
  511. 0 ret ;
  512. }
  513. } else {
  514. # Operator
  515. ast AST_TYPE take 1 == assert ;
  516. # TODO
  517. }
  518. }
  519. fun preproc_process_endif 5 {
  520. $ctx
  521. $tokens
  522. $intoks
  523. $iptr
  524. $if_stack
  525. @ctx 4 param = ;
  526. @tokens 3 param = ;
  527. @intoks 2 param = ;
  528. @iptr 1 param = ;
  529. @if_stack 0 param = ;
  530. if_stack vector_size 1 > "preproc_process_endif: unmatched endif" assert_msg ;
  531. if_stack vector_pop_back ;
  532. intoks iptr discard_white_tokens ;
  533. }
  534. fun preproc_process_else 5 {
  535. $ctx
  536. $tokens
  537. $intoks
  538. $iptr
  539. $if_stack
  540. @ctx 4 param = ;
  541. @tokens 3 param = ;
  542. @intoks 2 param = ;
  543. @iptr 1 param = ;
  544. @if_stack 0 param = ;
  545. $state
  546. if_stack vector_size 1 > "preproc_process_endif: unmatched else" assert_msg ;
  547. @state if_stack vector_pop_back = ;
  548. @state state 1 + = ;
  549. if state 2 > {
  550. @state 2 = ;
  551. }
  552. if_stack state vector_push_back ;
  553. intoks iptr discard_white_tokens ;
  554. }
  555. fun preproc_process_ifdef 5 {
  556. $ctx
  557. $tokens
  558. $intoks
  559. $iptr
  560. $if_stack
  561. @ctx 4 param = ;
  562. @tokens 3 param = ;
  563. @intoks 2 param = ;
  564. @iptr 1 param = ;
  565. @if_stack 0 param = ;
  566. intoks iptr discard_white_tokens ;
  567. $ident
  568. @ident intoks iptr ** vector_at = ;
  569. ident "\n" strcmp 0 != "preproc_process_ifdef: newline found" assert_msg ;
  570. if ctx PPCTX_DEFINES take ident map_has {
  571. if_stack 1 vector_push_back ;
  572. } else {
  573. if_stack 0 vector_push_back ;
  574. }
  575. intoks iptr discard_white_tokens ;
  576. }
  577. fun preproc_process_ifndef 5 {
  578. $ctx
  579. $tokens
  580. $intoks
  581. $iptr
  582. $if_stack
  583. @ctx 4 param = ;
  584. @tokens 3 param = ;
  585. @intoks 2 param = ;
  586. @iptr 1 param = ;
  587. @if_stack 0 param = ;
  588. intoks iptr discard_white_tokens ;
  589. $ident
  590. @ident intoks iptr ** vector_at = ;
  591. ident "\n" strcmp 0 != "preproc_process_ifndef: newline found" assert_msg ;
  592. if ctx PPCTX_DEFINES take ident map_has {
  593. if_stack 0 vector_push_back ;
  594. } else {
  595. if_stack 1 vector_push_back ;
  596. }
  597. intoks iptr discard_white_tokens ;
  598. }
  599. fun preproc_process_elif 5 {
  600. $ctx
  601. $tokens
  602. $intoks
  603. $iptr
  604. $if_stack
  605. @ctx 4 param = ;
  606. @tokens 3 param = ;
  607. @intoks 2 param = ;
  608. @iptr 1 param = ;
  609. @if_stack 0 param = ;
  610. 0 "preproc_process_elif: not implemented" assert_msg ;
  611. }
  612. fun preproc_process_if 5 {
  613. $ctx
  614. $tokens
  615. $intoks
  616. $iptr
  617. $if_stack
  618. @ctx 4 param = ;
  619. @tokens 3 param = ;
  620. @intoks 2 param = ;
  621. @iptr 1 param = ;
  622. @if_stack 0 param = ;
  623. $ast
  624. @ast intoks iptr "\n" ast_parse = ;
  625. #ast ast_dump ;
  626. ast ast_destroy ;
  627. ctx ast preproc_eval ;
  628. # FIXME
  629. if_stack 0 vector_push_back ;
  630. 0 "preproc_process_if: not implemented" assert_msg ;
  631. }
  632. fun preproc_process_error 4 {
  633. $ctx
  634. $tokens
  635. $intoks
  636. $iptr
  637. @ctx 3 param = ;
  638. @tokens 2 param = ;
  639. @intoks 1 param = ;
  640. @iptr 0 param = ;
  641. 0 "preproc_process_error: dying because of error" assert_msg ;
  642. }
  643. fun is_including 1 {
  644. $if_stack
  645. @if_stack 0 param = ;
  646. $i
  647. @i 0 = ;
  648. while i if_stack vector_size < {
  649. if if_stack i vector_at 1 != {
  650. 0 ret ;
  651. }
  652. @i i 1 + = ;
  653. }
  654. 1 ret ;
  655. }
  656. fun preproc_file 3 {
  657. $ctx
  658. $filename
  659. $tokens
  660. @ctx 1 param = ;
  661. @filename 0 param = ;
  662. @tokens 2 param = ;
  663. $intoks
  664. @intoks filename tokenize_file = ;
  665. # All incoming tokens are accumulated in ready_toks; before each
  666. # preprocessor directive is processed (and at the end of the file),
  667. # tokens in ready_tokens are expanded and flushed; this is probably
  668. # not the correct algorithm, but it should work for sane programs.
  669. $ready_toks
  670. @ready_toks 4 vector_init = ;
  671. $i
  672. @i 0 = ;
  673. $at_newline
  674. @at_newline 1 = ;
  675. # For each #if stack level, we store 0 if no if has matched yet, 1
  676. # if we are including and 2 if we have already matched
  677. $if_stack
  678. @if_stack 4 vector_init = ;
  679. if_stack 1 vector_push_back ;
  680. $including
  681. @including if_stack is_including = ;
  682. while i intoks vector_size < {
  683. $tok
  684. @tok intoks i vector_at = ;
  685. if tok "#" strcmp 0 == at_newline && {
  686. ctx ready_toks tokens preproc_expand ;
  687. ready_toks vector_clear ;
  688. intoks @i discard_white_tokens ;
  689. @tok intoks i vector_at = ;
  690. $processed
  691. @processed 0 = ;
  692. if tok "include" strcmp 0 == processed ! && {
  693. if including {
  694. ctx tokens intoks @i preproc_process_include ;
  695. } else {
  696. intoks @i discard_until_newline ;
  697. }
  698. @processed 1 = ;
  699. }
  700. if tok "define" strcmp 0 == processed ! && {
  701. if including {
  702. ctx tokens intoks @i preproc_process_define ;
  703. } else {
  704. intoks @i discard_until_newline ;
  705. }
  706. @processed 1 = ;
  707. }
  708. if tok "undef" strcmp 0 == processed ! && {
  709. if including {
  710. ctx tokens intoks @i preproc_process_undef ;
  711. } else {
  712. intoks @i discard_until_newline ;
  713. }
  714. @processed 1 = ;
  715. }
  716. if tok "error" strcmp 0 == processed ! && {
  717. if including {
  718. ctx tokens intoks @i preproc_process_error ;
  719. } else {
  720. intoks @i discard_until_newline ;
  721. }
  722. @processed 1 = ;
  723. }
  724. if tok "if" strcmp 0 == processed ! && {
  725. ctx tokens intoks @i if_stack preproc_process_if ;
  726. @including if_stack is_including = ;
  727. @processed 1 = ;
  728. }
  729. if tok "endif" strcmp 0 == processed ! && {
  730. ctx tokens intoks @i if_stack preproc_process_endif ;
  731. @including if_stack is_including = ;
  732. @processed 1 = ;
  733. }
  734. if tok "elif" strcmp 0 == processed ! && {
  735. ctx tokens intoks @i if_stack preproc_process_elif ;
  736. @including if_stack is_including = ;
  737. @processed 1 = ;
  738. }
  739. if tok "else" strcmp 0 == processed ! && {
  740. ctx tokens intoks @i if_stack preproc_process_else ;
  741. @including if_stack is_including = ;
  742. @processed 1 = ;
  743. }
  744. if tok "ifdef" strcmp 0 == processed ! && {
  745. ctx tokens intoks @i if_stack preproc_process_ifdef ;
  746. @including if_stack is_including = ;
  747. @processed 1 = ;
  748. }
  749. if tok "ifndef" strcmp 0 == processed ! && {
  750. ctx tokens intoks @i if_stack preproc_process_ifndef ;
  751. @including if_stack is_including = ;
  752. @processed 1 = ;
  753. }
  754. if processed ! {
  755. 0 "preproc_file: invalid preprocessor directive" assert_msg ;
  756. }
  757. intoks i vector_at "\n" strcmp 0 == "preproc_file: error 1" assert_msg ;
  758. } else {
  759. if including {
  760. ready_toks tok vector_push_back ;
  761. #ctx tokens intoks @i process_token ;
  762. }
  763. }
  764. @tok intoks i vector_at = ;
  765. @at_newline tok "\n" strcmp 0 == = ;
  766. @i i 1 + = ;
  767. }
  768. ctx ready_toks tokens preproc_expand ;
  769. ready_toks vector_clear ;
  770. ready_toks vector_destroy ;
  771. if_stack vector_size 1 == "preproc_file: some #if was not closed" assert_msg ;
  772. if_stack vector_destroy ;
  773. intoks free_vect_of_ptrs ;
  774. }
  775. fun remove_whites 1 {
  776. $intoks
  777. @intoks 0 param = ;
  778. $outtoks
  779. @outtoks 4 vector_init = ;
  780. $i
  781. @i 0 = ;
  782. while i intoks vector_size < {
  783. $tok
  784. @tok intoks i vector_at = ;
  785. if tok " " strcmp 0 == {
  786. tok free ;
  787. } else {
  788. if tok "\n" strcmp 0 == {
  789. tok free ;
  790. } else {
  791. outtoks tok vector_push_back ;
  792. }
  793. }
  794. @i i 1 + = ;
  795. }
  796. intoks vector_destroy ;
  797. outtoks ret ;
  798. }