tcc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +35 -0
  3. data/README.md +196 -0
  4. data/ext/tcc/extconf.rb +25 -0
  5. data/ext/tcc/tcc-0.9.26.patch +30 -0
  6. data/ext/tcc/tcc-0.9.26/COPYING +504 -0
  7. data/ext/tcc/tcc-0.9.26/Changelog +396 -0
  8. data/ext/tcc/tcc-0.9.26/Makefile +349 -0
  9. data/ext/tcc/tcc-0.9.26/README +101 -0
  10. data/ext/tcc/tcc-0.9.26/TODO +93 -0
  11. data/ext/tcc/tcc-0.9.26/VERSION +1 -0
  12. data/ext/tcc/tcc-0.9.26/arm-gen.c +2005 -0
  13. data/ext/tcc/tcc-0.9.26/c67-gen.c +2560 -0
  14. data/ext/tcc/tcc-0.9.26/coff.h +446 -0
  15. data/ext/tcc/tcc-0.9.26/config.h +8 -0
  16. data/ext/tcc/tcc-0.9.26/config.mak +28 -0
  17. data/ext/tcc/tcc-0.9.26/config.texi +1 -0
  18. data/ext/tcc/tcc-0.9.26/configure +540 -0
  19. data/ext/tcc/tcc-0.9.26/conftest.c +71 -0
  20. data/ext/tcc/tcc-0.9.26/elf.h +1731 -0
  21. data/ext/tcc/tcc-0.9.26/examples/ex1.c +8 -0
  22. data/ext/tcc/tcc-0.9.26/examples/ex2.c +98 -0
  23. data/ext/tcc/tcc-0.9.26/examples/ex3.c +24 -0
  24. data/ext/tcc/tcc-0.9.26/examples/ex4.c +26 -0
  25. data/ext/tcc/tcc-0.9.26/examples/ex5.c +8 -0
  26. data/ext/tcc/tcc-0.9.26/i386-asm.c +1498 -0
  27. data/ext/tcc/tcc-0.9.26/i386-asm.h +473 -0
  28. data/ext/tcc/tcc-0.9.26/i386-gen.c +1096 -0
  29. data/ext/tcc/tcc-0.9.26/i386-tok.h +243 -0
  30. data/ext/tcc/tcc-0.9.26/il-gen.c +667 -0
  31. data/ext/tcc/tcc-0.9.26/il-opcodes.h +251 -0
  32. data/ext/tcc/tcc-0.9.26/include/float.h +57 -0
  33. data/ext/tcc/tcc-0.9.26/include/stdarg.h +41 -0
  34. data/ext/tcc/tcc-0.9.26/include/stdbool.h +10 -0
  35. data/ext/tcc/tcc-0.9.26/include/stddef.h +28 -0
  36. data/ext/tcc/tcc-0.9.26/include/tcclib.h +78 -0
  37. data/ext/tcc/tcc-0.9.26/include/varargs.h +12 -0
  38. data/ext/tcc/tcc-0.9.26/lib/Makefile +102 -0
  39. data/ext/tcc/tcc-0.9.26/lib/alloca86-bt.S +47 -0
  40. data/ext/tcc/tcc-0.9.26/lib/alloca86.S +35 -0
  41. data/ext/tcc/tcc-0.9.26/lib/alloca86_64.S +42 -0
  42. data/ext/tcc/tcc-0.9.26/lib/bcheck.c +875 -0
  43. data/ext/tcc/tcc-0.9.26/lib/libtcc1.c +691 -0
  44. data/ext/tcc/tcc-0.9.26/libtcc.c +1941 -0
  45. data/ext/tcc/tcc-0.9.26/libtcc.h +103 -0
  46. data/ext/tcc/tcc-0.9.26/stab.def +234 -0
  47. data/ext/tcc/tcc-0.9.26/stab.h +17 -0
  48. data/ext/tcc/tcc-0.9.26/tcc-doc.html +2332 -0
  49. data/ext/tcc/tcc-0.9.26/tcc-doc.info +1151 -0
  50. data/ext/tcc/tcc-0.9.26/tcc-doc.texi +1268 -0
  51. data/ext/tcc/tcc-0.9.26/tcc.1 +415 -0
  52. data/ext/tcc/tcc-0.9.26/tcc.c +352 -0
  53. data/ext/tcc/tcc-0.9.26/tcc.h +1379 -0
  54. data/ext/tcc/tcc-0.9.26/tccasm.c +1118 -0
  55. data/ext/tcc/tcc-0.9.26/tcccoff.c +948 -0
  56. data/ext/tcc/tcc-0.9.26/tccelf.c +3129 -0
  57. data/ext/tcc/tcc-0.9.26/tccgen.c +5841 -0
  58. data/ext/tcc/tcc-0.9.26/tccpe.c +1887 -0
  59. data/ext/tcc/tcc-0.9.26/tccpp.c +3128 -0
  60. data/ext/tcc/tcc-0.9.26/tccrun.c +737 -0
  61. data/ext/tcc/tcc-0.9.26/tcctok.h +278 -0
  62. data/ext/tcc/tcc-0.9.26/tests/Makefile +199 -0
  63. data/ext/tcc/tcc-0.9.26/tests/asmtest.S +609 -0
  64. data/ext/tcc/tcc-0.9.26/tests/boundtest.c +233 -0
  65. data/ext/tcc/tcc-0.9.26/tests/gcctestsuite.sh +33 -0
  66. data/ext/tcc/tcc-0.9.26/tests/libtcc_test.c +76 -0
  67. data/ext/tcc/tcc-0.9.26/tests/tcctest.c +2713 -0
  68. data/ext/tcc/tcc-0.9.26/tests/tests2/00_assignment.c +18 -0
  69. data/ext/tcc/tcc-0.9.26/tests/tests2/00_assignment.expect +3 -0
  70. data/ext/tcc/tcc-0.9.26/tests/tests2/01_comment.c +14 -0
  71. data/ext/tcc/tcc-0.9.26/tests/tests2/01_comment.expect +5 -0
  72. data/ext/tcc/tcc-0.9.26/tests/tests2/02_printf.c +18 -0
  73. data/ext/tcc/tcc-0.9.26/tests/tests2/02_printf.expect +15 -0
  74. data/ext/tcc/tcc-0.9.26/tests/tests2/03_struct.c +31 -0
  75. data/ext/tcc/tcc-0.9.26/tests/tests2/03_struct.expect +6 -0
  76. data/ext/tcc/tcc-0.9.26/tests/tests2/04_for.c +15 -0
  77. data/ext/tcc/tcc-0.9.26/tests/tests2/04_for.expect +10 -0
  78. data/ext/tcc/tcc-0.9.26/tests/tests2/05_array.c +21 -0
  79. data/ext/tcc/tcc-0.9.26/tests/tests2/05_array.expect +10 -0
  80. data/ext/tcc/tcc-0.9.26/tests/tests2/06_case.c +29 -0
  81. data/ext/tcc/tcc-0.9.26/tests/tests2/06_case.expect +8 -0
  82. data/ext/tcc/tcc-0.9.26/tests/tests2/07_function.c +30 -0
  83. data/ext/tcc/tcc-0.9.26/tests/tests2/07_function.expect +4 -0
  84. data/ext/tcc/tcc-0.9.26/tests/tests2/08_while.c +24 -0
  85. data/ext/tcc/tcc-0.9.26/tests/tests2/08_while.expect +11 -0
  86. data/ext/tcc/tcc-0.9.26/tests/tests2/09_do_while.c +24 -0
  87. data/ext/tcc/tcc-0.9.26/tests/tests2/09_do_while.expect +11 -0
  88. data/ext/tcc/tcc-0.9.26/tests/tests2/10_pointer.c +40 -0
  89. data/ext/tcc/tcc-0.9.26/tests/tests2/10_pointer.expect +8 -0
  90. data/ext/tcc/tcc-0.9.26/tests/tests2/11_precedence.c +40 -0
  91. data/ext/tcc/tcc-0.9.26/tests/tests2/11_precedence.expect +15 -0
  92. data/ext/tcc/tcc-0.9.26/tests/tests2/12_hashdefine.c +14 -0
  93. data/ext/tcc/tcc-0.9.26/tests/tests2/12_hashdefine.expect +2 -0
  94. data/ext/tcc/tcc-0.9.26/tests/tests2/13_integer_literals.c +20 -0
  95. data/ext/tcc/tcc-0.9.26/tests/tests2/13_integer_literals.expect +5 -0
  96. data/ext/tcc/tcc-0.9.26/tests/tests2/14_if.c +21 -0
  97. data/ext/tcc/tcc-0.9.26/tests/tests2/14_if.expect +2 -0
  98. data/ext/tcc/tcc-0.9.26/tests/tests2/15_recursion.c +21 -0
  99. data/ext/tcc/tcc-0.9.26/tests/tests2/15_recursion.expect +10 -0
  100. data/ext/tcc/tcc-0.9.26/tests/tests2/16_nesting.c +21 -0
  101. data/ext/tcc/tcc-0.9.26/tests/tests2/16_nesting.expect +18 -0
  102. data/ext/tcc/tcc-0.9.26/tests/tests2/17_enum.c +29 -0
  103. data/ext/tcc/tcc-0.9.26/tests/tests2/17_enum.expect +3 -0
  104. data/ext/tcc/tcc-0.9.26/tests/tests2/18_include.c +12 -0
  105. data/ext/tcc/tcc-0.9.26/tests/tests2/18_include.expect +3 -0
  106. data/ext/tcc/tcc-0.9.26/tests/tests2/18_include.h +1 -0
  107. data/ext/tcc/tcc-0.9.26/tests/tests2/19_pointer_arithmetic.c +28 -0
  108. data/ext/tcc/tcc-0.9.26/tests/tests2/19_pointer_arithmetic.expect +3 -0
  109. data/ext/tcc/tcc-0.9.26/tests/tests2/20_pointer_comparison.c +24 -0
  110. data/ext/tcc/tcc-0.9.26/tests/tests2/20_pointer_comparison.expect +6 -0
  111. data/ext/tcc/tcc-0.9.26/tests/tests2/21_char_array.c +33 -0
  112. data/ext/tcc/tcc-0.9.26/tests/tests2/21_char_array.expect +7 -0
  113. data/ext/tcc/tcc-0.9.26/tests/tests2/22_floating_point.c +50 -0
  114. data/ext/tcc/tcc-0.9.26/tests/tests2/22_floating_point.expect +16 -0
  115. data/ext/tcc/tcc-0.9.26/tests/tests2/23_type_coercion.c +54 -0
  116. data/ext/tcc/tcc-0.9.26/tests/tests2/23_type_coercion.expect +12 -0
  117. data/ext/tcc/tcc-0.9.26/tests/tests2/24_math_library.c +28 -0
  118. data/ext/tcc/tcc-0.9.26/tests/tests2/24_math_library.expect +18 -0
  119. data/ext/tcc/tcc-0.9.26/tests/tests2/25_quicksort.c +83 -0
  120. data/ext/tcc/tcc-0.9.26/tests/tests2/25_quicksort.expect +2 -0
  121. data/ext/tcc/tcc-0.9.26/tests/tests2/26_character_constants.c +17 -0
  122. data/ext/tcc/tcc-0.9.26/tests/tests2/26_character_constants.expect +8 -0
  123. data/ext/tcc/tcc-0.9.26/tests/tests2/27_sizeof.c +16 -0
  124. data/ext/tcc/tcc-0.9.26/tests/tests2/27_sizeof.expect +3 -0
  125. data/ext/tcc/tcc-0.9.26/tests/tests2/28_strings.c +46 -0
  126. data/ext/tcc/tcc-0.9.26/tests/tests2/28_strings.expect +19 -0
  127. data/ext/tcc/tcc-0.9.26/tests/tests2/29_array_address.c +13 -0
  128. data/ext/tcc/tcc-0.9.26/tests/tests2/29_array_address.expect +1 -0
  129. data/ext/tcc/tcc-0.9.26/tests/tests2/30_hanoi.c +122 -0
  130. data/ext/tcc/tcc-0.9.26/tests/tests2/30_hanoi.expect +71 -0
  131. data/ext/tcc/tcc-0.9.26/tests/tests2/31_args.c +14 -0
  132. data/ext/tcc/tcc-0.9.26/tests/tests2/31_args.expect +7 -0
  133. data/ext/tcc/tcc-0.9.26/tests/tests2/32_led.c +266 -0
  134. data/ext/tcc/tcc-0.9.26/tests/tests2/32_led.expect +4 -0
  135. data/ext/tcc/tcc-0.9.26/tests/tests2/33_ternary_op.c +15 -0
  136. data/ext/tcc/tcc-0.9.26/tests/tests2/33_ternary_op.expect +10 -0
  137. data/ext/tcc/tcc-0.9.26/tests/tests2/34_array_assignment.c +23 -0
  138. data/ext/tcc/tcc-0.9.26/tests/tests2/34_array_assignment.expect +2 -0
  139. data/ext/tcc/tcc-0.9.26/tests/tests2/35_sizeof.c +14 -0
  140. data/ext/tcc/tcc-0.9.26/tests/tests2/35_sizeof.expect +2 -0
  141. data/ext/tcc/tcc-0.9.26/tests/tests2/36_array_initialisers.c +21 -0
  142. data/ext/tcc/tcc-0.9.26/tests/tests2/36_array_initialisers.expect +20 -0
  143. data/ext/tcc/tcc-0.9.26/tests/tests2/37_sprintf.c +17 -0
  144. data/ext/tcc/tcc-0.9.26/tests/tests2/37_sprintf.expect +20 -0
  145. data/ext/tcc/tcc-0.9.26/tests/tests2/38_multiple_array_index.c +32 -0
  146. data/ext/tcc/tcc-0.9.26/tests/tests2/38_multiple_array_index.expect +4 -0
  147. data/ext/tcc/tcc-0.9.26/tests/tests2/39_typedef.c +31 -0
  148. data/ext/tcc/tcc-0.9.26/tests/tests2/39_typedef.expect +3 -0
  149. data/ext/tcc/tcc-0.9.26/tests/tests2/40_stdio.c +52 -0
  150. data/ext/tcc/tcc-0.9.26/tests/tests2/40_stdio.expect +27 -0
  151. data/ext/tcc/tcc-0.9.26/tests/tests2/41_hashif.c +85 -0
  152. data/ext/tcc/tcc-0.9.26/tests/tests2/41_hashif.expect +6 -0
  153. data/ext/tcc/tcc-0.9.26/tests/tests2/42_function_pointer.c +18 -0
  154. data/ext/tcc/tcc-0.9.26/tests/tests2/42_function_pointer.expect +2 -0
  155. data/ext/tcc/tcc-0.9.26/tests/tests2/43_void_param.c +15 -0
  156. data/ext/tcc/tcc-0.9.26/tests/tests2/43_void_param.expect +1 -0
  157. data/ext/tcc/tcc-0.9.26/tests/tests2/44_scoped_declarations.c +17 -0
  158. data/ext/tcc/tcc-0.9.26/tests/tests2/44_scoped_declarations.expect +1 -0
  159. data/ext/tcc/tcc-0.9.26/tests/tests2/45_empty_for.c +18 -0
  160. data/ext/tcc/tcc-0.9.26/tests/tests2/45_empty_for.expect +10 -0
  161. data/ext/tcc/tcc-0.9.26/tests/tests2/46_grep.c +564 -0
  162. data/ext/tcc/tcc-0.9.26/tests/tests2/47_switch_return.c +24 -0
  163. data/ext/tcc/tcc-0.9.26/tests/tests2/47_switch_return.expect +4 -0
  164. data/ext/tcc/tcc-0.9.26/tests/tests2/48_nested_break.c +26 -0
  165. data/ext/tcc/tcc-0.9.26/tests/tests2/48_nested_break.expect +1 -0
  166. data/ext/tcc/tcc-0.9.26/tests/tests2/49_bracket_evaluation.c +23 -0
  167. data/ext/tcc/tcc-0.9.26/tests/tests2/49_bracket_evaluation.expect +1 -0
  168. data/ext/tcc/tcc-0.9.26/tests/tests2/50_logical_second_arg.c +29 -0
  169. data/ext/tcc/tcc-0.9.26/tests/tests2/50_logical_second_arg.expect +20 -0
  170. data/ext/tcc/tcc-0.9.26/tests/tests2/51_static.c +30 -0
  171. data/ext/tcc/tcc-0.9.26/tests/tests2/51_static.expect +8 -0
  172. data/ext/tcc/tcc-0.9.26/tests/tests2/52_unnamed_enum.c +27 -0
  173. data/ext/tcc/tcc-0.9.26/tests/tests2/52_unnamed_enum.expect +9 -0
  174. data/ext/tcc/tcc-0.9.26/tests/tests2/54_goto.c +56 -0
  175. data/ext/tcc/tcc-0.9.26/tests/tests2/54_goto.expect +8 -0
  176. data/ext/tcc/tcc-0.9.26/tests/tests2/55_lshift_type.c +52 -0
  177. data/ext/tcc/tcc-0.9.26/tests/tests2/55_lshift_type.expect +1 -0
  178. data/ext/tcc/tcc-0.9.26/tests/tests2/LICENSE +37 -0
  179. data/ext/tcc/tcc-0.9.26/tests/tests2/Makefile +98 -0
  180. data/ext/tcc/tcc-0.9.26/texi2pod.pl +427 -0
  181. data/ext/tcc/tcc-0.9.26/win32/build-tcc.bat +60 -0
  182. data/ext/tcc/tcc-0.9.26/win32/examples/dll.c +12 -0
  183. data/ext/tcc/tcc-0.9.26/win32/examples/fib.c +23 -0
  184. data/ext/tcc/tcc-0.9.26/win32/examples/hello_dll.c +19 -0
  185. data/ext/tcc/tcc-0.9.26/win32/examples/hello_win.c +163 -0
  186. data/ext/tcc/tcc-0.9.26/win32/include/_mingw.h +139 -0
  187. data/ext/tcc/tcc-0.9.26/win32/include/assert.h +54 -0
  188. data/ext/tcc/tcc-0.9.26/win32/include/conio.h +409 -0
  189. data/ext/tcc/tcc-0.9.26/win32/include/ctype.h +281 -0
  190. data/ext/tcc/tcc-0.9.26/win32/include/dir.h +31 -0
  191. data/ext/tcc/tcc-0.9.26/win32/include/direct.h +68 -0
  192. data/ext/tcc/tcc-0.9.26/win32/include/dirent.h +135 -0
  193. data/ext/tcc/tcc-0.9.26/win32/include/dos.h +55 -0
  194. data/ext/tcc/tcc-0.9.26/win32/include/errno.h +75 -0
  195. data/ext/tcc/tcc-0.9.26/win32/include/excpt.h +123 -0
  196. data/ext/tcc/tcc-0.9.26/win32/include/fcntl.h +52 -0
  197. data/ext/tcc/tcc-0.9.26/win32/include/fenv.h +108 -0
  198. data/ext/tcc/tcc-0.9.26/win32/include/inttypes.h +297 -0
  199. data/ext/tcc/tcc-0.9.26/win32/include/io.h +418 -0
  200. data/ext/tcc/tcc-0.9.26/win32/include/limits.h +111 -0
  201. data/ext/tcc/tcc-0.9.26/win32/include/locale.h +91 -0
  202. data/ext/tcc/tcc-0.9.26/win32/include/malloc.h +175 -0
  203. data/ext/tcc/tcc-0.9.26/win32/include/math.h +777 -0
  204. data/ext/tcc/tcc-0.9.26/win32/include/mem.h +13 -0
  205. data/ext/tcc/tcc-0.9.26/win32/include/memory.h +40 -0
  206. data/ext/tcc/tcc-0.9.26/win32/include/process.h +176 -0
  207. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/conio_s.h +42 -0
  208. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/crtdbg_s.h +19 -0
  209. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/io_s.h +33 -0
  210. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/mbstring_s.h +52 -0
  211. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/search_s.h +25 -0
  212. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/stdio_s.h +145 -0
  213. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/stdlib_s.h +67 -0
  214. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/stralign_s.h +30 -0
  215. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/string_s.h +41 -0
  216. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/sys/timeb_s.h +34 -0
  217. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/tchar_s.h +266 -0
  218. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/time_s.h +61 -0
  219. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/wchar_s.h +128 -0
  220. data/ext/tcc/tcc-0.9.26/win32/include/setjmp.h +160 -0
  221. data/ext/tcc/tcc-0.9.26/win32/include/share.h +28 -0
  222. data/ext/tcc/tcc-0.9.26/win32/include/signal.h +63 -0
  223. data/ext/tcc/tcc-0.9.26/win32/include/stdint.h +209 -0
  224. data/ext/tcc/tcc-0.9.26/win32/include/stdio.h +429 -0
  225. data/ext/tcc/tcc-0.9.26/win32/include/stdlib.h +580 -0
  226. data/ext/tcc/tcc-0.9.26/win32/include/string.h +164 -0
  227. data/ext/tcc/tcc-0.9.26/win32/include/sys/fcntl.h +13 -0
  228. data/ext/tcc/tcc-0.9.26/win32/include/sys/file.h +14 -0
  229. data/ext/tcc/tcc-0.9.26/win32/include/sys/locking.h +30 -0
  230. data/ext/tcc/tcc-0.9.26/win32/include/sys/stat.h +290 -0
  231. data/ext/tcc/tcc-0.9.26/win32/include/sys/time.h +69 -0
  232. data/ext/tcc/tcc-0.9.26/win32/include/sys/timeb.h +133 -0
  233. data/ext/tcc/tcc-0.9.26/win32/include/sys/types.h +118 -0
  234. data/ext/tcc/tcc-0.9.26/win32/include/sys/unistd.h +14 -0
  235. data/ext/tcc/tcc-0.9.26/win32/include/sys/utime.h +146 -0
  236. data/ext/tcc/tcc-0.9.26/win32/include/tchar.h +1102 -0
  237. data/ext/tcc/tcc-0.9.26/win32/include/time.h +287 -0
  238. data/ext/tcc/tcc-0.9.26/win32/include/vadefs.h +11 -0
  239. data/ext/tcc/tcc-0.9.26/win32/include/values.h +4 -0
  240. data/ext/tcc/tcc-0.9.26/win32/include/wchar.h +871 -0
  241. data/ext/tcc/tcc-0.9.26/win32/include/wctype.h +172 -0
  242. data/ext/tcc/tcc-0.9.26/win32/include/winapi/basetsd.h +149 -0
  243. data/ext/tcc/tcc-0.9.26/win32/include/winapi/basetyps.h +85 -0
  244. data/ext/tcc/tcc-0.9.26/win32/include/winapi/guiddef.h +151 -0
  245. data/ext/tcc/tcc-0.9.26/win32/include/winapi/intrin.h +11 -0
  246. data/ext/tcc/tcc-0.9.26/win32/include/winapi/poppack.h +8 -0
  247. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack1.h +8 -0
  248. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack2.h +8 -0
  249. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack4.h +8 -0
  250. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack8.h +8 -0
  251. data/ext/tcc/tcc-0.9.26/win32/include/winapi/reason.h +80 -0
  252. data/ext/tcc/tcc-0.9.26/win32/include/winapi/specstrings.h +7 -0
  253. data/ext/tcc/tcc-0.9.26/win32/include/winapi/stralign.h +154 -0
  254. data/ext/tcc/tcc-0.9.26/win32/include/winapi/tvout.h +79 -0
  255. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winbase.h +2951 -0
  256. data/ext/tcc/tcc-0.9.26/win32/include/winapi/wincon.h +301 -0
  257. data/ext/tcc/tcc-0.9.26/win32/include/winapi/windef.h +293 -0
  258. data/ext/tcc/tcc-0.9.26/win32/include/winapi/windows.h +123 -0
  259. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winerror.h +3166 -0
  260. data/ext/tcc/tcc-0.9.26/win32/include/winapi/wingdi.h +4080 -0
  261. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winnetwk.h +476 -0
  262. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winnls.h +765 -0
  263. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winnt.h +5770 -0
  264. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winreg.h +272 -0
  265. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winuser.h +5651 -0
  266. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winver.h +160 -0
  267. data/ext/tcc/tcc-0.9.26/win32/lib/chkstk.S +191 -0
  268. data/ext/tcc/tcc-0.9.26/win32/lib/crt1.c +34 -0
  269. data/ext/tcc/tcc-0.9.26/win32/lib/dllcrt1.c +13 -0
  270. data/ext/tcc/tcc-0.9.26/win32/lib/dllmain.c +9 -0
  271. data/ext/tcc/tcc-0.9.26/win32/lib/gdi32.def +337 -0
  272. data/ext/tcc/tcc-0.9.26/win32/lib/kernel32.def +765 -0
  273. data/ext/tcc/tcc-0.9.26/win32/lib/msvcrt.def +1399 -0
  274. data/ext/tcc/tcc-0.9.26/win32/lib/user32.def +654 -0
  275. data/ext/tcc/tcc-0.9.26/win32/lib/wincrt1.c +64 -0
  276. data/ext/tcc/tcc-0.9.26/win32/tcc-win32.txt +156 -0
  277. data/ext/tcc/tcc-0.9.26/win32/tools/tiny_impdef.c +243 -0
  278. data/ext/tcc/tcc-0.9.26/win32/tools/tiny_libmaker.c +258 -0
  279. data/ext/tcc/tcc-0.9.26/x86_64-asm.h +448 -0
  280. data/ext/tcc/tcc-0.9.26/x86_64-gen.c +1701 -0
  281. data/lib/tcc.rb +291 -0
  282. data/tcc.gemspec +15 -0
  283. metadata +343 -0
@@ -0,0 +1,3128 @@
1
+ /*
2
+ * TCC - Tiny C Compiler
3
+ *
4
+ * Copyright (c) 2001-2004 Fabrice Bellard
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2 of the License, or (at your option) any later version.
10
+ *
11
+ * This library 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 GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+ #include "tcc.h"
22
+
23
+ /********************************************************/
24
+ /* global variables */
25
+
26
+ ST_DATA int tok_flags;
27
+ /* additional informations about token */
28
+ #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
29
+ #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
30
+ #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
31
+ #define TOK_FLAG_EOF 0x0008 /* end of file */
32
+
33
+ ST_DATA int parse_flags;
34
+ #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
35
+ #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
36
+ #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
37
+ token. line feed is also
38
+ returned at eof */
39
+ #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
40
+ #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
41
+
42
+ ST_DATA struct BufferedFile *file;
43
+ ST_DATA int ch, tok;
44
+ ST_DATA CValue tokc;
45
+ ST_DATA const int *macro_ptr;
46
+ ST_DATA CString tokcstr; /* current parsed string, if any */
47
+
48
+ /* display benchmark infos */
49
+ ST_DATA int total_lines;
50
+ ST_DATA int total_bytes;
51
+ ST_DATA int tok_ident;
52
+ ST_DATA TokenSym **table_ident;
53
+
54
+ /* ------------------------------------------------------------------------- */
55
+
56
+ static int *macro_ptr_allocated;
57
+ static const int *unget_saved_macro_ptr;
58
+ static int unget_saved_buffer[TOK_MAX_SIZE + 1];
59
+ static int unget_buffer_enabled;
60
+ static TokenSym *hash_ident[TOK_HASH_SIZE];
61
+ static char token_buf[STRING_MAX_SIZE + 1];
62
+ /* true if isid(c) || isnum(c) */
63
+ static unsigned char isidnum_table[256-CH_EOF];
64
+
65
+ static const char tcc_keywords[] =
66
+ #define DEF(id, str) str "\0"
67
+ #include "tcctok.h"
68
+ #undef DEF
69
+ ;
70
+
71
+ /* WARNING: the content of this string encodes token numbers */
72
+ static const unsigned char tok_two_chars[] =
73
+ "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253"
74
+ "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
75
+
76
+ struct macro_level {
77
+ struct macro_level *prev;
78
+ const int *p;
79
+ };
80
+
81
+ ST_FUNC void next_nomacro(void);
82
+ static void next_nomacro_spc(void);
83
+ static void macro_subst(
84
+ TokenString *tok_str,
85
+ Sym **nested_list,
86
+ const int *macro_str,
87
+ struct macro_level **can_read_stream
88
+ );
89
+
90
+ ST_FUNC void skip(int c)
91
+ {
92
+ if (tok != c)
93
+ tcc_error("'%c' expected (got \"%s\")", c, get_tok_str(tok, &tokc));
94
+ next();
95
+ }
96
+
97
+ ST_FUNC void expect(const char *msg)
98
+ {
99
+ tcc_error("%s expected", msg);
100
+ }
101
+
102
+ /* ------------------------------------------------------------------------- */
103
+ /* CString handling */
104
+ static void cstr_realloc(CString *cstr, int new_size)
105
+ {
106
+ int size;
107
+ void *data;
108
+
109
+ size = cstr->size_allocated;
110
+ if (size == 0)
111
+ size = 8; /* no need to allocate a too small first string */
112
+ while (size < new_size)
113
+ size = size * 2;
114
+ data = tcc_realloc(cstr->data_allocated, size);
115
+ cstr->data_allocated = data;
116
+ cstr->size_allocated = size;
117
+ cstr->data = data;
118
+ }
119
+
120
+ /* add a byte */
121
+ ST_FUNC void cstr_ccat(CString *cstr, int ch)
122
+ {
123
+ int size;
124
+ size = cstr->size + 1;
125
+ if (size > cstr->size_allocated)
126
+ cstr_realloc(cstr, size);
127
+ ((unsigned char *)cstr->data)[size - 1] = ch;
128
+ cstr->size = size;
129
+ }
130
+
131
+ ST_FUNC void cstr_cat(CString *cstr, const char *str)
132
+ {
133
+ int c;
134
+ for(;;) {
135
+ c = *str;
136
+ if (c == '\0')
137
+ break;
138
+ cstr_ccat(cstr, c);
139
+ str++;
140
+ }
141
+ }
142
+
143
+ /* add a wide char */
144
+ ST_FUNC void cstr_wccat(CString *cstr, int ch)
145
+ {
146
+ int size;
147
+ size = cstr->size + sizeof(nwchar_t);
148
+ if (size > cstr->size_allocated)
149
+ cstr_realloc(cstr, size);
150
+ *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
151
+ cstr->size = size;
152
+ }
153
+
154
+ ST_FUNC void cstr_new(CString *cstr)
155
+ {
156
+ memset(cstr, 0, sizeof(CString));
157
+ }
158
+
159
+ /* free string and reset it to NULL */
160
+ ST_FUNC void cstr_free(CString *cstr)
161
+ {
162
+ tcc_free(cstr->data_allocated);
163
+ cstr_new(cstr);
164
+ }
165
+
166
+ /* reset string to empty */
167
+ ST_FUNC void cstr_reset(CString *cstr)
168
+ {
169
+ cstr->size = 0;
170
+ }
171
+
172
+ /* XXX: unicode ? */
173
+ static void add_char(CString *cstr, int c)
174
+ {
175
+ if (c == '\'' || c == '\"' || c == '\\') {
176
+ /* XXX: could be more precise if char or string */
177
+ cstr_ccat(cstr, '\\');
178
+ }
179
+ if (c >= 32 && c <= 126) {
180
+ cstr_ccat(cstr, c);
181
+ } else {
182
+ cstr_ccat(cstr, '\\');
183
+ if (c == '\n') {
184
+ cstr_ccat(cstr, 'n');
185
+ } else {
186
+ cstr_ccat(cstr, '0' + ((c >> 6) & 7));
187
+ cstr_ccat(cstr, '0' + ((c >> 3) & 7));
188
+ cstr_ccat(cstr, '0' + (c & 7));
189
+ }
190
+ }
191
+ }
192
+
193
+ /* ------------------------------------------------------------------------- */
194
+ /* allocate a new token */
195
+ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
196
+ {
197
+ TokenSym *ts, **ptable;
198
+ int i;
199
+
200
+ if (tok_ident >= SYM_FIRST_ANOM)
201
+ tcc_error("memory full");
202
+
203
+ /* expand token table if needed */
204
+ i = tok_ident - TOK_IDENT;
205
+ if ((i % TOK_ALLOC_INCR) == 0) {
206
+ ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
207
+ table_ident = ptable;
208
+ }
209
+
210
+ ts = tcc_malloc(sizeof(TokenSym) + len);
211
+ table_ident[i] = ts;
212
+ ts->tok = tok_ident++;
213
+ ts->sym_define = NULL;
214
+ ts->sym_label = NULL;
215
+ ts->sym_struct = NULL;
216
+ ts->sym_identifier = NULL;
217
+ ts->len = len;
218
+ ts->hash_next = NULL;
219
+ memcpy(ts->str, str, len);
220
+ ts->str[len] = '\0';
221
+ *pts = ts;
222
+ return ts;
223
+ }
224
+
225
+ #define TOK_HASH_INIT 1
226
+ #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
227
+
228
+ /* find a token and add it if not found */
229
+ ST_FUNC TokenSym *tok_alloc(const char *str, int len)
230
+ {
231
+ TokenSym *ts, **pts;
232
+ int i;
233
+ unsigned int h;
234
+
235
+ h = TOK_HASH_INIT;
236
+ for(i=0;i<len;i++)
237
+ h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
238
+ h &= (TOK_HASH_SIZE - 1);
239
+
240
+ pts = &hash_ident[h];
241
+ for(;;) {
242
+ ts = *pts;
243
+ if (!ts)
244
+ break;
245
+ if (ts->len == len && !memcmp(ts->str, str, len))
246
+ return ts;
247
+ pts = &(ts->hash_next);
248
+ }
249
+ return tok_alloc_new(pts, str, len);
250
+ }
251
+
252
+ /* XXX: buffer overflow */
253
+ /* XXX: float tokens */
254
+ ST_FUNC char *get_tok_str(int v, CValue *cv)
255
+ {
256
+ static char buf[STRING_MAX_SIZE + 1];
257
+ static CString cstr_buf;
258
+ CString *cstr;
259
+ char *p;
260
+ int i, len;
261
+
262
+ /* NOTE: to go faster, we give a fixed buffer for small strings */
263
+ cstr_reset(&cstr_buf);
264
+ cstr_buf.data = buf;
265
+ cstr_buf.size_allocated = sizeof(buf);
266
+ p = buf;
267
+
268
+ switch(v) {
269
+ case TOK_CINT:
270
+ case TOK_CUINT:
271
+ /* XXX: not quite exact, but only useful for testing */
272
+ sprintf(p, "%u", cv->ui);
273
+ break;
274
+ case TOK_CLLONG:
275
+ case TOK_CULLONG:
276
+ /* XXX: not quite exact, but only useful for testing */
277
+ #ifdef _WIN32
278
+ sprintf(p, "%u", (unsigned)cv->ull);
279
+ #else
280
+ sprintf(p, "%Lu", cv->ull);
281
+ #endif
282
+ break;
283
+ case TOK_LCHAR:
284
+ cstr_ccat(&cstr_buf, 'L');
285
+ case TOK_CCHAR:
286
+ cstr_ccat(&cstr_buf, '\'');
287
+ add_char(&cstr_buf, cv->i);
288
+ cstr_ccat(&cstr_buf, '\'');
289
+ cstr_ccat(&cstr_buf, '\0');
290
+ break;
291
+ case TOK_PPNUM:
292
+ cstr = cv->cstr;
293
+ len = cstr->size - 1;
294
+ for(i=0;i<len;i++)
295
+ add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
296
+ cstr_ccat(&cstr_buf, '\0');
297
+ break;
298
+ case TOK_LSTR:
299
+ cstr_ccat(&cstr_buf, 'L');
300
+ case TOK_STR:
301
+ cstr = cv->cstr;
302
+ cstr_ccat(&cstr_buf, '\"');
303
+ if (v == TOK_STR) {
304
+ len = cstr->size - 1;
305
+ for(i=0;i<len;i++)
306
+ add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
307
+ } else {
308
+ len = (cstr->size / sizeof(nwchar_t)) - 1;
309
+ for(i=0;i<len;i++)
310
+ add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
311
+ }
312
+ cstr_ccat(&cstr_buf, '\"');
313
+ cstr_ccat(&cstr_buf, '\0');
314
+ break;
315
+ case TOK_LT:
316
+ v = '<';
317
+ goto addv;
318
+ case TOK_GT:
319
+ v = '>';
320
+ goto addv;
321
+ case TOK_DOTS:
322
+ return strcpy(p, "...");
323
+ case TOK_A_SHL:
324
+ return strcpy(p, "<<=");
325
+ case TOK_A_SAR:
326
+ return strcpy(p, ">>=");
327
+ default:
328
+ if (v < TOK_IDENT) {
329
+ /* search in two bytes table */
330
+ const unsigned char *q = tok_two_chars;
331
+ while (*q) {
332
+ if (q[2] == v) {
333
+ *p++ = q[0];
334
+ *p++ = q[1];
335
+ *p = '\0';
336
+ return buf;
337
+ }
338
+ q += 3;
339
+ }
340
+ addv:
341
+ *p++ = v;
342
+ *p = '\0';
343
+ } else if (v < tok_ident) {
344
+ return table_ident[v - TOK_IDENT]->str;
345
+ } else if (v >= SYM_FIRST_ANOM) {
346
+ /* special name for anonymous symbol */
347
+ sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
348
+ } else {
349
+ /* should never happen */
350
+ return NULL;
351
+ }
352
+ break;
353
+ }
354
+ return cstr_buf.data;
355
+ }
356
+
357
+ /* fill input buffer and peek next char */
358
+ static int tcc_peekc_slow(BufferedFile *bf)
359
+ {
360
+ int len;
361
+ /* only tries to read if really end of buffer */
362
+ if (bf->buf_ptr >= bf->buf_end) {
363
+ if (bf->fd != -1) {
364
+ #if defined(PARSE_DEBUG)
365
+ len = 8;
366
+ #else
367
+ len = IO_BUF_SIZE;
368
+ #endif
369
+ len = read(bf->fd, bf->buffer, len);
370
+ if (len < 0)
371
+ len = 0;
372
+ } else {
373
+ len = 0;
374
+ }
375
+ total_bytes += len;
376
+ bf->buf_ptr = bf->buffer;
377
+ bf->buf_end = bf->buffer + len;
378
+ *bf->buf_end = CH_EOB;
379
+ }
380
+ if (bf->buf_ptr < bf->buf_end) {
381
+ return bf->buf_ptr[0];
382
+ } else {
383
+ bf->buf_ptr = bf->buf_end;
384
+ return CH_EOF;
385
+ }
386
+ }
387
+
388
+ /* return the current character, handling end of block if necessary
389
+ (but not stray) */
390
+ ST_FUNC int handle_eob(void)
391
+ {
392
+ return tcc_peekc_slow(file);
393
+ }
394
+
395
+ /* read next char from current input file and handle end of input buffer */
396
+ ST_INLN void inp(void)
397
+ {
398
+ ch = *(++(file->buf_ptr));
399
+ /* end of buffer/file handling */
400
+ if (ch == CH_EOB)
401
+ ch = handle_eob();
402
+ }
403
+
404
+ /* handle '\[\r]\n' */
405
+ static int handle_stray_noerror(void)
406
+ {
407
+ while (ch == '\\') {
408
+ inp();
409
+ if (ch == '\n') {
410
+ file->line_num++;
411
+ inp();
412
+ } else if (ch == '\r') {
413
+ inp();
414
+ if (ch != '\n')
415
+ goto fail;
416
+ file->line_num++;
417
+ inp();
418
+ } else {
419
+ fail:
420
+ return 1;
421
+ }
422
+ }
423
+ return 0;
424
+ }
425
+
426
+ static void handle_stray(void)
427
+ {
428
+ if (handle_stray_noerror())
429
+ tcc_error("stray '\\' in program");
430
+ }
431
+
432
+ /* skip the stray and handle the \\n case. Output an error if
433
+ incorrect char after the stray */
434
+ static int handle_stray1(uint8_t *p)
435
+ {
436
+ int c;
437
+
438
+ if (p >= file->buf_end) {
439
+ file->buf_ptr = p;
440
+ c = handle_eob();
441
+ p = file->buf_ptr;
442
+ if (c == '\\')
443
+ goto parse_stray;
444
+ } else {
445
+ parse_stray:
446
+ file->buf_ptr = p;
447
+ ch = *p;
448
+ handle_stray();
449
+ p = file->buf_ptr;
450
+ c = *p;
451
+ }
452
+ return c;
453
+ }
454
+
455
+ /* handle just the EOB case, but not stray */
456
+ #define PEEKC_EOB(c, p)\
457
+ {\
458
+ p++;\
459
+ c = *p;\
460
+ if (c == '\\') {\
461
+ file->buf_ptr = p;\
462
+ c = handle_eob();\
463
+ p = file->buf_ptr;\
464
+ }\
465
+ }
466
+
467
+ /* handle the complicated stray case */
468
+ #define PEEKC(c, p)\
469
+ {\
470
+ p++;\
471
+ c = *p;\
472
+ if (c == '\\') {\
473
+ c = handle_stray1(p);\
474
+ p = file->buf_ptr;\
475
+ }\
476
+ }
477
+
478
+ /* input with '\[\r]\n' handling. Note that this function cannot
479
+ handle other characters after '\', so you cannot call it inside
480
+ strings or comments */
481
+ ST_FUNC void minp(void)
482
+ {
483
+ inp();
484
+ if (ch == '\\')
485
+ handle_stray();
486
+ }
487
+
488
+
489
+ /* single line C++ comments */
490
+ static uint8_t *parse_line_comment(uint8_t *p)
491
+ {
492
+ int c;
493
+
494
+ p++;
495
+ for(;;) {
496
+ c = *p;
497
+ redo:
498
+ if (c == '\n' || c == CH_EOF) {
499
+ break;
500
+ } else if (c == '\\') {
501
+ file->buf_ptr = p;
502
+ c = handle_eob();
503
+ p = file->buf_ptr;
504
+ if (c == '\\') {
505
+ PEEKC_EOB(c, p);
506
+ if (c == '\n') {
507
+ file->line_num++;
508
+ PEEKC_EOB(c, p);
509
+ } else if (c == '\r') {
510
+ PEEKC_EOB(c, p);
511
+ if (c == '\n') {
512
+ file->line_num++;
513
+ PEEKC_EOB(c, p);
514
+ }
515
+ }
516
+ } else {
517
+ goto redo;
518
+ }
519
+ } else {
520
+ p++;
521
+ }
522
+ }
523
+ return p;
524
+ }
525
+
526
+ /* C comments */
527
+ ST_FUNC uint8_t *parse_comment(uint8_t *p)
528
+ {
529
+ int c;
530
+
531
+ p++;
532
+ for(;;) {
533
+ /* fast skip loop */
534
+ for(;;) {
535
+ c = *p;
536
+ if (c == '\n' || c == '*' || c == '\\')
537
+ break;
538
+ p++;
539
+ c = *p;
540
+ if (c == '\n' || c == '*' || c == '\\')
541
+ break;
542
+ p++;
543
+ }
544
+ /* now we can handle all the cases */
545
+ if (c == '\n') {
546
+ file->line_num++;
547
+ p++;
548
+ } else if (c == '*') {
549
+ p++;
550
+ for(;;) {
551
+ c = *p;
552
+ if (c == '*') {
553
+ p++;
554
+ } else if (c == '/') {
555
+ goto end_of_comment;
556
+ } else if (c == '\\') {
557
+ file->buf_ptr = p;
558
+ c = handle_eob();
559
+ p = file->buf_ptr;
560
+ if (c == '\\') {
561
+ /* skip '\[\r]\n', otherwise just skip the stray */
562
+ while (c == '\\') {
563
+ PEEKC_EOB(c, p);
564
+ if (c == '\n') {
565
+ file->line_num++;
566
+ PEEKC_EOB(c, p);
567
+ } else if (c == '\r') {
568
+ PEEKC_EOB(c, p);
569
+ if (c == '\n') {
570
+ file->line_num++;
571
+ PEEKC_EOB(c, p);
572
+ }
573
+ } else {
574
+ goto after_star;
575
+ }
576
+ }
577
+ }
578
+ } else {
579
+ break;
580
+ }
581
+ }
582
+ after_star: ;
583
+ } else {
584
+ /* stray, eob or eof */
585
+ file->buf_ptr = p;
586
+ c = handle_eob();
587
+ p = file->buf_ptr;
588
+ if (c == CH_EOF) {
589
+ tcc_error("unexpected end of file in comment");
590
+ } else if (c == '\\') {
591
+ p++;
592
+ }
593
+ }
594
+ }
595
+ end_of_comment:
596
+ p++;
597
+ return p;
598
+ }
599
+
600
+ #define cinp minp
601
+
602
+ static inline void skip_spaces(void)
603
+ {
604
+ while (is_space(ch))
605
+ cinp();
606
+ }
607
+
608
+ static inline int check_space(int t, int *spc)
609
+ {
610
+ if (is_space(t)) {
611
+ if (*spc)
612
+ return 1;
613
+ *spc = 1;
614
+ } else
615
+ *spc = 0;
616
+ return 0;
617
+ }
618
+
619
+ /* parse a string without interpreting escapes */
620
+ static uint8_t *parse_pp_string(uint8_t *p,
621
+ int sep, CString *str)
622
+ {
623
+ int c;
624
+ p++;
625
+ for(;;) {
626
+ c = *p;
627
+ if (c == sep) {
628
+ break;
629
+ } else if (c == '\\') {
630
+ file->buf_ptr = p;
631
+ c = handle_eob();
632
+ p = file->buf_ptr;
633
+ if (c == CH_EOF) {
634
+ unterminated_string:
635
+ /* XXX: indicate line number of start of string */
636
+ tcc_error("missing terminating %c character", sep);
637
+ } else if (c == '\\') {
638
+ /* escape : just skip \[\r]\n */
639
+ PEEKC_EOB(c, p);
640
+ if (c == '\n') {
641
+ file->line_num++;
642
+ p++;
643
+ } else if (c == '\r') {
644
+ PEEKC_EOB(c, p);
645
+ if (c != '\n')
646
+ expect("'\n' after '\r'");
647
+ file->line_num++;
648
+ p++;
649
+ } else if (c == CH_EOF) {
650
+ goto unterminated_string;
651
+ } else {
652
+ if (str) {
653
+ cstr_ccat(str, '\\');
654
+ cstr_ccat(str, c);
655
+ }
656
+ p++;
657
+ }
658
+ }
659
+ } else if (c == '\n') {
660
+ file->line_num++;
661
+ goto add_char;
662
+ } else if (c == '\r') {
663
+ PEEKC_EOB(c, p);
664
+ if (c != '\n') {
665
+ if (str)
666
+ cstr_ccat(str, '\r');
667
+ } else {
668
+ file->line_num++;
669
+ goto add_char;
670
+ }
671
+ } else {
672
+ add_char:
673
+ if (str)
674
+ cstr_ccat(str, c);
675
+ p++;
676
+ }
677
+ }
678
+ p++;
679
+ return p;
680
+ }
681
+
682
+ /* skip block of text until #else, #elif or #endif. skip also pairs of
683
+ #if/#endif */
684
+ static void preprocess_skip(void)
685
+ {
686
+ int a, start_of_line, c, in_warn_or_error;
687
+ uint8_t *p;
688
+
689
+ p = file->buf_ptr;
690
+ a = 0;
691
+ redo_start:
692
+ start_of_line = 1;
693
+ in_warn_or_error = 0;
694
+ for(;;) {
695
+ redo_no_start:
696
+ c = *p;
697
+ switch(c) {
698
+ case ' ':
699
+ case '\t':
700
+ case '\f':
701
+ case '\v':
702
+ case '\r':
703
+ p++;
704
+ goto redo_no_start;
705
+ case '\n':
706
+ file->line_num++;
707
+ p++;
708
+ goto redo_start;
709
+ case '\\':
710
+ file->buf_ptr = p;
711
+ c = handle_eob();
712
+ if (c == CH_EOF) {
713
+ expect("#endif");
714
+ } else if (c == '\\') {
715
+ ch = file->buf_ptr[0];
716
+ handle_stray_noerror();
717
+ }
718
+ p = file->buf_ptr;
719
+ goto redo_no_start;
720
+ /* skip strings */
721
+ case '\"':
722
+ case '\'':
723
+ if (in_warn_or_error)
724
+ goto _default;
725
+ p = parse_pp_string(p, c, NULL);
726
+ break;
727
+ /* skip comments */
728
+ case '/':
729
+ if (in_warn_or_error)
730
+ goto _default;
731
+ file->buf_ptr = p;
732
+ ch = *p;
733
+ minp();
734
+ p = file->buf_ptr;
735
+ if (ch == '*') {
736
+ p = parse_comment(p);
737
+ } else if (ch == '/') {
738
+ p = parse_line_comment(p);
739
+ }
740
+ break;
741
+ case '#':
742
+ p++;
743
+ if (start_of_line) {
744
+ file->buf_ptr = p;
745
+ next_nomacro();
746
+ p = file->buf_ptr;
747
+ if (a == 0 &&
748
+ (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
749
+ goto the_end;
750
+ if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
751
+ a++;
752
+ else if (tok == TOK_ENDIF)
753
+ a--;
754
+ else if( tok == TOK_ERROR || tok == TOK_WARNING)
755
+ in_warn_or_error = 1;
756
+ else if (tok == TOK_LINEFEED)
757
+ goto redo_start;
758
+ }
759
+ break;
760
+ _default:
761
+ default:
762
+ p++;
763
+ break;
764
+ }
765
+ start_of_line = 0;
766
+ }
767
+ the_end: ;
768
+ file->buf_ptr = p;
769
+ }
770
+
771
+ /* ParseState handling */
772
+
773
+ /* XXX: currently, no include file info is stored. Thus, we cannot display
774
+ accurate messages if the function or data definition spans multiple
775
+ files */
776
+
777
+ /* save current parse state in 's' */
778
+ ST_FUNC void save_parse_state(ParseState *s)
779
+ {
780
+ s->line_num = file->line_num;
781
+ s->macro_ptr = macro_ptr;
782
+ s->tok = tok;
783
+ s->tokc = tokc;
784
+ }
785
+
786
+ /* restore parse state from 's' */
787
+ ST_FUNC void restore_parse_state(ParseState *s)
788
+ {
789
+ file->line_num = s->line_num;
790
+ macro_ptr = s->macro_ptr;
791
+ tok = s->tok;
792
+ tokc = s->tokc;
793
+ }
794
+
795
+ /* return the number of additional 'ints' necessary to store the
796
+ token */
797
+ static inline int tok_ext_size(int t)
798
+ {
799
+ switch(t) {
800
+ /* 4 bytes */
801
+ case TOK_CINT:
802
+ case TOK_CUINT:
803
+ case TOK_CCHAR:
804
+ case TOK_LCHAR:
805
+ case TOK_CFLOAT:
806
+ case TOK_LINENUM:
807
+ return 1;
808
+ case TOK_STR:
809
+ case TOK_LSTR:
810
+ case TOK_PPNUM:
811
+ tcc_error("unsupported token");
812
+ return 1;
813
+ case TOK_CDOUBLE:
814
+ case TOK_CLLONG:
815
+ case TOK_CULLONG:
816
+ return 2;
817
+ case TOK_CLDOUBLE:
818
+ return LDOUBLE_SIZE / 4;
819
+ default:
820
+ return 0;
821
+ }
822
+ }
823
+
824
+ /* token string handling */
825
+
826
+ ST_INLN void tok_str_new(TokenString *s)
827
+ {
828
+ s->str = NULL;
829
+ s->len = 0;
830
+ s->allocated_len = 0;
831
+ s->last_line_num = -1;
832
+ }
833
+
834
+ ST_FUNC void tok_str_free(int *str)
835
+ {
836
+ tcc_free(str);
837
+ }
838
+
839
+ static int *tok_str_realloc(TokenString *s)
840
+ {
841
+ int *str, len;
842
+
843
+ if (s->allocated_len == 0) {
844
+ len = 8;
845
+ } else {
846
+ len = s->allocated_len * 2;
847
+ }
848
+ str = tcc_realloc(s->str, len * sizeof(int));
849
+ s->allocated_len = len;
850
+ s->str = str;
851
+ return str;
852
+ }
853
+
854
+ ST_FUNC void tok_str_add(TokenString *s, int t)
855
+ {
856
+ int len, *str;
857
+
858
+ len = s->len;
859
+ str = s->str;
860
+ if (len >= s->allocated_len)
861
+ str = tok_str_realloc(s);
862
+ str[len++] = t;
863
+ s->len = len;
864
+ }
865
+
866
+ static void tok_str_add2(TokenString *s, int t, CValue *cv)
867
+ {
868
+ int len, *str;
869
+
870
+ len = s->len;
871
+ str = s->str;
872
+
873
+ /* allocate space for worst case */
874
+ if (len + TOK_MAX_SIZE > s->allocated_len)
875
+ str = tok_str_realloc(s);
876
+ str[len++] = t;
877
+ switch(t) {
878
+ case TOK_CINT:
879
+ case TOK_CUINT:
880
+ case TOK_CCHAR:
881
+ case TOK_LCHAR:
882
+ case TOK_CFLOAT:
883
+ case TOK_LINENUM:
884
+ str[len++] = cv->tab[0];
885
+ break;
886
+ case TOK_PPNUM:
887
+ case TOK_STR:
888
+ case TOK_LSTR:
889
+ {
890
+ int nb_words;
891
+ CString *cstr;
892
+
893
+ nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
894
+ while ((len + nb_words) > s->allocated_len)
895
+ str = tok_str_realloc(s);
896
+ cstr = (CString *)(str + len);
897
+ cstr->data = NULL;
898
+ cstr->size = cv->cstr->size;
899
+ cstr->data_allocated = NULL;
900
+ cstr->size_allocated = cstr->size;
901
+ memcpy((char *)cstr + sizeof(CString),
902
+ cv->cstr->data, cstr->size);
903
+ len += nb_words;
904
+ }
905
+ break;
906
+ case TOK_CDOUBLE:
907
+ case TOK_CLLONG:
908
+ case TOK_CULLONG:
909
+ #if LDOUBLE_SIZE == 8
910
+ case TOK_CLDOUBLE:
911
+ #endif
912
+ str[len++] = cv->tab[0];
913
+ str[len++] = cv->tab[1];
914
+ break;
915
+ #if LDOUBLE_SIZE == 12
916
+ case TOK_CLDOUBLE:
917
+ str[len++] = cv->tab[0];
918
+ str[len++] = cv->tab[1];
919
+ str[len++] = cv->tab[2];
920
+ #elif LDOUBLE_SIZE == 16
921
+ case TOK_CLDOUBLE:
922
+ str[len++] = cv->tab[0];
923
+ str[len++] = cv->tab[1];
924
+ str[len++] = cv->tab[2];
925
+ str[len++] = cv->tab[3];
926
+ #elif LDOUBLE_SIZE != 8
927
+ #error add long double size support
928
+ #endif
929
+ break;
930
+ default:
931
+ break;
932
+ }
933
+ s->len = len;
934
+ }
935
+
936
+ /* add the current parse token in token string 's' */
937
+ ST_FUNC void tok_str_add_tok(TokenString *s)
938
+ {
939
+ CValue cval;
940
+
941
+ /* save line number info */
942
+ if (file->line_num != s->last_line_num) {
943
+ s->last_line_num = file->line_num;
944
+ cval.i = s->last_line_num;
945
+ tok_str_add2(s, TOK_LINENUM, &cval);
946
+ }
947
+ tok_str_add2(s, tok, &tokc);
948
+ }
949
+
950
+ /* get a token from an integer array and increment pointer
951
+ accordingly. we code it as a macro to avoid pointer aliasing. */
952
+ static inline void TOK_GET(int *t, const int **pp, CValue *cv)
953
+ {
954
+ const int *p = *pp;
955
+ int n, *tab;
956
+
957
+ tab = cv->tab;
958
+ switch(*t = *p++) {
959
+ case TOK_CINT:
960
+ case TOK_CUINT:
961
+ case TOK_CCHAR:
962
+ case TOK_LCHAR:
963
+ case TOK_CFLOAT:
964
+ case TOK_LINENUM:
965
+ tab[0] = *p++;
966
+ break;
967
+ case TOK_STR:
968
+ case TOK_LSTR:
969
+ case TOK_PPNUM:
970
+ cv->cstr = (CString *)p;
971
+ cv->cstr->data = (char *)p + sizeof(CString);
972
+ p += (sizeof(CString) + cv->cstr->size + 3) >> 2;
973
+ break;
974
+ case TOK_CDOUBLE:
975
+ case TOK_CLLONG:
976
+ case TOK_CULLONG:
977
+ n = 2;
978
+ goto copy;
979
+ case TOK_CLDOUBLE:
980
+ #if LDOUBLE_SIZE == 16
981
+ n = 4;
982
+ #elif LDOUBLE_SIZE == 12
983
+ n = 3;
984
+ #elif LDOUBLE_SIZE == 8
985
+ n = 2;
986
+ #else
987
+ # error add long double size support
988
+ #endif
989
+ copy:
990
+ do
991
+ *tab++ = *p++;
992
+ while (--n);
993
+ break;
994
+ default:
995
+ break;
996
+ }
997
+ *pp = p;
998
+ }
999
+
1000
+ static int macro_is_equal(const int *a, const int *b)
1001
+ {
1002
+ char buf[STRING_MAX_SIZE + 1];
1003
+ CValue cv;
1004
+ int t;
1005
+ while (*a && *b) {
1006
+ TOK_GET(&t, &a, &cv);
1007
+ pstrcpy(buf, sizeof buf, get_tok_str(t, &cv));
1008
+ TOK_GET(&t, &b, &cv);
1009
+ if (strcmp(buf, get_tok_str(t, &cv)))
1010
+ return 0;
1011
+ }
1012
+ return !(*a || *b);
1013
+ }
1014
+
1015
+ /* defines handling */
1016
+ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
1017
+ {
1018
+ Sym *s;
1019
+
1020
+ s = define_find(v);
1021
+ if (s && !macro_is_equal(s->d, str))
1022
+ tcc_warning("%s redefined", get_tok_str(v, NULL));
1023
+
1024
+ s = sym_push2(&define_stack, v, macro_type, 0);
1025
+ s->d = str;
1026
+ s->next = first_arg;
1027
+ table_ident[v - TOK_IDENT]->sym_define = s;
1028
+ }
1029
+
1030
+ /* undefined a define symbol. Its name is just set to zero */
1031
+ ST_FUNC void define_undef(Sym *s)
1032
+ {
1033
+ int v;
1034
+ v = s->v;
1035
+ if (v >= TOK_IDENT && v < tok_ident)
1036
+ table_ident[v - TOK_IDENT]->sym_define = NULL;
1037
+ s->v = 0;
1038
+ }
1039
+
1040
+ ST_INLN Sym *define_find(int v)
1041
+ {
1042
+ v -= TOK_IDENT;
1043
+ if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1044
+ return NULL;
1045
+ return table_ident[v]->sym_define;
1046
+ }
1047
+
1048
+ /* free define stack until top reaches 'b' */
1049
+ ST_FUNC void free_defines(Sym *b)
1050
+ {
1051
+ Sym *top, *top1;
1052
+ int v;
1053
+
1054
+ top = define_stack;
1055
+ while (top != b) {
1056
+ top1 = top->prev;
1057
+ /* do not free args or predefined defines */
1058
+ if (top->d)
1059
+ tok_str_free(top->d);
1060
+ v = top->v;
1061
+ if (v >= TOK_IDENT && v < tok_ident)
1062
+ table_ident[v - TOK_IDENT]->sym_define = NULL;
1063
+ sym_free(top);
1064
+ top = top1;
1065
+ }
1066
+ define_stack = b;
1067
+ }
1068
+
1069
+ /* label lookup */
1070
+ ST_FUNC Sym *label_find(int v)
1071
+ {
1072
+ v -= TOK_IDENT;
1073
+ if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1074
+ return NULL;
1075
+ return table_ident[v]->sym_label;
1076
+ }
1077
+
1078
+ ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
1079
+ {
1080
+ Sym *s, **ps;
1081
+ s = sym_push2(ptop, v, 0, 0);
1082
+ s->r = flags;
1083
+ ps = &table_ident[v - TOK_IDENT]->sym_label;
1084
+ if (ptop == &global_label_stack) {
1085
+ /* modify the top most local identifier, so that
1086
+ sym_identifier will point to 's' when popped */
1087
+ while (*ps != NULL)
1088
+ ps = &(*ps)->prev_tok;
1089
+ }
1090
+ s->prev_tok = *ps;
1091
+ *ps = s;
1092
+ return s;
1093
+ }
1094
+
1095
+ /* pop labels until element last is reached. Look if any labels are
1096
+ undefined. Define symbols if '&&label' was used. */
1097
+ ST_FUNC void label_pop(Sym **ptop, Sym *slast)
1098
+ {
1099
+ Sym *s, *s1;
1100
+ for(s = *ptop; s != slast; s = s1) {
1101
+ s1 = s->prev;
1102
+ if (s->r == LABEL_DECLARED) {
1103
+ tcc_warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
1104
+ } else if (s->r == LABEL_FORWARD) {
1105
+ tcc_error("label '%s' used but not defined",
1106
+ get_tok_str(s->v, NULL));
1107
+ } else {
1108
+ if (s->c) {
1109
+ /* define corresponding symbol. A size of
1110
+ 1 is put. */
1111
+ put_extern_sym(s, cur_text_section, s->jnext, 1);
1112
+ }
1113
+ }
1114
+ /* remove label */
1115
+ table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
1116
+ sym_free(s);
1117
+ }
1118
+ *ptop = slast;
1119
+ }
1120
+
1121
+ /* eval an expression for #if/#elif */
1122
+ static int expr_preprocess(void)
1123
+ {
1124
+ int c, t;
1125
+ TokenString str;
1126
+
1127
+ tok_str_new(&str);
1128
+ while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1129
+ next(); /* do macro subst */
1130
+ if (tok == TOK_DEFINED) {
1131
+ next_nomacro();
1132
+ t = tok;
1133
+ if (t == '(')
1134
+ next_nomacro();
1135
+ c = define_find(tok) != 0;
1136
+ if (t == '(')
1137
+ next_nomacro();
1138
+ tok = TOK_CINT;
1139
+ tokc.i = c;
1140
+ } else if (tok >= TOK_IDENT) {
1141
+ /* if undefined macro */
1142
+ tok = TOK_CINT;
1143
+ tokc.i = 0;
1144
+ }
1145
+ tok_str_add_tok(&str);
1146
+ }
1147
+ tok_str_add(&str, -1); /* simulate end of file */
1148
+ tok_str_add(&str, 0);
1149
+ /* now evaluate C constant expression */
1150
+ macro_ptr = str.str;
1151
+ next();
1152
+ c = expr_const();
1153
+ macro_ptr = NULL;
1154
+ tok_str_free(str.str);
1155
+ return c != 0;
1156
+ }
1157
+
1158
+ #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
1159
+ static void tok_print(int *str)
1160
+ {
1161
+ int t;
1162
+ CValue cval;
1163
+
1164
+ printf("<");
1165
+ while (1) {
1166
+ TOK_GET(&t, &str, &cval);
1167
+ if (!t)
1168
+ break;
1169
+ printf("%s", get_tok_str(t, &cval));
1170
+ }
1171
+ printf(">\n");
1172
+ }
1173
+ #endif
1174
+
1175
+ /* parse after #define */
1176
+ ST_FUNC void parse_define(void)
1177
+ {
1178
+ Sym *s, *first, **ps;
1179
+ int v, t, varg, is_vaargs, spc;
1180
+ TokenString str;
1181
+
1182
+ v = tok;
1183
+ if (v < TOK_IDENT)
1184
+ tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
1185
+ /* XXX: should check if same macro (ANSI) */
1186
+ first = NULL;
1187
+ t = MACRO_OBJ;
1188
+ /* '(' must be just after macro definition for MACRO_FUNC */
1189
+ next_nomacro_spc();
1190
+ if (tok == '(') {
1191
+ next_nomacro();
1192
+ ps = &first;
1193
+ while (tok != ')') {
1194
+ varg = tok;
1195
+ next_nomacro();
1196
+ is_vaargs = 0;
1197
+ if (varg == TOK_DOTS) {
1198
+ varg = TOK___VA_ARGS__;
1199
+ is_vaargs = 1;
1200
+ } else if (tok == TOK_DOTS && gnu_ext) {
1201
+ is_vaargs = 1;
1202
+ next_nomacro();
1203
+ }
1204
+ if (varg < TOK_IDENT)
1205
+ tcc_error("badly punctuated parameter list");
1206
+ s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
1207
+ *ps = s;
1208
+ ps = &s->next;
1209
+ if (tok != ',')
1210
+ break;
1211
+ next_nomacro();
1212
+ }
1213
+ if (tok == ')')
1214
+ next_nomacro_spc();
1215
+ t = MACRO_FUNC;
1216
+ }
1217
+ tok_str_new(&str);
1218
+ spc = 2;
1219
+ /* EOF testing necessary for '-D' handling */
1220
+ while (tok != TOK_LINEFEED && tok != TOK_EOF) {
1221
+ /* remove spaces around ## and after '#' */
1222
+ if (TOK_TWOSHARPS == tok) {
1223
+ if (1 == spc)
1224
+ --str.len;
1225
+ spc = 2;
1226
+ } else if ('#' == tok) {
1227
+ spc = 2;
1228
+ } else if (check_space(tok, &spc)) {
1229
+ goto skip;
1230
+ }
1231
+ tok_str_add2(&str, tok, &tokc);
1232
+ skip:
1233
+ next_nomacro_spc();
1234
+ }
1235
+ if (spc == 1)
1236
+ --str.len; /* remove trailing space */
1237
+ tok_str_add(&str, 0);
1238
+ #ifdef PP_DEBUG
1239
+ printf("define %s %d: ", get_tok_str(v, NULL), t);
1240
+ tok_print(str.str);
1241
+ #endif
1242
+ define_push(v, t, str.str, first);
1243
+ }
1244
+
1245
+ static inline int hash_cached_include(const char *filename)
1246
+ {
1247
+ const unsigned char *s;
1248
+ unsigned int h;
1249
+
1250
+ h = TOK_HASH_INIT;
1251
+ s = filename;
1252
+ while (*s) {
1253
+ h = TOK_HASH_FUNC(h, *s);
1254
+ s++;
1255
+ }
1256
+ h &= (CACHED_INCLUDES_HASH_SIZE - 1);
1257
+ return h;
1258
+ }
1259
+
1260
+ static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
1261
+ {
1262
+ CachedInclude *e;
1263
+ int i, h;
1264
+ h = hash_cached_include(filename);
1265
+ i = s1->cached_includes_hash[h];
1266
+ for(;;) {
1267
+ if (i == 0)
1268
+ break;
1269
+ e = s1->cached_includes[i - 1];
1270
+ if (0 == PATHCMP(e->filename, filename))
1271
+ return e;
1272
+ i = e->hash_next;
1273
+ }
1274
+ return NULL;
1275
+ }
1276
+
1277
+ static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro)
1278
+ {
1279
+ CachedInclude *e;
1280
+ int h;
1281
+
1282
+ if (search_cached_include(s1, filename))
1283
+ return;
1284
+ #ifdef INC_DEBUG
1285
+ printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
1286
+ #endif
1287
+ e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
1288
+ strcpy(e->filename, filename);
1289
+ e->ifndef_macro = ifndef_macro;
1290
+ dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
1291
+ /* add in hash table */
1292
+ h = hash_cached_include(filename);
1293
+ e->hash_next = s1->cached_includes_hash[h];
1294
+ s1->cached_includes_hash[h] = s1->nb_cached_includes;
1295
+ }
1296
+
1297
+ static void pragma_parse(TCCState *s1)
1298
+ {
1299
+ int val;
1300
+
1301
+ next();
1302
+ if (tok == TOK_pack) {
1303
+ /*
1304
+ This may be:
1305
+ #pragma pack(1) // set
1306
+ #pragma pack() // reset to default
1307
+ #pragma pack(push,1) // push & set
1308
+ #pragma pack(pop) // restore previous
1309
+ */
1310
+ next();
1311
+ skip('(');
1312
+ if (tok == TOK_ASM_pop) {
1313
+ next();
1314
+ if (s1->pack_stack_ptr <= s1->pack_stack) {
1315
+ stk_error:
1316
+ tcc_error("out of pack stack");
1317
+ }
1318
+ s1->pack_stack_ptr--;
1319
+ } else {
1320
+ val = 0;
1321
+ if (tok != ')') {
1322
+ if (tok == TOK_ASM_push) {
1323
+ next();
1324
+ if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
1325
+ goto stk_error;
1326
+ s1->pack_stack_ptr++;
1327
+ skip(',');
1328
+ }
1329
+ if (tok != TOK_CINT) {
1330
+ pack_error:
1331
+ tcc_error("invalid pack pragma");
1332
+ }
1333
+ val = tokc.i;
1334
+ if (val < 1 || val > 16 || (val & (val - 1)) != 0)
1335
+ goto pack_error;
1336
+ next();
1337
+ }
1338
+ *s1->pack_stack_ptr = val;
1339
+ skip(')');
1340
+ }
1341
+ }
1342
+ }
1343
+
1344
+ /* is_bof is true if first non space token at beginning of file */
1345
+ ST_FUNC void preprocess(int is_bof)
1346
+ {
1347
+ TCCState *s1 = tcc_state;
1348
+ int i, c, n, saved_parse_flags;
1349
+ char buf[1024], *q;
1350
+ Sym *s;
1351
+
1352
+ saved_parse_flags = parse_flags;
1353
+ parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
1354
+ PARSE_FLAG_LINEFEED;
1355
+ next_nomacro();
1356
+ redo:
1357
+ switch(tok) {
1358
+ case TOK_DEFINE:
1359
+ next_nomacro();
1360
+ parse_define();
1361
+ break;
1362
+ case TOK_UNDEF:
1363
+ next_nomacro();
1364
+ s = define_find(tok);
1365
+ /* undefine symbol by putting an invalid name */
1366
+ if (s)
1367
+ define_undef(s);
1368
+ break;
1369
+ case TOK_INCLUDE:
1370
+ case TOK_INCLUDE_NEXT:
1371
+ ch = file->buf_ptr[0];
1372
+ /* XXX: incorrect if comments : use next_nomacro with a special mode */
1373
+ skip_spaces();
1374
+ if (ch == '<') {
1375
+ c = '>';
1376
+ goto read_name;
1377
+ } else if (ch == '\"') {
1378
+ c = ch;
1379
+ read_name:
1380
+ inp();
1381
+ q = buf;
1382
+ while (ch != c && ch != '\n' && ch != CH_EOF) {
1383
+ if ((q - buf) < sizeof(buf) - 1)
1384
+ *q++ = ch;
1385
+ if (ch == '\\') {
1386
+ if (handle_stray_noerror() == 0)
1387
+ --q;
1388
+ } else
1389
+ inp();
1390
+ }
1391
+ *q = '\0';
1392
+ minp();
1393
+ #if 0
1394
+ /* eat all spaces and comments after include */
1395
+ /* XXX: slightly incorrect */
1396
+ while (ch1 != '\n' && ch1 != CH_EOF)
1397
+ inp();
1398
+ #endif
1399
+ } else {
1400
+ /* computed #include : either we have only strings or
1401
+ we have anything enclosed in '<>' */
1402
+ next();
1403
+ buf[0] = '\0';
1404
+ if (tok == TOK_STR) {
1405
+ while (tok != TOK_LINEFEED) {
1406
+ if (tok != TOK_STR) {
1407
+ include_syntax:
1408
+ tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
1409
+ }
1410
+ pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
1411
+ next();
1412
+ }
1413
+ c = '\"';
1414
+ } else {
1415
+ int len;
1416
+ while (tok != TOK_LINEFEED) {
1417
+ pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
1418
+ next();
1419
+ }
1420
+ len = strlen(buf);
1421
+ /* check syntax and remove '<>' */
1422
+ if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
1423
+ goto include_syntax;
1424
+ memmove(buf, buf + 1, len - 2);
1425
+ buf[len - 2] = '\0';
1426
+ c = '>';
1427
+ }
1428
+ }
1429
+
1430
+ if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
1431
+ tcc_error("#include recursion too deep");
1432
+ /* store current file in stack, but increment stack later below */
1433
+ *s1->include_stack_ptr = file;
1434
+
1435
+ n = s1->nb_include_paths + s1->nb_sysinclude_paths;
1436
+ for (i = -2; i < n; ++i) {
1437
+ char buf1[sizeof file->filename];
1438
+ CachedInclude *e;
1439
+ BufferedFile **f;
1440
+ const char *path;
1441
+
1442
+ if (i == -2) {
1443
+ /* check absolute include path */
1444
+ if (!IS_ABSPATH(buf))
1445
+ continue;
1446
+ buf1[0] = 0;
1447
+ i = n; /* force end loop */
1448
+
1449
+ } else if (i == -1) {
1450
+ /* search in current dir if "header.h" */
1451
+ if (c != '\"')
1452
+ continue;
1453
+ path = file->filename;
1454
+ pstrncpy(buf1, path, tcc_basename(path) - path);
1455
+
1456
+ } else {
1457
+ /* search in all the include paths */
1458
+ if (i < s1->nb_include_paths)
1459
+ path = s1->include_paths[i];
1460
+ else
1461
+ path = s1->sysinclude_paths[i - s1->nb_include_paths];
1462
+ pstrcpy(buf1, sizeof(buf1), path);
1463
+ pstrcat(buf1, sizeof(buf1), "/");
1464
+ }
1465
+
1466
+ pstrcat(buf1, sizeof(buf1), buf);
1467
+
1468
+ if (tok == TOK_INCLUDE_NEXT)
1469
+ for (f = s1->include_stack_ptr; f >= s1->include_stack; --f)
1470
+ if (0 == PATHCMP((*f)->filename, buf1)) {
1471
+ #ifdef INC_DEBUG
1472
+ printf("%s: #include_next skipping %s\n", file->filename, buf1);
1473
+ #endif
1474
+ goto include_trynext;
1475
+ }
1476
+
1477
+ e = search_cached_include(s1, buf1);
1478
+ if (e && define_find(e->ifndef_macro)) {
1479
+ /* no need to parse the include because the 'ifndef macro'
1480
+ is defined */
1481
+ #ifdef INC_DEBUG
1482
+ printf("%s: skipping cached %s\n", file->filename, buf1);
1483
+ #endif
1484
+ goto include_done;
1485
+ }
1486
+
1487
+ if (tcc_open(s1, buf1) < 0)
1488
+ include_trynext:
1489
+ continue;
1490
+
1491
+ #ifdef INC_DEBUG
1492
+ printf("%s: including %s\n", file->prev->filename, file->filename);
1493
+ #endif
1494
+ /* update target deps */
1495
+ dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
1496
+ tcc_strdup(buf1));
1497
+ /* push current file in stack */
1498
+ ++s1->include_stack_ptr;
1499
+ /* add include file debug info */
1500
+ if (s1->do_debug)
1501
+ put_stabs(file->filename, N_BINCL, 0, 0, 0);
1502
+ tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
1503
+ ch = file->buf_ptr[0];
1504
+ goto the_end;
1505
+ }
1506
+ tcc_error("include file '%s' not found", buf);
1507
+ include_done:
1508
+ break;
1509
+ case TOK_IFNDEF:
1510
+ c = 1;
1511
+ goto do_ifdef;
1512
+ case TOK_IF:
1513
+ c = expr_preprocess();
1514
+ goto do_if;
1515
+ case TOK_IFDEF:
1516
+ c = 0;
1517
+ do_ifdef:
1518
+ next_nomacro();
1519
+ if (tok < TOK_IDENT)
1520
+ tcc_error("invalid argument for '#if%sdef'", c ? "n" : "");
1521
+ if (is_bof) {
1522
+ if (c) {
1523
+ #ifdef INC_DEBUG
1524
+ printf("#ifndef %s\n", get_tok_str(tok, NULL));
1525
+ #endif
1526
+ file->ifndef_macro = tok;
1527
+ }
1528
+ }
1529
+ c = (define_find(tok) != 0) ^ c;
1530
+ do_if:
1531
+ if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
1532
+ tcc_error("memory full");
1533
+ *s1->ifdef_stack_ptr++ = c;
1534
+ goto test_skip;
1535
+ case TOK_ELSE:
1536
+ if (s1->ifdef_stack_ptr == s1->ifdef_stack)
1537
+ tcc_error("#else without matching #if");
1538
+ if (s1->ifdef_stack_ptr[-1] & 2)
1539
+ tcc_error("#else after #else");
1540
+ c = (s1->ifdef_stack_ptr[-1] ^= 3);
1541
+ goto test_else;
1542
+ case TOK_ELIF:
1543
+ if (s1->ifdef_stack_ptr == s1->ifdef_stack)
1544
+ tcc_error("#elif without matching #if");
1545
+ c = s1->ifdef_stack_ptr[-1];
1546
+ if (c > 1)
1547
+ tcc_error("#elif after #else");
1548
+ /* last #if/#elif expression was true: we skip */
1549
+ if (c == 1)
1550
+ goto skip;
1551
+ c = expr_preprocess();
1552
+ s1->ifdef_stack_ptr[-1] = c;
1553
+ test_else:
1554
+ if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1)
1555
+ file->ifndef_macro = 0;
1556
+ test_skip:
1557
+ if (!(c & 1)) {
1558
+ skip:
1559
+ preprocess_skip();
1560
+ is_bof = 0;
1561
+ goto redo;
1562
+ }
1563
+ break;
1564
+ case TOK_ENDIF:
1565
+ if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
1566
+ tcc_error("#endif without matching #if");
1567
+ s1->ifdef_stack_ptr--;
1568
+ /* '#ifndef macro' was at the start of file. Now we check if
1569
+ an '#endif' is exactly at the end of file */
1570
+ if (file->ifndef_macro &&
1571
+ s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
1572
+ file->ifndef_macro_saved = file->ifndef_macro;
1573
+ /* need to set to zero to avoid false matches if another
1574
+ #ifndef at middle of file */
1575
+ file->ifndef_macro = 0;
1576
+ while (tok != TOK_LINEFEED)
1577
+ next_nomacro();
1578
+ tok_flags |= TOK_FLAG_ENDIF;
1579
+ goto the_end;
1580
+ }
1581
+ break;
1582
+ case TOK_LINE:
1583
+ next();
1584
+ if (tok != TOK_CINT)
1585
+ tcc_error("#line");
1586
+ file->line_num = tokc.i - 1; /* the line number will be incremented after */
1587
+ next();
1588
+ if (tok != TOK_LINEFEED) {
1589
+ if (tok != TOK_STR)
1590
+ tcc_error("#line");
1591
+ pstrcpy(file->filename, sizeof(file->filename),
1592
+ (char *)tokc.cstr->data);
1593
+ }
1594
+ break;
1595
+ case TOK_ERROR:
1596
+ case TOK_WARNING:
1597
+ c = tok;
1598
+ ch = file->buf_ptr[0];
1599
+ skip_spaces();
1600
+ q = buf;
1601
+ while (ch != '\n' && ch != CH_EOF) {
1602
+ if ((q - buf) < sizeof(buf) - 1)
1603
+ *q++ = ch;
1604
+ if (ch == '\\') {
1605
+ if (handle_stray_noerror() == 0)
1606
+ --q;
1607
+ } else
1608
+ inp();
1609
+ }
1610
+ *q = '\0';
1611
+ if (c == TOK_ERROR)
1612
+ tcc_error("#error %s", buf);
1613
+ else
1614
+ tcc_warning("#warning %s", buf);
1615
+ break;
1616
+ case TOK_PRAGMA:
1617
+ pragma_parse(s1);
1618
+ break;
1619
+ default:
1620
+ if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_PPNUM) {
1621
+ /* '!' is ignored to allow C scripts. numbers are ignored
1622
+ to emulate cpp behaviour */
1623
+ } else {
1624
+ if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
1625
+ tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
1626
+ else {
1627
+ /* this is a gas line comment in an 'S' file. */
1628
+ file->buf_ptr = parse_line_comment(file->buf_ptr);
1629
+ goto the_end;
1630
+ }
1631
+ }
1632
+ break;
1633
+ }
1634
+ /* ignore other preprocess commands or #! for C scripts */
1635
+ while (tok != TOK_LINEFEED)
1636
+ next_nomacro();
1637
+ the_end:
1638
+ parse_flags = saved_parse_flags;
1639
+ }
1640
+
1641
+ /* evaluate escape codes in a string. */
1642
+ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
1643
+ {
1644
+ int c, n;
1645
+ const uint8_t *p;
1646
+
1647
+ p = buf;
1648
+ for(;;) {
1649
+ c = *p;
1650
+ if (c == '\0')
1651
+ break;
1652
+ if (c == '\\') {
1653
+ p++;
1654
+ /* escape */
1655
+ c = *p;
1656
+ switch(c) {
1657
+ case '0': case '1': case '2': case '3':
1658
+ case '4': case '5': case '6': case '7':
1659
+ /* at most three octal digits */
1660
+ n = c - '0';
1661
+ p++;
1662
+ c = *p;
1663
+ if (isoct(c)) {
1664
+ n = n * 8 + c - '0';
1665
+ p++;
1666
+ c = *p;
1667
+ if (isoct(c)) {
1668
+ n = n * 8 + c - '0';
1669
+ p++;
1670
+ }
1671
+ }
1672
+ c = n;
1673
+ goto add_char_nonext;
1674
+ case 'x':
1675
+ case 'u':
1676
+ case 'U':
1677
+ p++;
1678
+ n = 0;
1679
+ for(;;) {
1680
+ c = *p;
1681
+ if (c >= 'a' && c <= 'f')
1682
+ c = c - 'a' + 10;
1683
+ else if (c >= 'A' && c <= 'F')
1684
+ c = c - 'A' + 10;
1685
+ else if (isnum(c))
1686
+ c = c - '0';
1687
+ else
1688
+ break;
1689
+ n = n * 16 + c;
1690
+ p++;
1691
+ }
1692
+ c = n;
1693
+ goto add_char_nonext;
1694
+ case 'a':
1695
+ c = '\a';
1696
+ break;
1697
+ case 'b':
1698
+ c = '\b';
1699
+ break;
1700
+ case 'f':
1701
+ c = '\f';
1702
+ break;
1703
+ case 'n':
1704
+ c = '\n';
1705
+ break;
1706
+ case 'r':
1707
+ c = '\r';
1708
+ break;
1709
+ case 't':
1710
+ c = '\t';
1711
+ break;
1712
+ case 'v':
1713
+ c = '\v';
1714
+ break;
1715
+ case 'e':
1716
+ if (!gnu_ext)
1717
+ goto invalid_escape;
1718
+ c = 27;
1719
+ break;
1720
+ case '\'':
1721
+ case '\"':
1722
+ case '\\':
1723
+ case '?':
1724
+ break;
1725
+ default:
1726
+ invalid_escape:
1727
+ if (c >= '!' && c <= '~')
1728
+ tcc_warning("unknown escape sequence: \'\\%c\'", c);
1729
+ else
1730
+ tcc_warning("unknown escape sequence: \'\\x%x\'", c);
1731
+ break;
1732
+ }
1733
+ }
1734
+ p++;
1735
+ add_char_nonext:
1736
+ if (!is_long)
1737
+ cstr_ccat(outstr, c);
1738
+ else
1739
+ cstr_wccat(outstr, c);
1740
+ }
1741
+ /* add a trailing '\0' */
1742
+ if (!is_long)
1743
+ cstr_ccat(outstr, '\0');
1744
+ else
1745
+ cstr_wccat(outstr, '\0');
1746
+ }
1747
+
1748
+ /* we use 64 bit numbers */
1749
+ #define BN_SIZE 2
1750
+
1751
+ /* bn = (bn << shift) | or_val */
1752
+ static void bn_lshift(unsigned int *bn, int shift, int or_val)
1753
+ {
1754
+ int i;
1755
+ unsigned int v;
1756
+ for(i=0;i<BN_SIZE;i++) {
1757
+ v = bn[i];
1758
+ bn[i] = (v << shift) | or_val;
1759
+ or_val = v >> (32 - shift);
1760
+ }
1761
+ }
1762
+
1763
+ static void bn_zero(unsigned int *bn)
1764
+ {
1765
+ int i;
1766
+ for(i=0;i<BN_SIZE;i++) {
1767
+ bn[i] = 0;
1768
+ }
1769
+ }
1770
+
1771
+ /* parse number in null terminated string 'p' and return it in the
1772
+ current token */
1773
+ static void parse_number(const char *p)
1774
+ {
1775
+ int b, t, shift, frac_bits, s, exp_val, ch;
1776
+ char *q;
1777
+ unsigned int bn[BN_SIZE];
1778
+ double d;
1779
+
1780
+ /* number */
1781
+ q = token_buf;
1782
+ ch = *p++;
1783
+ t = ch;
1784
+ ch = *p++;
1785
+ *q++ = t;
1786
+ b = 10;
1787
+ if (t == '.') {
1788
+ goto float_frac_parse;
1789
+ } else if (t == '0') {
1790
+ if (ch == 'x' || ch == 'X') {
1791
+ q--;
1792
+ ch = *p++;
1793
+ b = 16;
1794
+ } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1795
+ q--;
1796
+ ch = *p++;
1797
+ b = 2;
1798
+ }
1799
+ }
1800
+ /* parse all digits. cannot check octal numbers at this stage
1801
+ because of floating point constants */
1802
+ while (1) {
1803
+ if (ch >= 'a' && ch <= 'f')
1804
+ t = ch - 'a' + 10;
1805
+ else if (ch >= 'A' && ch <= 'F')
1806
+ t = ch - 'A' + 10;
1807
+ else if (isnum(ch))
1808
+ t = ch - '0';
1809
+ else
1810
+ break;
1811
+ if (t >= b)
1812
+ break;
1813
+ if (q >= token_buf + STRING_MAX_SIZE) {
1814
+ num_too_long:
1815
+ tcc_error("number too long");
1816
+ }
1817
+ *q++ = ch;
1818
+ ch = *p++;
1819
+ }
1820
+ if (ch == '.' ||
1821
+ ((ch == 'e' || ch == 'E') && b == 10) ||
1822
+ ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1823
+ if (b != 10) {
1824
+ /* NOTE: strtox should support that for hexa numbers, but
1825
+ non ISOC99 libcs do not support it, so we prefer to do
1826
+ it by hand */
1827
+ /* hexadecimal or binary floats */
1828
+ /* XXX: handle overflows */
1829
+ *q = '\0';
1830
+ if (b == 16)
1831
+ shift = 4;
1832
+ else
1833
+ shift = 2;
1834
+ bn_zero(bn);
1835
+ q = token_buf;
1836
+ while (1) {
1837
+ t = *q++;
1838
+ if (t == '\0') {
1839
+ break;
1840
+ } else if (t >= 'a') {
1841
+ t = t - 'a' + 10;
1842
+ } else if (t >= 'A') {
1843
+ t = t - 'A' + 10;
1844
+ } else {
1845
+ t = t - '0';
1846
+ }
1847
+ bn_lshift(bn, shift, t);
1848
+ }
1849
+ frac_bits = 0;
1850
+ if (ch == '.') {
1851
+ ch = *p++;
1852
+ while (1) {
1853
+ t = ch;
1854
+ if (t >= 'a' && t <= 'f') {
1855
+ t = t - 'a' + 10;
1856
+ } else if (t >= 'A' && t <= 'F') {
1857
+ t = t - 'A' + 10;
1858
+ } else if (t >= '0' && t <= '9') {
1859
+ t = t - '0';
1860
+ } else {
1861
+ break;
1862
+ }
1863
+ if (t >= b)
1864
+ tcc_error("invalid digit");
1865
+ bn_lshift(bn, shift, t);
1866
+ frac_bits += shift;
1867
+ ch = *p++;
1868
+ }
1869
+ }
1870
+ if (ch != 'p' && ch != 'P')
1871
+ expect("exponent");
1872
+ ch = *p++;
1873
+ s = 1;
1874
+ exp_val = 0;
1875
+ if (ch == '+') {
1876
+ ch = *p++;
1877
+ } else if (ch == '-') {
1878
+ s = -1;
1879
+ ch = *p++;
1880
+ }
1881
+ if (ch < '0' || ch > '9')
1882
+ expect("exponent digits");
1883
+ while (ch >= '0' && ch <= '9') {
1884
+ exp_val = exp_val * 10 + ch - '0';
1885
+ ch = *p++;
1886
+ }
1887
+ exp_val = exp_val * s;
1888
+
1889
+ /* now we can generate the number */
1890
+ /* XXX: should patch directly float number */
1891
+ d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1892
+ d = ldexp(d, exp_val - frac_bits);
1893
+ t = toup(ch);
1894
+ if (t == 'F') {
1895
+ ch = *p++;
1896
+ tok = TOK_CFLOAT;
1897
+ /* float : should handle overflow */
1898
+ tokc.f = (float)d;
1899
+ } else if (t == 'L') {
1900
+ ch = *p++;
1901
+ #ifdef TCC_TARGET_PE
1902
+ tok = TOK_CDOUBLE;
1903
+ tokc.d = d;
1904
+ #else
1905
+ tok = TOK_CLDOUBLE;
1906
+ /* XXX: not large enough */
1907
+ tokc.ld = (long double)d;
1908
+ #endif
1909
+ } else {
1910
+ tok = TOK_CDOUBLE;
1911
+ tokc.d = d;
1912
+ }
1913
+ } else {
1914
+ /* decimal floats */
1915
+ if (ch == '.') {
1916
+ if (q >= token_buf + STRING_MAX_SIZE)
1917
+ goto num_too_long;
1918
+ *q++ = ch;
1919
+ ch = *p++;
1920
+ float_frac_parse:
1921
+ while (ch >= '0' && ch <= '9') {
1922
+ if (q >= token_buf + STRING_MAX_SIZE)
1923
+ goto num_too_long;
1924
+ *q++ = ch;
1925
+ ch = *p++;
1926
+ }
1927
+ }
1928
+ if (ch == 'e' || ch == 'E') {
1929
+ if (q >= token_buf + STRING_MAX_SIZE)
1930
+ goto num_too_long;
1931
+ *q++ = ch;
1932
+ ch = *p++;
1933
+ if (ch == '-' || ch == '+') {
1934
+ if (q >= token_buf + STRING_MAX_SIZE)
1935
+ goto num_too_long;
1936
+ *q++ = ch;
1937
+ ch = *p++;
1938
+ }
1939
+ if (ch < '0' || ch > '9')
1940
+ expect("exponent digits");
1941
+ while (ch >= '0' && ch <= '9') {
1942
+ if (q >= token_buf + STRING_MAX_SIZE)
1943
+ goto num_too_long;
1944
+ *q++ = ch;
1945
+ ch = *p++;
1946
+ }
1947
+ }
1948
+ *q = '\0';
1949
+ t = toup(ch);
1950
+ errno = 0;
1951
+ if (t == 'F') {
1952
+ ch = *p++;
1953
+ tok = TOK_CFLOAT;
1954
+ tokc.f = strtof(token_buf, NULL);
1955
+ } else if (t == 'L') {
1956
+ ch = *p++;
1957
+ #ifdef TCC_TARGET_PE
1958
+ tok = TOK_CDOUBLE;
1959
+ tokc.d = strtod(token_buf, NULL);
1960
+ #else
1961
+ tok = TOK_CLDOUBLE;
1962
+ tokc.ld = strtold(token_buf, NULL);
1963
+ #endif
1964
+ } else {
1965
+ tok = TOK_CDOUBLE;
1966
+ tokc.d = strtod(token_buf, NULL);
1967
+ }
1968
+ }
1969
+ } else {
1970
+ unsigned long long n, n1;
1971
+ int lcount, ucount;
1972
+
1973
+ /* integer number */
1974
+ *q = '\0';
1975
+ q = token_buf;
1976
+ if (b == 10 && *q == '0') {
1977
+ b = 8;
1978
+ q++;
1979
+ }
1980
+ n = 0;
1981
+ while(1) {
1982
+ t = *q++;
1983
+ /* no need for checks except for base 10 / 8 errors */
1984
+ if (t == '\0') {
1985
+ break;
1986
+ } else if (t >= 'a') {
1987
+ t = t - 'a' + 10;
1988
+ } else if (t >= 'A') {
1989
+ t = t - 'A' + 10;
1990
+ } else {
1991
+ t = t - '0';
1992
+ if (t >= b)
1993
+ tcc_error("invalid digit");
1994
+ }
1995
+ n1 = n;
1996
+ n = n * b + t;
1997
+ /* detect overflow */
1998
+ /* XXX: this test is not reliable */
1999
+ if (n < n1)
2000
+ tcc_error("integer constant overflow");
2001
+ }
2002
+
2003
+ /* XXX: not exactly ANSI compliant */
2004
+ if ((n & 0xffffffff00000000LL) != 0) {
2005
+ if ((n >> 63) != 0)
2006
+ tok = TOK_CULLONG;
2007
+ else
2008
+ tok = TOK_CLLONG;
2009
+ } else if (n > 0x7fffffff) {
2010
+ tok = TOK_CUINT;
2011
+ } else {
2012
+ tok = TOK_CINT;
2013
+ }
2014
+ lcount = 0;
2015
+ ucount = 0;
2016
+ for(;;) {
2017
+ t = toup(ch);
2018
+ if (t == 'L') {
2019
+ if (lcount >= 2)
2020
+ tcc_error("three 'l's in integer constant");
2021
+ lcount++;
2022
+ #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
2023
+ if (lcount == 2) {
2024
+ #endif
2025
+ if (tok == TOK_CINT)
2026
+ tok = TOK_CLLONG;
2027
+ else if (tok == TOK_CUINT)
2028
+ tok = TOK_CULLONG;
2029
+ #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
2030
+ }
2031
+ #endif
2032
+ ch = *p++;
2033
+ } else if (t == 'U') {
2034
+ if (ucount >= 1)
2035
+ tcc_error("two 'u's in integer constant");
2036
+ ucount++;
2037
+ if (tok == TOK_CINT)
2038
+ tok = TOK_CUINT;
2039
+ else if (tok == TOK_CLLONG)
2040
+ tok = TOK_CULLONG;
2041
+ ch = *p++;
2042
+ } else {
2043
+ break;
2044
+ }
2045
+ }
2046
+ if (tok == TOK_CINT || tok == TOK_CUINT)
2047
+ tokc.ui = n;
2048
+ else
2049
+ tokc.ull = n;
2050
+ }
2051
+ if (ch)
2052
+ tcc_error("invalid number\n");
2053
+ }
2054
+
2055
+
2056
+ #define PARSE2(c1, tok1, c2, tok2) \
2057
+ case c1: \
2058
+ PEEKC(c, p); \
2059
+ if (c == c2) { \
2060
+ p++; \
2061
+ tok = tok2; \
2062
+ } else { \
2063
+ tok = tok1; \
2064
+ } \
2065
+ break;
2066
+
2067
+ /* return next token without macro substitution */
2068
+ static inline void next_nomacro1(void)
2069
+ {
2070
+ int t, c, is_long;
2071
+ TokenSym *ts;
2072
+ uint8_t *p, *p1;
2073
+ unsigned int h;
2074
+
2075
+ p = file->buf_ptr;
2076
+ redo_no_start:
2077
+ c = *p;
2078
+ switch(c) {
2079
+ case ' ':
2080
+ case '\t':
2081
+ tok = c;
2082
+ p++;
2083
+ goto keep_tok_flags;
2084
+ case '\f':
2085
+ case '\v':
2086
+ case '\r':
2087
+ p++;
2088
+ goto redo_no_start;
2089
+ case '\\':
2090
+ /* first look if it is in fact an end of buffer */
2091
+ if (p >= file->buf_end) {
2092
+ file->buf_ptr = p;
2093
+ handle_eob();
2094
+ p = file->buf_ptr;
2095
+ if (p >= file->buf_end)
2096
+ goto parse_eof;
2097
+ else
2098
+ goto redo_no_start;
2099
+ } else {
2100
+ file->buf_ptr = p;
2101
+ ch = *p;
2102
+ handle_stray();
2103
+ p = file->buf_ptr;
2104
+ goto redo_no_start;
2105
+ }
2106
+ parse_eof:
2107
+ {
2108
+ TCCState *s1 = tcc_state;
2109
+ if ((parse_flags & PARSE_FLAG_LINEFEED)
2110
+ && !(tok_flags & TOK_FLAG_EOF)) {
2111
+ tok_flags |= TOK_FLAG_EOF;
2112
+ tok = TOK_LINEFEED;
2113
+ goto keep_tok_flags;
2114
+ } else if (!(parse_flags & PARSE_FLAG_PREPROCESS)) {
2115
+ tok = TOK_EOF;
2116
+ } else if (s1->ifdef_stack_ptr != file->ifdef_stack_ptr) {
2117
+ tcc_error("missing #endif");
2118
+ } else if (s1->include_stack_ptr == s1->include_stack) {
2119
+ /* no include left : end of file. */
2120
+ tok = TOK_EOF;
2121
+ } else {
2122
+ tok_flags &= ~TOK_FLAG_EOF;
2123
+ /* pop include file */
2124
+
2125
+ /* test if previous '#endif' was after a #ifdef at
2126
+ start of file */
2127
+ if (tok_flags & TOK_FLAG_ENDIF) {
2128
+ #ifdef INC_DEBUG
2129
+ printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
2130
+ #endif
2131
+ add_cached_include(s1, file->filename, file->ifndef_macro_saved);
2132
+ tok_flags &= ~TOK_FLAG_ENDIF;
2133
+ }
2134
+
2135
+ /* add end of include file debug info */
2136
+ if (tcc_state->do_debug) {
2137
+ put_stabd(N_EINCL, 0, 0);
2138
+ }
2139
+ /* pop include stack */
2140
+ tcc_close();
2141
+ s1->include_stack_ptr--;
2142
+ p = file->buf_ptr;
2143
+ goto redo_no_start;
2144
+ }
2145
+ }
2146
+ break;
2147
+
2148
+ case '\n':
2149
+ file->line_num++;
2150
+ tok_flags |= TOK_FLAG_BOL;
2151
+ p++;
2152
+ maybe_newline:
2153
+ if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
2154
+ goto redo_no_start;
2155
+ tok = TOK_LINEFEED;
2156
+ goto keep_tok_flags;
2157
+
2158
+ case '#':
2159
+ /* XXX: simplify */
2160
+ PEEKC(c, p);
2161
+ if ((tok_flags & TOK_FLAG_BOL) &&
2162
+ (parse_flags & PARSE_FLAG_PREPROCESS)) {
2163
+ file->buf_ptr = p;
2164
+ preprocess(tok_flags & TOK_FLAG_BOF);
2165
+ p = file->buf_ptr;
2166
+ goto maybe_newline;
2167
+ } else {
2168
+ if (c == '#') {
2169
+ p++;
2170
+ tok = TOK_TWOSHARPS;
2171
+ } else {
2172
+ if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
2173
+ p = parse_line_comment(p - 1);
2174
+ goto redo_no_start;
2175
+ } else {
2176
+ tok = '#';
2177
+ }
2178
+ }
2179
+ }
2180
+ break;
2181
+
2182
+ case 'a': case 'b': case 'c': case 'd':
2183
+ case 'e': case 'f': case 'g': case 'h':
2184
+ case 'i': case 'j': case 'k': case 'l':
2185
+ case 'm': case 'n': case 'o': case 'p':
2186
+ case 'q': case 'r': case 's': case 't':
2187
+ case 'u': case 'v': case 'w': case 'x':
2188
+ case 'y': case 'z':
2189
+ case 'A': case 'B': case 'C': case 'D':
2190
+ case 'E': case 'F': case 'G': case 'H':
2191
+ case 'I': case 'J': case 'K':
2192
+ case 'M': case 'N': case 'O': case 'P':
2193
+ case 'Q': case 'R': case 'S': case 'T':
2194
+ case 'U': case 'V': case 'W': case 'X':
2195
+ case 'Y': case 'Z':
2196
+ case '_':
2197
+ parse_ident_fast:
2198
+ p1 = p;
2199
+ h = TOK_HASH_INIT;
2200
+ h = TOK_HASH_FUNC(h, c);
2201
+ p++;
2202
+ for(;;) {
2203
+ c = *p;
2204
+ if (!isidnum_table[c-CH_EOF])
2205
+ break;
2206
+ h = TOK_HASH_FUNC(h, c);
2207
+ p++;
2208
+ }
2209
+ if (c != '\\') {
2210
+ TokenSym **pts;
2211
+ int len;
2212
+
2213
+ /* fast case : no stray found, so we have the full token
2214
+ and we have already hashed it */
2215
+ len = p - p1;
2216
+ h &= (TOK_HASH_SIZE - 1);
2217
+ pts = &hash_ident[h];
2218
+ for(;;) {
2219
+ ts = *pts;
2220
+ if (!ts)
2221
+ break;
2222
+ if (ts->len == len && !memcmp(ts->str, p1, len))
2223
+ goto token_found;
2224
+ pts = &(ts->hash_next);
2225
+ }
2226
+ ts = tok_alloc_new(pts, p1, len);
2227
+ token_found: ;
2228
+ } else {
2229
+ /* slower case */
2230
+ cstr_reset(&tokcstr);
2231
+
2232
+ while (p1 < p) {
2233
+ cstr_ccat(&tokcstr, *p1);
2234
+ p1++;
2235
+ }
2236
+ p--;
2237
+ PEEKC(c, p);
2238
+ parse_ident_slow:
2239
+ while (isidnum_table[c-CH_EOF]) {
2240
+ cstr_ccat(&tokcstr, c);
2241
+ PEEKC(c, p);
2242
+ }
2243
+ ts = tok_alloc(tokcstr.data, tokcstr.size);
2244
+ }
2245
+ tok = ts->tok;
2246
+ break;
2247
+ case 'L':
2248
+ t = p[1];
2249
+ if (t != '\\' && t != '\'' && t != '\"') {
2250
+ /* fast case */
2251
+ goto parse_ident_fast;
2252
+ } else {
2253
+ PEEKC(c, p);
2254
+ if (c == '\'' || c == '\"') {
2255
+ is_long = 1;
2256
+ goto str_const;
2257
+ } else {
2258
+ cstr_reset(&tokcstr);
2259
+ cstr_ccat(&tokcstr, 'L');
2260
+ goto parse_ident_slow;
2261
+ }
2262
+ }
2263
+ break;
2264
+ case '0': case '1': case '2': case '3':
2265
+ case '4': case '5': case '6': case '7':
2266
+ case '8': case '9':
2267
+
2268
+ cstr_reset(&tokcstr);
2269
+ /* after the first digit, accept digits, alpha, '.' or sign if
2270
+ prefixed by 'eEpP' */
2271
+ parse_num:
2272
+ for(;;) {
2273
+ t = c;
2274
+ cstr_ccat(&tokcstr, c);
2275
+ PEEKC(c, p);
2276
+ if (!(isnum(c) || isid(c) || c == '.' ||
2277
+ ((c == '+' || c == '-') &&
2278
+ (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
2279
+ break;
2280
+ }
2281
+ /* We add a trailing '\0' to ease parsing */
2282
+ cstr_ccat(&tokcstr, '\0');
2283
+ tokc.cstr = &tokcstr;
2284
+ tok = TOK_PPNUM;
2285
+ break;
2286
+ case '.':
2287
+ /* special dot handling because it can also start a number */
2288
+ PEEKC(c, p);
2289
+ if (isnum(c)) {
2290
+ cstr_reset(&tokcstr);
2291
+ cstr_ccat(&tokcstr, '.');
2292
+ goto parse_num;
2293
+ } else if (c == '.') {
2294
+ PEEKC(c, p);
2295
+ if (c != '.')
2296
+ expect("'.'");
2297
+ PEEKC(c, p);
2298
+ tok = TOK_DOTS;
2299
+ } else {
2300
+ tok = '.';
2301
+ }
2302
+ break;
2303
+ case '\'':
2304
+ case '\"':
2305
+ is_long = 0;
2306
+ str_const:
2307
+ {
2308
+ CString str;
2309
+ int sep;
2310
+
2311
+ sep = c;
2312
+
2313
+ /* parse the string */
2314
+ cstr_new(&str);
2315
+ p = parse_pp_string(p, sep, &str);
2316
+ cstr_ccat(&str, '\0');
2317
+
2318
+ /* eval the escape (should be done as TOK_PPNUM) */
2319
+ cstr_reset(&tokcstr);
2320
+ parse_escape_string(&tokcstr, str.data, is_long);
2321
+ cstr_free(&str);
2322
+
2323
+ if (sep == '\'') {
2324
+ int char_size;
2325
+ /* XXX: make it portable */
2326
+ if (!is_long)
2327
+ char_size = 1;
2328
+ else
2329
+ char_size = sizeof(nwchar_t);
2330
+ if (tokcstr.size <= char_size)
2331
+ tcc_error("empty character constant");
2332
+ if (tokcstr.size > 2 * char_size)
2333
+ tcc_warning("multi-character character constant");
2334
+ if (!is_long) {
2335
+ tokc.i = *(int8_t *)tokcstr.data;
2336
+ tok = TOK_CCHAR;
2337
+ } else {
2338
+ tokc.i = *(nwchar_t *)tokcstr.data;
2339
+ tok = TOK_LCHAR;
2340
+ }
2341
+ } else {
2342
+ tokc.cstr = &tokcstr;
2343
+ if (!is_long)
2344
+ tok = TOK_STR;
2345
+ else
2346
+ tok = TOK_LSTR;
2347
+ }
2348
+ }
2349
+ break;
2350
+
2351
+ case '<':
2352
+ PEEKC(c, p);
2353
+ if (c == '=') {
2354
+ p++;
2355
+ tok = TOK_LE;
2356
+ } else if (c == '<') {
2357
+ PEEKC(c, p);
2358
+ if (c == '=') {
2359
+ p++;
2360
+ tok = TOK_A_SHL;
2361
+ } else {
2362
+ tok = TOK_SHL;
2363
+ }
2364
+ } else {
2365
+ tok = TOK_LT;
2366
+ }
2367
+ break;
2368
+
2369
+ case '>':
2370
+ PEEKC(c, p);
2371
+ if (c == '=') {
2372
+ p++;
2373
+ tok = TOK_GE;
2374
+ } else if (c == '>') {
2375
+ PEEKC(c, p);
2376
+ if (c == '=') {
2377
+ p++;
2378
+ tok = TOK_A_SAR;
2379
+ } else {
2380
+ tok = TOK_SAR;
2381
+ }
2382
+ } else {
2383
+ tok = TOK_GT;
2384
+ }
2385
+ break;
2386
+
2387
+ case '&':
2388
+ PEEKC(c, p);
2389
+ if (c == '&') {
2390
+ p++;
2391
+ tok = TOK_LAND;
2392
+ } else if (c == '=') {
2393
+ p++;
2394
+ tok = TOK_A_AND;
2395
+ } else {
2396
+ tok = '&';
2397
+ }
2398
+ break;
2399
+
2400
+ case '|':
2401
+ PEEKC(c, p);
2402
+ if (c == '|') {
2403
+ p++;
2404
+ tok = TOK_LOR;
2405
+ } else if (c == '=') {
2406
+ p++;
2407
+ tok = TOK_A_OR;
2408
+ } else {
2409
+ tok = '|';
2410
+ }
2411
+ break;
2412
+
2413
+ case '+':
2414
+ PEEKC(c, p);
2415
+ if (c == '+') {
2416
+ p++;
2417
+ tok = TOK_INC;
2418
+ } else if (c == '=') {
2419
+ p++;
2420
+ tok = TOK_A_ADD;
2421
+ } else {
2422
+ tok = '+';
2423
+ }
2424
+ break;
2425
+
2426
+ case '-':
2427
+ PEEKC(c, p);
2428
+ if (c == '-') {
2429
+ p++;
2430
+ tok = TOK_DEC;
2431
+ } else if (c == '=') {
2432
+ p++;
2433
+ tok = TOK_A_SUB;
2434
+ } else if (c == '>') {
2435
+ p++;
2436
+ tok = TOK_ARROW;
2437
+ } else {
2438
+ tok = '-';
2439
+ }
2440
+ break;
2441
+
2442
+ PARSE2('!', '!', '=', TOK_NE)
2443
+ PARSE2('=', '=', '=', TOK_EQ)
2444
+ PARSE2('*', '*', '=', TOK_A_MUL)
2445
+ PARSE2('%', '%', '=', TOK_A_MOD)
2446
+ PARSE2('^', '^', '=', TOK_A_XOR)
2447
+
2448
+ /* comments or operator */
2449
+ case '/':
2450
+ PEEKC(c, p);
2451
+ if (c == '*') {
2452
+ p = parse_comment(p);
2453
+ /* comments replaced by a blank */
2454
+ tok = ' ';
2455
+ goto keep_tok_flags;
2456
+ } else if (c == '/') {
2457
+ p = parse_line_comment(p);
2458
+ tok = ' ';
2459
+ goto keep_tok_flags;
2460
+ } else if (c == '=') {
2461
+ p++;
2462
+ tok = TOK_A_DIV;
2463
+ } else {
2464
+ tok = '/';
2465
+ }
2466
+ break;
2467
+
2468
+ /* simple tokens */
2469
+ case '(':
2470
+ case ')':
2471
+ case '[':
2472
+ case ']':
2473
+ case '{':
2474
+ case '}':
2475
+ case ',':
2476
+ case ';':
2477
+ case ':':
2478
+ case '?':
2479
+ case '~':
2480
+ case '$': /* only used in assembler */
2481
+ case '@': /* dito */
2482
+ tok = c;
2483
+ p++;
2484
+ break;
2485
+ default:
2486
+ tcc_error("unrecognized character \\x%02x", c);
2487
+ break;
2488
+ }
2489
+ tok_flags = 0;
2490
+ keep_tok_flags:
2491
+ file->buf_ptr = p;
2492
+ #if defined(PARSE_DEBUG)
2493
+ printf("token = %s\n", get_tok_str(tok, &tokc));
2494
+ #endif
2495
+ }
2496
+
2497
+ /* return next token without macro substitution. Can read input from
2498
+ macro_ptr buffer */
2499
+ static void next_nomacro_spc(void)
2500
+ {
2501
+ if (macro_ptr) {
2502
+ redo:
2503
+ tok = *macro_ptr;
2504
+ if (tok) {
2505
+ TOK_GET(&tok, &macro_ptr, &tokc);
2506
+ if (tok == TOK_LINENUM) {
2507
+ file->line_num = tokc.i;
2508
+ goto redo;
2509
+ }
2510
+ }
2511
+ } else {
2512
+ next_nomacro1();
2513
+ }
2514
+ }
2515
+
2516
+ ST_FUNC void next_nomacro(void)
2517
+ {
2518
+ do {
2519
+ next_nomacro_spc();
2520
+ } while (is_space(tok));
2521
+ }
2522
+
2523
+ /* substitute args in macro_str and return allocated string */
2524
+ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
2525
+ {
2526
+ int last_tok, t, spc;
2527
+ const int *st;
2528
+ Sym *s;
2529
+ CValue cval;
2530
+ TokenString str;
2531
+ CString cstr;
2532
+
2533
+ tok_str_new(&str);
2534
+ last_tok = 0;
2535
+ while(1) {
2536
+ TOK_GET(&t, &macro_str, &cval);
2537
+ if (!t)
2538
+ break;
2539
+ if (t == '#') {
2540
+ /* stringize */
2541
+ TOK_GET(&t, &macro_str, &cval);
2542
+ if (!t)
2543
+ break;
2544
+ s = sym_find2(args, t);
2545
+ if (s) {
2546
+ cstr_new(&cstr);
2547
+ st = s->d;
2548
+ spc = 0;
2549
+ while (*st) {
2550
+ TOK_GET(&t, &st, &cval);
2551
+ if (!check_space(t, &spc))
2552
+ cstr_cat(&cstr, get_tok_str(t, &cval));
2553
+ }
2554
+ cstr.size -= spc;
2555
+ cstr_ccat(&cstr, '\0');
2556
+ #ifdef PP_DEBUG
2557
+ printf("stringize: %s\n", (char *)cstr.data);
2558
+ #endif
2559
+ /* add string */
2560
+ cval.cstr = &cstr;
2561
+ tok_str_add2(&str, TOK_STR, &cval);
2562
+ cstr_free(&cstr);
2563
+ } else {
2564
+ tok_str_add2(&str, t, &cval);
2565
+ }
2566
+ } else if (t >= TOK_IDENT) {
2567
+ s = sym_find2(args, t);
2568
+ if (s) {
2569
+ st = s->d;
2570
+ /* if '##' is present before or after, no arg substitution */
2571
+ if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2572
+ /* special case for var arg macros : ## eats the
2573
+ ',' if empty VA_ARGS variable. */
2574
+ /* XXX: test of the ',' is not 100%
2575
+ reliable. should fix it to avoid security
2576
+ problems */
2577
+ if (gnu_ext && s->type.t &&
2578
+ last_tok == TOK_TWOSHARPS &&
2579
+ str.len >= 2 && str.str[str.len - 2] == ',') {
2580
+ if (*st == 0) {
2581
+ /* suppress ',' '##' */
2582
+ str.len -= 2;
2583
+ } else {
2584
+ /* suppress '##' and add variable */
2585
+ str.len--;
2586
+ goto add_var;
2587
+ }
2588
+ } else {
2589
+ int t1;
2590
+ add_var:
2591
+ for(;;) {
2592
+ TOK_GET(&t1, &st, &cval);
2593
+ if (!t1)
2594
+ break;
2595
+ tok_str_add2(&str, t1, &cval);
2596
+ }
2597
+ }
2598
+ } else {
2599
+ /* NOTE: the stream cannot be read when macro
2600
+ substituing an argument */
2601
+ macro_subst(&str, nested_list, st, NULL);
2602
+ }
2603
+ } else {
2604
+ tok_str_add(&str, t);
2605
+ }
2606
+ } else {
2607
+ tok_str_add2(&str, t, &cval);
2608
+ }
2609
+ last_tok = t;
2610
+ }
2611
+ tok_str_add(&str, 0);
2612
+ return str.str;
2613
+ }
2614
+
2615
+ static char const ab_month_name[12][4] =
2616
+ {
2617
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
2618
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
2619
+ };
2620
+
2621
+ /* do macro substitution of current token with macro 's' and add
2622
+ result to (tok_str,tok_len). 'nested_list' is the list of all
2623
+ macros we got inside to avoid recursing. Return non zero if no
2624
+ substitution needs to be done */
2625
+ static int macro_subst_tok(TokenString *tok_str,
2626
+ Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
2627
+ {
2628
+ Sym *args, *sa, *sa1;
2629
+ int mstr_allocated, parlevel, *mstr, t, t1, spc;
2630
+ const int *p;
2631
+ TokenString str;
2632
+ char *cstrval;
2633
+ CValue cval;
2634
+ CString cstr;
2635
+ char buf[32];
2636
+
2637
+ /* if symbol is a macro, prepare substitution */
2638
+ /* special macros */
2639
+ if (tok == TOK___LINE__) {
2640
+ snprintf(buf, sizeof(buf), "%d", file->line_num);
2641
+ cstrval = buf;
2642
+ t1 = TOK_PPNUM;
2643
+ goto add_cstr1;
2644
+ } else if (tok == TOK___FILE__) {
2645
+ cstrval = file->filename;
2646
+ goto add_cstr;
2647
+ } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
2648
+ time_t ti;
2649
+ struct tm *tm;
2650
+
2651
+ time(&ti);
2652
+ tm = localtime(&ti);
2653
+ if (tok == TOK___DATE__) {
2654
+ snprintf(buf, sizeof(buf), "%s %2d %d",
2655
+ ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
2656
+ } else {
2657
+ snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
2658
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
2659
+ }
2660
+ cstrval = buf;
2661
+ add_cstr:
2662
+ t1 = TOK_STR;
2663
+ add_cstr1:
2664
+ cstr_new(&cstr);
2665
+ cstr_cat(&cstr, cstrval);
2666
+ cstr_ccat(&cstr, '\0');
2667
+ cval.cstr = &cstr;
2668
+ tok_str_add2(tok_str, t1, &cval);
2669
+ cstr_free(&cstr);
2670
+ } else {
2671
+ mstr = s->d;
2672
+ mstr_allocated = 0;
2673
+ if (s->type.t == MACRO_FUNC) {
2674
+ /* NOTE: we do not use next_nomacro to avoid eating the
2675
+ next token. XXX: find better solution */
2676
+ redo:
2677
+ if (macro_ptr) {
2678
+ p = macro_ptr;
2679
+ while (is_space(t = *p) || TOK_LINEFEED == t)
2680
+ ++p;
2681
+ if (t == 0 && can_read_stream) {
2682
+ /* end of macro stream: we must look at the token
2683
+ after in the file */
2684
+ struct macro_level *ml = *can_read_stream;
2685
+ macro_ptr = NULL;
2686
+ if (ml)
2687
+ {
2688
+ macro_ptr = ml->p;
2689
+ ml->p = NULL;
2690
+ *can_read_stream = ml -> prev;
2691
+ }
2692
+ /* also, end of scope for nested defined symbol */
2693
+ (*nested_list)->v = -1;
2694
+ goto redo;
2695
+ }
2696
+ } else {
2697
+ ch = file->buf_ptr[0];
2698
+ while (is_space(ch) || ch == '\n' || ch == '/')
2699
+ {
2700
+ if (ch == '/')
2701
+ {
2702
+ int c;
2703
+ uint8_t *p = file->buf_ptr;
2704
+ PEEKC(c, p);
2705
+ if (c == '*') {
2706
+ p = parse_comment(p);
2707
+ file->buf_ptr = p - 1;
2708
+ } else if (c == '/') {
2709
+ p = parse_line_comment(p);
2710
+ file->buf_ptr = p - 1;
2711
+ } else
2712
+ break;
2713
+ }
2714
+ cinp();
2715
+ }
2716
+ t = ch;
2717
+ }
2718
+ if (t != '(') /* no macro subst */
2719
+ return -1;
2720
+
2721
+ /* argument macro */
2722
+ next_nomacro();
2723
+ next_nomacro();
2724
+ args = NULL;
2725
+ sa = s->next;
2726
+ /* NOTE: empty args are allowed, except if no args */
2727
+ for(;;) {
2728
+ /* handle '()' case */
2729
+ if (!args && !sa && tok == ')')
2730
+ break;
2731
+ if (!sa)
2732
+ tcc_error("macro '%s' used with too many args",
2733
+ get_tok_str(s->v, 0));
2734
+ tok_str_new(&str);
2735
+ parlevel = spc = 0;
2736
+ /* NOTE: non zero sa->t indicates VA_ARGS */
2737
+ while ((parlevel > 0 ||
2738
+ (tok != ')' &&
2739
+ (tok != ',' || sa->type.t))) &&
2740
+ tok != -1) {
2741
+ if (tok == '(')
2742
+ parlevel++;
2743
+ else if (tok == ')')
2744
+ parlevel--;
2745
+ if (tok == TOK_LINEFEED)
2746
+ tok = ' ';
2747
+ if (!check_space(tok, &spc))
2748
+ tok_str_add2(&str, tok, &tokc);
2749
+ next_nomacro_spc();
2750
+ }
2751
+ str.len -= spc;
2752
+ tok_str_add(&str, 0);
2753
+ sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
2754
+ sa1->d = str.str;
2755
+ sa = sa->next;
2756
+ if (tok == ')') {
2757
+ /* special case for gcc var args: add an empty
2758
+ var arg argument if it is omitted */
2759
+ if (sa && sa->type.t && gnu_ext)
2760
+ continue;
2761
+ else
2762
+ break;
2763
+ }
2764
+ if (tok != ',')
2765
+ expect(",");
2766
+ next_nomacro();
2767
+ }
2768
+ if (sa) {
2769
+ tcc_error("macro '%s' used with too few args",
2770
+ get_tok_str(s->v, 0));
2771
+ }
2772
+
2773
+ /* now subst each arg */
2774
+ mstr = macro_arg_subst(nested_list, mstr, args);
2775
+ /* free memory */
2776
+ sa = args;
2777
+ while (sa) {
2778
+ sa1 = sa->prev;
2779
+ tok_str_free(sa->d);
2780
+ sym_free(sa);
2781
+ sa = sa1;
2782
+ }
2783
+ mstr_allocated = 1;
2784
+ }
2785
+ sym_push2(nested_list, s->v, 0, 0);
2786
+ macro_subst(tok_str, nested_list, mstr, can_read_stream);
2787
+ /* pop nested defined symbol */
2788
+ sa1 = *nested_list;
2789
+ *nested_list = sa1->prev;
2790
+ sym_free(sa1);
2791
+ if (mstr_allocated)
2792
+ tok_str_free(mstr);
2793
+ }
2794
+ return 0;
2795
+ }
2796
+
2797
+ /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
2798
+ return the resulting string (which must be freed). */
2799
+ static inline int *macro_twosharps(const int *macro_str)
2800
+ {
2801
+ const int *ptr;
2802
+ int t;
2803
+ TokenString macro_str1;
2804
+ CString cstr;
2805
+ int n, start_of_nosubsts;
2806
+
2807
+ /* we search the first '##' */
2808
+ for(ptr = macro_str;;) {
2809
+ CValue cval;
2810
+ TOK_GET(&t, &ptr, &cval);
2811
+ if (t == TOK_TWOSHARPS)
2812
+ break;
2813
+ /* nothing more to do if end of string */
2814
+ if (t == 0)
2815
+ return NULL;
2816
+ }
2817
+
2818
+ /* we saw '##', so we need more processing to handle it */
2819
+ start_of_nosubsts = -1;
2820
+ tok_str_new(&macro_str1);
2821
+ for(ptr = macro_str;;) {
2822
+ TOK_GET(&tok, &ptr, &tokc);
2823
+ if (tok == 0)
2824
+ break;
2825
+ if (tok == TOK_TWOSHARPS)
2826
+ continue;
2827
+ if (tok == TOK_NOSUBST && start_of_nosubsts < 0)
2828
+ start_of_nosubsts = macro_str1.len;
2829
+ while (*ptr == TOK_TWOSHARPS) {
2830
+ /* given 'a##b', remove nosubsts preceding 'a' */
2831
+ if (start_of_nosubsts >= 0)
2832
+ macro_str1.len = start_of_nosubsts;
2833
+ /* given 'a##b', skip '##' */
2834
+ t = *++ptr;
2835
+ /* given 'a##b', remove nosubsts preceding 'b' */
2836
+ while (t == TOK_NOSUBST)
2837
+ t = *++ptr;
2838
+ if (t && t != TOK_TWOSHARPS) {
2839
+ CValue cval;
2840
+ TOK_GET(&t, &ptr, &cval);
2841
+ /* We concatenate the two tokens */
2842
+ cstr_new(&cstr);
2843
+ cstr_cat(&cstr, get_tok_str(tok, &tokc));
2844
+ n = cstr.size;
2845
+ cstr_cat(&cstr, get_tok_str(t, &cval));
2846
+ cstr_ccat(&cstr, '\0');
2847
+
2848
+ tcc_open_bf(tcc_state, ":paste:", cstr.size);
2849
+ memcpy(file->buffer, cstr.data, cstr.size);
2850
+ for (;;) {
2851
+ next_nomacro1();
2852
+ if (0 == *file->buf_ptr)
2853
+ break;
2854
+ tok_str_add2(&macro_str1, tok, &tokc);
2855
+ tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid preprocessing token",
2856
+ n, cstr.data, (char*)cstr.data + n);
2857
+ }
2858
+ tcc_close();
2859
+ cstr_free(&cstr);
2860
+ }
2861
+ }
2862
+ if (tok != TOK_NOSUBST)
2863
+ start_of_nosubsts = -1;
2864
+ tok_str_add2(&macro_str1, tok, &tokc);
2865
+ }
2866
+ tok_str_add(&macro_str1, 0);
2867
+ return macro_str1.str;
2868
+ }
2869
+
2870
+
2871
+ /* do macro substitution of macro_str and add result to
2872
+ (tok_str,tok_len). 'nested_list' is the list of all macros we got
2873
+ inside to avoid recursing. */
2874
+ static void macro_subst(TokenString *tok_str, Sym **nested_list,
2875
+ const int *macro_str, struct macro_level ** can_read_stream)
2876
+ {
2877
+ Sym *s;
2878
+ int *macro_str1;
2879
+ const int *ptr;
2880
+ int t, ret, spc;
2881
+ CValue cval;
2882
+ struct macro_level ml;
2883
+ int force_blank;
2884
+
2885
+ /* first scan for '##' operator handling */
2886
+ ptr = macro_str;
2887
+ macro_str1 = macro_twosharps(ptr);
2888
+
2889
+ if (macro_str1)
2890
+ ptr = macro_str1;
2891
+ spc = 0;
2892
+ force_blank = 0;
2893
+
2894
+ while (1) {
2895
+ /* NOTE: ptr == NULL can only happen if tokens are read from
2896
+ file stream due to a macro function call */
2897
+ if (ptr == NULL)
2898
+ break;
2899
+ TOK_GET(&t, &ptr, &cval);
2900
+ if (t == 0)
2901
+ break;
2902
+ if (t == TOK_NOSUBST) {
2903
+ /* following token has already been subst'd. just copy it on */
2904
+ tok_str_add2(tok_str, TOK_NOSUBST, NULL);
2905
+ TOK_GET(&t, &ptr, &cval);
2906
+ goto no_subst;
2907
+ }
2908
+ s = define_find(t);
2909
+ if (s != NULL) {
2910
+ /* if nested substitution, do nothing */
2911
+ if (sym_find2(*nested_list, t)) {
2912
+ /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again */
2913
+ tok_str_add2(tok_str, TOK_NOSUBST, NULL);
2914
+ goto no_subst;
2915
+ }
2916
+ ml.p = macro_ptr;
2917
+ if (can_read_stream)
2918
+ ml.prev = *can_read_stream, *can_read_stream = &ml;
2919
+ macro_ptr = (int *)ptr;
2920
+ tok = t;
2921
+ ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
2922
+ ptr = (int *)macro_ptr;
2923
+ macro_ptr = ml.p;
2924
+ if (can_read_stream && *can_read_stream == &ml)
2925
+ *can_read_stream = ml.prev;
2926
+ if (ret != 0)
2927
+ goto no_subst;
2928
+ if (parse_flags & PARSE_FLAG_SPACES)
2929
+ force_blank = 1;
2930
+ } else {
2931
+ no_subst:
2932
+ if (force_blank) {
2933
+ tok_str_add(tok_str, ' ');
2934
+ spc = 1;
2935
+ force_blank = 0;
2936
+ }
2937
+ if (!check_space(t, &spc))
2938
+ tok_str_add2(tok_str, t, &cval);
2939
+ }
2940
+ }
2941
+ if (macro_str1)
2942
+ tok_str_free(macro_str1);
2943
+ }
2944
+
2945
+ /* return next token with macro substitution */
2946
+ ST_FUNC void next(void)
2947
+ {
2948
+ Sym *nested_list, *s;
2949
+ TokenString str;
2950
+ struct macro_level *ml;
2951
+
2952
+ redo:
2953
+ if (parse_flags & PARSE_FLAG_SPACES)
2954
+ next_nomacro_spc();
2955
+ else
2956
+ next_nomacro();
2957
+ if (!macro_ptr) {
2958
+ /* if not reading from macro substituted string, then try
2959
+ to substitute macros */
2960
+ if (tok >= TOK_IDENT &&
2961
+ (parse_flags & PARSE_FLAG_PREPROCESS)) {
2962
+ s = define_find(tok);
2963
+ if (s) {
2964
+ /* we have a macro: we try to substitute */
2965
+ tok_str_new(&str);
2966
+ nested_list = NULL;
2967
+ ml = NULL;
2968
+ if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
2969
+ /* substitution done, NOTE: maybe empty */
2970
+ tok_str_add(&str, 0);
2971
+ macro_ptr = str.str;
2972
+ macro_ptr_allocated = str.str;
2973
+ goto redo;
2974
+ }
2975
+ }
2976
+ }
2977
+ } else {
2978
+ if (tok == 0) {
2979
+ /* end of macro or end of unget buffer */
2980
+ if (unget_buffer_enabled) {
2981
+ macro_ptr = unget_saved_macro_ptr;
2982
+ unget_buffer_enabled = 0;
2983
+ } else {
2984
+ /* end of macro string: free it */
2985
+ tok_str_free(macro_ptr_allocated);
2986
+ macro_ptr_allocated = NULL;
2987
+ macro_ptr = NULL;
2988
+ }
2989
+ goto redo;
2990
+ } else if (tok == TOK_NOSUBST) {
2991
+ /* discard preprocessor's nosubst markers */
2992
+ goto redo;
2993
+ }
2994
+ }
2995
+
2996
+ /* convert preprocessor tokens into C tokens */
2997
+ if (tok == TOK_PPNUM &&
2998
+ (parse_flags & PARSE_FLAG_TOK_NUM)) {
2999
+ parse_number((char *)tokc.cstr->data);
3000
+ }
3001
+ }
3002
+
3003
+ /* push back current token and set current token to 'last_tok'. Only
3004
+ identifier case handled for labels. */
3005
+ ST_INLN void unget_tok(int last_tok)
3006
+ {
3007
+ int i, n;
3008
+ int *q;
3009
+ if (unget_buffer_enabled)
3010
+ {
3011
+ /* assert(macro_ptr == unget_saved_buffer + 1);
3012
+ assert(*macro_ptr == 0); */
3013
+ }
3014
+ else
3015
+ {
3016
+ unget_saved_macro_ptr = macro_ptr;
3017
+ unget_buffer_enabled = 1;
3018
+ }
3019
+ q = unget_saved_buffer;
3020
+ macro_ptr = q;
3021
+ *q++ = tok;
3022
+ n = tok_ext_size(tok) - 1;
3023
+ for(i=0;i<n;i++)
3024
+ *q++ = tokc.tab[i];
3025
+ *q = 0; /* end of token string */
3026
+ tok = last_tok;
3027
+ }
3028
+
3029
+
3030
+ /* better than nothing, but needs extension to handle '-E' option
3031
+ correctly too */
3032
+ ST_FUNC void preprocess_init(TCCState *s1)
3033
+ {
3034
+ s1->include_stack_ptr = s1->include_stack;
3035
+ /* XXX: move that before to avoid having to initialize
3036
+ file->ifdef_stack_ptr ? */
3037
+ s1->ifdef_stack_ptr = s1->ifdef_stack;
3038
+ file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
3039
+
3040
+ vtop = vstack - 1;
3041
+ s1->pack_stack[0] = 0;
3042
+ s1->pack_stack_ptr = s1->pack_stack;
3043
+ }
3044
+
3045
+ ST_FUNC void preprocess_new(void)
3046
+ {
3047
+ int i, c;
3048
+ const char *p, *r;
3049
+
3050
+ /* init isid table */
3051
+ for(i=CH_EOF;i<256;i++)
3052
+ isidnum_table[i-CH_EOF] = isid(i) || isnum(i);
3053
+
3054
+ /* add all tokens */
3055
+ table_ident = NULL;
3056
+ memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
3057
+
3058
+ tok_ident = TOK_IDENT;
3059
+ p = tcc_keywords;
3060
+ while (*p) {
3061
+ r = p;
3062
+ for(;;) {
3063
+ c = *r++;
3064
+ if (c == '\0')
3065
+ break;
3066
+ }
3067
+ tok_alloc(p, r - p - 1);
3068
+ p = r;
3069
+ }
3070
+ }
3071
+
3072
+ /* Preprocess the current file */
3073
+ ST_FUNC int tcc_preprocess(TCCState *s1)
3074
+ {
3075
+ Sym *define_start;
3076
+
3077
+ BufferedFile *file_ref, **iptr, **iptr_new;
3078
+ int token_seen, line_ref, d;
3079
+ const char *s;
3080
+
3081
+ preprocess_init(s1);
3082
+ define_start = define_stack;
3083
+ ch = file->buf_ptr[0];
3084
+ tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
3085
+ parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
3086
+ PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
3087
+ token_seen = 0;
3088
+ line_ref = 0;
3089
+ file_ref = NULL;
3090
+ iptr = s1->include_stack_ptr;
3091
+
3092
+ for (;;) {
3093
+ next();
3094
+ if (tok == TOK_EOF) {
3095
+ break;
3096
+ } else if (file != file_ref) {
3097
+ goto print_line;
3098
+ } else if (tok == TOK_LINEFEED) {
3099
+ if (!token_seen)
3100
+ continue;
3101
+ ++line_ref;
3102
+ token_seen = 0;
3103
+ } else if (!token_seen) {
3104
+ d = file->line_num - line_ref;
3105
+ if (file != file_ref || d < 0 || d >= 8) {
3106
+ print_line:
3107
+ iptr_new = s1->include_stack_ptr;
3108
+ s = iptr_new > iptr ? " 1"
3109
+ : iptr_new < iptr ? " 2"
3110
+ : iptr_new > s1->include_stack ? " 3"
3111
+ : ""
3112
+ ;
3113
+ iptr = iptr_new;
3114
+ fprintf(s1->ppfp, "# %d \"%s\"%s\n", file->line_num, file->filename, s);
3115
+ } else {
3116
+ while (d)
3117
+ fputs("\n", s1->ppfp), --d;
3118
+ }
3119
+ line_ref = (file_ref = file)->line_num;
3120
+ token_seen = tok != TOK_LINEFEED;
3121
+ if (!token_seen)
3122
+ continue;
3123
+ }
3124
+ fputs(get_tok_str(tok, &tokc), s1->ppfp);
3125
+ }
3126
+ free_defines(define_start);
3127
+ return 0;
3128
+ }