enclave 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 (739) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +182 -0
  3. data/Rakefile +30 -0
  4. data/ext/enclave/enclave.c +390 -0
  5. data/ext/enclave/extconf.rb +33 -0
  6. data/ext/enclave/mruby/Makefile +63 -0
  7. data/ext/enclave/mruby/Rakefile +102 -0
  8. data/ext/enclave/mruby/benchmark/bm_ao_render.rb +309 -0
  9. data/ext/enclave/mruby/benchmark/bm_app_lc_fizzbuzz.rb +51 -0
  10. data/ext/enclave/mruby/benchmark/bm_fib.rb +6 -0
  11. data/ext/enclave/mruby/benchmark/bm_mandel_term.rb +34 -0
  12. data/ext/enclave/mruby/benchmark/bm_so_lists.rb +49 -0
  13. data/ext/enclave/mruby/benchmark/bm_so_mandelbrot.rb +65 -0
  14. data/ext/enclave/mruby/benchmark/vm_dispatch_bench.c +197 -0
  15. data/ext/enclave/mruby/benchmark/vm_optimization_bench.rb +513 -0
  16. data/ext/enclave/mruby/build/host/include/mrbconf.h +230 -0
  17. data/ext/enclave/mruby/build/host/include/mruby/array.h +303 -0
  18. data/ext/enclave/mruby/build/host/include/mruby/boxing_nan.h +169 -0
  19. data/ext/enclave/mruby/build/host/include/mruby/boxing_no.h +59 -0
  20. data/ext/enclave/mruby/build/host/include/mruby/boxing_word.h +248 -0
  21. data/ext/enclave/mruby/build/host/include/mruby/class.h +157 -0
  22. data/ext/enclave/mruby/build/host/include/mruby/common.h +127 -0
  23. data/ext/enclave/mruby/build/host/include/mruby/compile.h +187 -0
  24. data/ext/enclave/mruby/build/host/include/mruby/data.h +76 -0
  25. data/ext/enclave/mruby/build/host/include/mruby/debug.h +75 -0
  26. data/ext/enclave/mruby/build/host/include/mruby/dump.h +159 -0
  27. data/ext/enclave/mruby/build/host/include/mruby/endian.h +44 -0
  28. data/ext/enclave/mruby/build/host/include/mruby/error.h +168 -0
  29. data/ext/enclave/mruby/build/host/include/mruby/gc.h +77 -0
  30. data/ext/enclave/mruby/build/host/include/mruby/hash.h +234 -0
  31. data/ext/enclave/mruby/build/host/include/mruby/internal.h +278 -0
  32. data/ext/enclave/mruby/build/host/include/mruby/irep.h +142 -0
  33. data/ext/enclave/mruby/build/host/include/mruby/istruct.h +50 -0
  34. data/ext/enclave/mruby/build/host/include/mruby/khash.h +455 -0
  35. data/ext/enclave/mruby/build/host/include/mruby/mempool.h +19 -0
  36. data/ext/enclave/mruby/build/host/include/mruby/numeric.h +174 -0
  37. data/ext/enclave/mruby/build/host/include/mruby/object.h +44 -0
  38. data/ext/enclave/mruby/build/host/include/mruby/opcode.h +73 -0
  39. data/ext/enclave/mruby/build/host/include/mruby/ops.h +133 -0
  40. data/ext/enclave/mruby/build/host/include/mruby/presym/id.h +895 -0
  41. data/ext/enclave/mruby/build/host/include/mruby/presym/scanning.h +82 -0
  42. data/ext/enclave/mruby/build/host/include/mruby/presym/table.h +1787 -0
  43. data/ext/enclave/mruby/build/host/include/mruby/presym.h +65 -0
  44. data/ext/enclave/mruby/build/host/include/mruby/proc.h +184 -0
  45. data/ext/enclave/mruby/build/host/include/mruby/range.h +77 -0
  46. data/ext/enclave/mruby/build/host/include/mruby/re.h +16 -0
  47. data/ext/enclave/mruby/build/host/include/mruby/string.h +428 -0
  48. data/ext/enclave/mruby/build/host/include/mruby/throw.h +81 -0
  49. data/ext/enclave/mruby/build/host/include/mruby/value.h +471 -0
  50. data/ext/enclave/mruby/build/host/include/mruby/variable.h +108 -0
  51. data/ext/enclave/mruby/build/host/include/mruby/version.h +143 -0
  52. data/ext/enclave/mruby/build/host/include/mruby.h +1632 -0
  53. data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/id.h +281 -0
  54. data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/table.h +559 -0
  55. data/ext/enclave/mruby/build/host/mrbgems/gem_init.c +164 -0
  56. data/ext/enclave/mruby/build/host/mrbgems/mruby-array-ext/gem_init.c +650 -0
  57. data/ext/enclave/mruby/build/host/mrbgems/mruby-binding/gem_init.c +21 -0
  58. data/ext/enclave/mruby/build/host/mrbgems/mruby-catch/gem_init.c +86 -0
  59. data/ext/enclave/mruby/build/host/mrbgems/mruby-class-ext/gem_init.c +21 -0
  60. data/ext/enclave/mruby/build/host/mrbgems/mruby-compar-ext/gem_init.c +99 -0
  61. data/ext/enclave/mruby/build/host/mrbgems/mruby-complex/gem_init.c +362 -0
  62. data/ext/enclave/mruby/build/host/mrbgems/mruby-data/gem_init.c +21 -0
  63. data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-chain/gem_init.c +229 -0
  64. data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-ext/gem_init.c +1420 -0
  65. data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-lazy/gem_init.c +602 -0
  66. data/ext/enclave/mruby/build/host/mrbgems/mruby-enumerator/gem_init.c +822 -0
  67. data/ext/enclave/mruby/build/host/mrbgems/mruby-eval/gem_init.c +21 -0
  68. data/ext/enclave/mruby/build/host/mrbgems/mruby-fiber/gem_init.c +21 -0
  69. data/ext/enclave/mruby/build/host/mrbgems/mruby-hash-ext/gem_init.c +591 -0
  70. data/ext/enclave/mruby/build/host/mrbgems/mruby-kernel-ext/gem_init.c +21 -0
  71. data/ext/enclave/mruby/build/host/mrbgems/mruby-math/gem_init.c +21 -0
  72. data/ext/enclave/mruby/build/host/mrbgems/mruby-metaprog/gem_init.c +21 -0
  73. data/ext/enclave/mruby/build/host/mrbgems/mruby-method/gem_init.c +153 -0
  74. data/ext/enclave/mruby/build/host/mrbgems/mruby-numeric-ext/gem_init.c +211 -0
  75. data/ext/enclave/mruby/build/host/mrbgems/mruby-object-ext/gem_init.c +94 -0
  76. data/ext/enclave/mruby/build/host/mrbgems/mruby-objectspace/gem_init.c +21 -0
  77. data/ext/enclave/mruby/build/host/mrbgems/mruby-pack/gem_init.c +21 -0
  78. data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-binding/gem_init.c +21 -0
  79. data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-ext/gem_init.c +237 -0
  80. data/ext/enclave/mruby/build/host/mrbgems/mruby-random/gem_init.c +21 -0
  81. data/ext/enclave/mruby/build/host/mrbgems/mruby-range-ext/gem_init.c +205 -0
  82. data/ext/enclave/mruby/build/host/mrbgems/mruby-rational/gem_init.c +147 -0
  83. data/ext/enclave/mruby/build/host/mrbgems/mruby-set/gem_init.c +487 -0
  84. data/ext/enclave/mruby/build/host/mrbgems/mruby-sprintf/gem_init.c +83 -0
  85. data/ext/enclave/mruby/build/host/mrbgems/mruby-string-ext/gem_init.c +220 -0
  86. data/ext/enclave/mruby/build/host/mrbgems/mruby-struct/gem_init.c +175 -0
  87. data/ext/enclave/mruby/build/host/mrbgems/mruby-symbol-ext/gem_init.c +153 -0
  88. data/ext/enclave/mruby/build/host/mrbgems/mruby-time/gem_init.c +21 -0
  89. data/ext/enclave/mruby/build/host/mrbgems/mruby-toplevel-ext/gem_init.c +78 -0
  90. data/ext/enclave/mruby/build/host/mrblib/mrblib.c +1758 -0
  91. data/ext/enclave/mruby/build_config/ArduinoDue.rb +72 -0
  92. data/ext/enclave/mruby/build_config/IntelEdison.rb +69 -0
  93. data/ext/enclave/mruby/build_config/IntelGalileo.rb +88 -0
  94. data/ext/enclave/mruby/build_config/RX630.rb +63 -0
  95. data/ext/enclave/mruby/build_config/android_arm64_v8a.rb +11 -0
  96. data/ext/enclave/mruby/build_config/android_armeabi_v7a_neon_hard.rb +13 -0
  97. data/ext/enclave/mruby/build_config/bench.rb +11 -0
  98. data/ext/enclave/mruby/build_config/boxing.rb +19 -0
  99. data/ext/enclave/mruby/build_config/chipKITMax32.rb +68 -0
  100. data/ext/enclave/mruby/build_config/ci/gcc-clang.rb +40 -0
  101. data/ext/enclave/mruby/build_config/ci/msvc.rb +20 -0
  102. data/ext/enclave/mruby/build_config/clang-asan.rb +11 -0
  103. data/ext/enclave/mruby/build_config/cosmopolitan.rb +86 -0
  104. data/ext/enclave/mruby/build_config/cross-32bit.rb +14 -0
  105. data/ext/enclave/mruby/build_config/cross-mingw-winetest.rb +90 -0
  106. data/ext/enclave/mruby/build_config/cross-mingw.rb +14 -0
  107. data/ext/enclave/mruby/build_config/default.rb +83 -0
  108. data/ext/enclave/mruby/build_config/dreamcast_shelf.rb +81 -0
  109. data/ext/enclave/mruby/build_config/emscripten-cxx.rb +12 -0
  110. data/ext/enclave/mruby/build_config/emscripten.rb +10 -0
  111. data/ext/enclave/mruby/build_config/gameboyadvance.rb +72 -0
  112. data/ext/enclave/mruby/build_config/helpers/wine_runner.rb +71 -0
  113. data/ext/enclave/mruby/build_config/host-cxx.rb +12 -0
  114. data/ext/enclave/mruby/build_config/host-debug.rb +20 -0
  115. data/ext/enclave/mruby/build_config/host-f32.rb +14 -0
  116. data/ext/enclave/mruby/build_config/host-gprof.rb +14 -0
  117. data/ext/enclave/mruby/build_config/host-m32.rb +15 -0
  118. data/ext/enclave/mruby/build_config/host-nofloat.rb +22 -0
  119. data/ext/enclave/mruby/build_config/host-shared.rb +36 -0
  120. data/ext/enclave/mruby/build_config/i586-pc-msdosdjgpp.rb +76 -0
  121. data/ext/enclave/mruby/build_config/luckfox_pico.rb +106 -0
  122. data/ext/enclave/mruby/build_config/milkv_duo.rb +106 -0
  123. data/ext/enclave/mruby/build_config/minimal.rb +4 -0
  124. data/ext/enclave/mruby/build_config/mrbc.rb +10 -0
  125. data/ext/enclave/mruby/build_config/nintendo_switch.rb +73 -0
  126. data/ext/enclave/mruby/build_config/nintendo_wii.rb +95 -0
  127. data/ext/enclave/mruby/build_config/no-float.rb +17 -0
  128. data/ext/enclave/mruby/build_config/playstationportable.rb +78 -0
  129. data/ext/enclave/mruby/build_config/serenity.rb +26 -0
  130. data/ext/enclave/mruby/build_config.rb +9 -0
  131. data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb +5 -0
  132. data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c +23 -0
  133. data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb +7 -0
  134. data/ext/enclave/mruby/examples/mrbgems/c_extension_example/src/example.c +23 -0
  135. data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.c +7 -0
  136. data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.rb +3 -0
  137. data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/src/example.c +77 -0
  138. data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/test/example.c +7 -0
  139. data/ext/enclave/mruby/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c +70 -0
  140. data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb +5 -0
  141. data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/test/example.rb +3 -0
  142. data/ext/enclave/mruby/include/mrbconf.h +230 -0
  143. data/ext/enclave/mruby/include/mruby/array.h +303 -0
  144. data/ext/enclave/mruby/include/mruby/boxing_nan.h +169 -0
  145. data/ext/enclave/mruby/include/mruby/boxing_no.h +59 -0
  146. data/ext/enclave/mruby/include/mruby/boxing_word.h +248 -0
  147. data/ext/enclave/mruby/include/mruby/class.h +157 -0
  148. data/ext/enclave/mruby/include/mruby/common.h +127 -0
  149. data/ext/enclave/mruby/include/mruby/compile.h +187 -0
  150. data/ext/enclave/mruby/include/mruby/data.h +76 -0
  151. data/ext/enclave/mruby/include/mruby/debug.h +75 -0
  152. data/ext/enclave/mruby/include/mruby/dump.h +159 -0
  153. data/ext/enclave/mruby/include/mruby/endian.h +44 -0
  154. data/ext/enclave/mruby/include/mruby/error.h +168 -0
  155. data/ext/enclave/mruby/include/mruby/gc.h +77 -0
  156. data/ext/enclave/mruby/include/mruby/hash.h +234 -0
  157. data/ext/enclave/mruby/include/mruby/internal.h +278 -0
  158. data/ext/enclave/mruby/include/mruby/irep.h +142 -0
  159. data/ext/enclave/mruby/include/mruby/istruct.h +50 -0
  160. data/ext/enclave/mruby/include/mruby/khash.h +455 -0
  161. data/ext/enclave/mruby/include/mruby/mempool.h +19 -0
  162. data/ext/enclave/mruby/include/mruby/numeric.h +174 -0
  163. data/ext/enclave/mruby/include/mruby/object.h +44 -0
  164. data/ext/enclave/mruby/include/mruby/opcode.h +73 -0
  165. data/ext/enclave/mruby/include/mruby/ops.h +133 -0
  166. data/ext/enclave/mruby/include/mruby/presym/scanning.h +82 -0
  167. data/ext/enclave/mruby/include/mruby/presym.h +65 -0
  168. data/ext/enclave/mruby/include/mruby/proc.h +184 -0
  169. data/ext/enclave/mruby/include/mruby/range.h +77 -0
  170. data/ext/enclave/mruby/include/mruby/re.h +16 -0
  171. data/ext/enclave/mruby/include/mruby/string.h +428 -0
  172. data/ext/enclave/mruby/include/mruby/throw.h +81 -0
  173. data/ext/enclave/mruby/include/mruby/value.h +471 -0
  174. data/ext/enclave/mruby/include/mruby/variable.h +108 -0
  175. data/ext/enclave/mruby/include/mruby/version.h +143 -0
  176. data/ext/enclave/mruby/include/mruby.h +1632 -0
  177. data/ext/enclave/mruby/lib/mruby/amalgam.rb +568 -0
  178. data/ext/enclave/mruby/lib/mruby/build/command.rb +383 -0
  179. data/ext/enclave/mruby/lib/mruby/build/load_gems.rb +383 -0
  180. data/ext/enclave/mruby/lib/mruby/build.rb +616 -0
  181. data/ext/enclave/mruby/lib/mruby/core_ext.rb +61 -0
  182. data/ext/enclave/mruby/lib/mruby/doc.rb +51 -0
  183. data/ext/enclave/mruby/lib/mruby/gem.rb +585 -0
  184. data/ext/enclave/mruby/lib/mruby/lockfile.rb +81 -0
  185. data/ext/enclave/mruby/lib/mruby/presym.rb +167 -0
  186. data/ext/enclave/mruby/lib/mruby/source.rb +32 -0
  187. data/ext/enclave/mruby/mrbgems/default-no-fpu.gembox +3 -0
  188. data/ext/enclave/mruby/mrbgems/default-no-stdio.gembox +4 -0
  189. data/ext/enclave/mruby/mrbgems/default.gembox +25 -0
  190. data/ext/enclave/mruby/mrbgems/full-core.gembox +6 -0
  191. data/ext/enclave/mruby/mrbgems/hal-posix-dir/mrbgem.rake +7 -0
  192. data/ext/enclave/mruby/mrbgems/hal-posix-dir/src/dir_hal.c +193 -0
  193. data/ext/enclave/mruby/mrbgems/hal-posix-io/mrbgem.rake +8 -0
  194. data/ext/enclave/mruby/mrbgems/hal-posix-io/src/io_hal.c +602 -0
  195. data/ext/enclave/mruby/mrbgems/hal-posix-socket/mrbgem.rake +8 -0
  196. data/ext/enclave/mruby/mrbgems/hal-posix-socket/src/socket_hal.c +158 -0
  197. data/ext/enclave/mruby/mrbgems/hal-posix-task/README.md +102 -0
  198. data/ext/enclave/mruby/mrbgems/hal-posix-task/mrbgem.rake +8 -0
  199. data/ext/enclave/mruby/mrbgems/hal-posix-task/src/task_hal.c +252 -0
  200. data/ext/enclave/mruby/mrbgems/hal-win-dir/mrbgem.rake +7 -0
  201. data/ext/enclave/mruby/mrbgems/hal-win-dir/src/dir_hal.c +249 -0
  202. data/ext/enclave/mruby/mrbgems/hal-win-io/mrbgem.rake +11 -0
  203. data/ext/enclave/mruby/mrbgems/hal-win-io/src/io_hal.c +646 -0
  204. data/ext/enclave/mruby/mrbgems/hal-win-socket/mrbgem.rake +12 -0
  205. data/ext/enclave/mruby/mrbgems/hal-win-socket/src/socket_hal.c +177 -0
  206. data/ext/enclave/mruby/mrbgems/hal-win-task/README.md +109 -0
  207. data/ext/enclave/mruby/mrbgems/hal-win-task/mrbgem.rake +11 -0
  208. data/ext/enclave/mruby/mrbgems/hal-win-task/src/task_hal.c +187 -0
  209. data/ext/enclave/mruby/mrbgems/math.gembox +12 -0
  210. data/ext/enclave/mruby/mrbgems/metaprog.gembox +21 -0
  211. data/ext/enclave/mruby/mrbgems/mruby-array-ext/README.md +87 -0
  212. data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrbgem.rake +5 -0
  213. data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrblib/array.rb +784 -0
  214. data/ext/enclave/mruby/mrbgems/mruby-array-ext/src/array.c +1583 -0
  215. data/ext/enclave/mruby/mrbgems/mruby-array-ext/test/array.rb +849 -0
  216. data/ext/enclave/mruby/mrbgems/mruby-benchmark/README.md +257 -0
  217. data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrbgem.rake +10 -0
  218. data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrblib/benchmark.rb +131 -0
  219. data/ext/enclave/mruby/mrbgems/mruby-benchmark/test/benchmark.rb +244 -0
  220. data/ext/enclave/mruby/mrbgems/mruby-bigint/README-fgmp.md +154 -0
  221. data/ext/enclave/mruby/mrbgems/mruby-bigint/README.md +44 -0
  222. data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.c +6335 -0
  223. data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.h +117 -0
  224. data/ext/enclave/mruby/mrbgems/mruby-bigint/mrbgem.rake +10 -0
  225. data/ext/enclave/mruby/mrbgems/mruby-bigint/test/bigint.rb +157 -0
  226. data/ext/enclave/mruby/mrbgems/mruby-bin-config/README.md +46 -0
  227. data/ext/enclave/mruby/mrbgems/mruby-bin-config/mrbgem.rake +49 -0
  228. data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config +46 -0
  229. data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config.bat +92 -0
  230. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/README.md +63 -0
  231. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb +283 -0
  232. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb +703 -0
  233. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake +10 -0
  234. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c +523 -0
  235. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h +26 -0
  236. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c +238 -0
  237. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h +14 -0
  238. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c +88 -0
  239. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h +13 -0
  240. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.c +34 -0
  241. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.h +14 -0
  242. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c +436 -0
  243. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c +509 -0
  244. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c +71 -0
  245. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c +64 -0
  246. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +768 -0
  247. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h +159 -0
  248. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h +24 -0
  249. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h +19 -0
  250. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/README.md +94 -0
  251. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb +58 -0
  252. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake +7 -0
  253. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +808 -0
  254. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.c +1035 -0
  255. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.h +185 -0
  256. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c +797 -0
  257. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h +132 -0
  258. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c +1118 -0
  259. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h +153 -0
  260. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.c +516 -0
  261. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.h +95 -0
  262. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.c +185 -0
  263. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.h +76 -0
  264. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.c +491 -0
  265. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.h +137 -0
  266. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/README.md +58 -0
  267. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/bintest/mrbc.rb +30 -0
  268. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake +15 -0
  269. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +362 -0
  270. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/stub.c +104 -0
  271. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/README.md +47 -0
  272. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb +178 -0
  273. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake +7 -0
  274. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +380 -0
  275. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/README.md +38 -0
  276. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/bintest/mruby_strip.rb +73 -0
  277. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/mrbgem.rake +7 -0
  278. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c +139 -0
  279. data/ext/enclave/mruby/mrbgems/mruby-binding/README.md +256 -0
  280. data/ext/enclave/mruby/mrbgems/mruby-binding/mrbgem.rake +7 -0
  281. data/ext/enclave/mruby/mrbgems/mruby-binding/src/binding.c +518 -0
  282. data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.c +14 -0
  283. data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.rb +64 -0
  284. data/ext/enclave/mruby/mrbgems/mruby-catch/README.md +94 -0
  285. data/ext/enclave/mruby/mrbgems/mruby-catch/mrbgem.rake +5 -0
  286. data/ext/enclave/mruby/mrbgems/mruby-catch/mrblib/catch.rb +29 -0
  287. data/ext/enclave/mruby/mrbgems/mruby-catch/src/catch.c +149 -0
  288. data/ext/enclave/mruby/mrbgems/mruby-catch/test/catch.rb +86 -0
  289. data/ext/enclave/mruby/mrbgems/mruby-class-ext/README.md +81 -0
  290. data/ext/enclave/mruby/mrbgems/mruby-class-ext/mrbgem.rake +5 -0
  291. data/ext/enclave/mruby/mrbgems/mruby-class-ext/src/class.c +377 -0
  292. data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/class.rb +46 -0
  293. data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/module.rb +109 -0
  294. data/ext/enclave/mruby/mrbgems/mruby-cmath/README.md +45 -0
  295. data/ext/enclave/mruby/mrbgems/mruby-cmath/mrbgem.rake +8 -0
  296. data/ext/enclave/mruby/mrbgems/mruby-cmath/src/cmath.c +426 -0
  297. data/ext/enclave/mruby/mrbgems/mruby-cmath/test/cmath.rb +41 -0
  298. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/README.md +65 -0
  299. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrbgem.rake +5 -0
  300. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrblib/compar.rb +75 -0
  301. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/test/compar.rb +21 -0
  302. data/ext/enclave/mruby/mrbgems/mruby-compiler/README.md +28 -0
  303. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/codegen.c +7316 -0
  304. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/keywords +52 -0
  305. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/lex.def +207 -0
  306. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/node.h +784 -0
  307. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/parse.y +8977 -0
  308. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/y.tab.c +16136 -0
  309. data/ext/enclave/mruby/mrbgems/mruby-compiler/mrbgem.rake +42 -0
  310. data/ext/enclave/mruby/mrbgems/mruby-complex/README.md +55 -0
  311. data/ext/enclave/mruby/mrbgems/mruby-complex/mrbgem.rake +7 -0
  312. data/ext/enclave/mruby/mrbgems/mruby-complex/mrblib/complex.rb +259 -0
  313. data/ext/enclave/mruby/mrbgems/mruby-complex/src/complex.c +597 -0
  314. data/ext/enclave/mruby/mrbgems/mruby-complex/test/complex.rb +174 -0
  315. data/ext/enclave/mruby/mrbgems/mruby-data/README.md +126 -0
  316. data/ext/enclave/mruby/mrbgems/mruby-data/mrbgem.rake +5 -0
  317. data/ext/enclave/mruby/mrbgems/mruby-data/src/data.c +550 -0
  318. data/ext/enclave/mruby/mrbgems/mruby-data/test/data.rb +76 -0
  319. data/ext/enclave/mruby/mrbgems/mruby-dir/README.md +53 -0
  320. data/ext/enclave/mruby/mrbgems/mruby-dir/include/dir_hal.h +79 -0
  321. data/ext/enclave/mruby/mrbgems/mruby-dir/mrbgem.rake +35 -0
  322. data/ext/enclave/mruby/mrbgems/mruby-dir/mrblib/dir.rb +124 -0
  323. data/ext/enclave/mruby/mrbgems/mruby-dir/src/dir.c +493 -0
  324. data/ext/enclave/mruby/mrbgems/mruby-dir/test/dir.rb +138 -0
  325. data/ext/enclave/mruby/mrbgems/mruby-dir/test/dirtest.c +125 -0
  326. data/ext/enclave/mruby/mrbgems/mruby-encoding/README.md +96 -0
  327. data/ext/enclave/mruby/mrbgems/mruby-encoding/mrbgem.rake +8 -0
  328. data/ext/enclave/mruby/mrbgems/mruby-encoding/src/encoding.c +128 -0
  329. data/ext/enclave/mruby/mrbgems/mruby-encoding/test/numeric.rb +27 -0
  330. data/ext/enclave/mruby/mrbgems/mruby-encoding/test/string.rb +30 -0
  331. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/README.md +80 -0
  332. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrbgem.rake +6 -0
  333. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrblib/chain.rb +149 -0
  334. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/test/enum_chain.rb +108 -0
  335. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/README.md +487 -0
  336. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrbgem.rake +5 -0
  337. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb +938 -0
  338. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/test/enum.rb +223 -0
  339. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/README.md +91 -0
  340. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake +7 -0
  341. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +363 -0
  342. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb +59 -0
  343. data/ext/enclave/mruby/mrbgems/mruby-enumerator/README.md +89 -0
  344. data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrbgem.rake +6 -0
  345. data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb +861 -0
  346. data/ext/enclave/mruby/mrbgems/mruby-enumerator/test/enumerator.rb +664 -0
  347. data/ext/enclave/mruby/mrbgems/mruby-errno/README.md +83 -0
  348. data/ext/enclave/mruby/mrbgems/mruby-errno/mrbgem.rake +5 -0
  349. data/ext/enclave/mruby/mrbgems/mruby-errno/mrblib/errno.rb +50 -0
  350. data/ext/enclave/mruby/mrbgems/mruby-errno/src/errno.c +335 -0
  351. data/ext/enclave/mruby/mrbgems/mruby-errno/src/gen.rb +18 -0
  352. data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors.def +156 -0
  353. data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors_def.cstub +780 -0
  354. data/ext/enclave/mruby/mrbgems/mruby-errno/test/errno.rb +57 -0
  355. data/ext/enclave/mruby/mrbgems/mruby-error/README.md +103 -0
  356. data/ext/enclave/mruby/mrbgems/mruby-error/mrbgem.rake +5 -0
  357. data/ext/enclave/mruby/mrbgems/mruby-error/src/exception.c +143 -0
  358. data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.c +60 -0
  359. data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.rb +55 -0
  360. data/ext/enclave/mruby/mrbgems/mruby-eval/README.md +26 -0
  361. data/ext/enclave/mruby/mrbgems/mruby-eval/mrbgem.rake +10 -0
  362. data/ext/enclave/mruby/mrbgems/mruby-eval/src/eval.c +437 -0
  363. data/ext/enclave/mruby/mrbgems/mruby-eval/test/binding.rb +81 -0
  364. data/ext/enclave/mruby/mrbgems/mruby-eval/test/eval.rb +185 -0
  365. data/ext/enclave/mruby/mrbgems/mruby-exit/mrbgem.rake +5 -0
  366. data/ext/enclave/mruby/mrbgems/mruby-exit/src/mruby_exit.c +83 -0
  367. data/ext/enclave/mruby/mrbgems/mruby-fiber/mrbgem.rake +5 -0
  368. data/ext/enclave/mruby/mrbgems/mruby-fiber/src/fiber.c +575 -0
  369. data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber.rb +210 -0
  370. data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber2.rb +155 -0
  371. data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fibertest.c +87 -0
  372. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/README.md +392 -0
  373. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrbgem.rake +6 -0
  374. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb +408 -0
  375. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/src/hash_ext.c +392 -0
  376. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/test/hash.rb +317 -0
  377. data/ext/enclave/mruby/mrbgems/mruby-io/README.md +198 -0
  378. data/ext/enclave/mruby/mrbgems/mruby-io/include/io_hal.h +451 -0
  379. data/ext/enclave/mruby/mrbgems/mruby-io/include/mruby/io.h +76 -0
  380. data/ext/enclave/mruby/mrbgems/mruby-io/mrbgem.rake +34 -0
  381. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file.rb +109 -0
  382. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file_constants.rb +24 -0
  383. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/io.rb +303 -0
  384. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/kernel.rb +175 -0
  385. data/ext/enclave/mruby/mrbgems/mruby-io/src/file.c +1192 -0
  386. data/ext/enclave/mruby/mrbgems/mruby-io/src/file_test.c +403 -0
  387. data/ext/enclave/mruby/mrbgems/mruby-io/src/io.c +2260 -0
  388. data/ext/enclave/mruby/mrbgems/mruby-io/src/mruby_io_gem.c +21 -0
  389. data/ext/enclave/mruby/mrbgems/mruby-io/test/file.rb +415 -0
  390. data/ext/enclave/mruby/mrbgems/mruby-io/test/file_test.rb +112 -0
  391. data/ext/enclave/mruby/mrbgems/mruby-io/test/io.rb +668 -0
  392. data/ext/enclave/mruby/mrbgems/mruby-io/test/mruby_io_test.c +293 -0
  393. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/README.md +165 -0
  394. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake +5 -0
  395. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/src/kernel.c +316 -0
  396. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb +134 -0
  397. data/ext/enclave/mruby/mrbgems/mruby-math/README.md +77 -0
  398. data/ext/enclave/mruby/mrbgems/mruby-math/mrbgem.rake +5 -0
  399. data/ext/enclave/mruby/mrbgems/mruby-math/src/math.c +753 -0
  400. data/ext/enclave/mruby/mrbgems/mruby-math/test/math.rb +201 -0
  401. data/ext/enclave/mruby/mrbgems/mruby-metaprog/README.md +123 -0
  402. data/ext/enclave/mruby/mrbgems/mruby-metaprog/mrbgem.rake +5 -0
  403. data/ext/enclave/mruby/mrbgems/mruby-metaprog/src/metaprog.c +739 -0
  404. data/ext/enclave/mruby/mrbgems/mruby-metaprog/test/metaprog.rb +465 -0
  405. data/ext/enclave/mruby/mrbgems/mruby-method/README.md +66 -0
  406. data/ext/enclave/mruby/mrbgems/mruby-method/mrbgem.rake +7 -0
  407. data/ext/enclave/mruby/mrbgems/mruby-method/mrblib/method.rb +73 -0
  408. data/ext/enclave/mruby/mrbgems/mruby-method/src/method.c +890 -0
  409. data/ext/enclave/mruby/mrbgems/mruby-method/test/method.rb +514 -0
  410. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/README.md +78 -0
  411. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake +5 -0
  412. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb +125 -0
  413. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c +527 -0
  414. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb +137 -0
  415. data/ext/enclave/mruby/mrbgems/mruby-object-ext/README.md +144 -0
  416. data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrbgem.rake +5 -0
  417. data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrblib/object.rb +33 -0
  418. data/ext/enclave/mruby/mrbgems/mruby-object-ext/src/object.c +128 -0
  419. data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/nil.rb +16 -0
  420. data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object.rb +67 -0
  421. data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object_ext.c +17 -0
  422. data/ext/enclave/mruby/mrbgems/mruby-objectspace/README.md +59 -0
  423. data/ext/enclave/mruby/mrbgems/mruby-objectspace/mrbgem.rake +5 -0
  424. data/ext/enclave/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c +188 -0
  425. data/ext/enclave/mruby/mrbgems/mruby-objectspace/test/objectspace.rb +60 -0
  426. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/README.md +75 -0
  427. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/mrbgem.rake +10 -0
  428. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/src/memsize.c +271 -0
  429. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/test/memsize.rb +63 -0
  430. data/ext/enclave/mruby/mrbgems/mruby-pack/README.md +140 -0
  431. data/ext/enclave/mruby/mrbgems/mruby-pack/mrbgem.rake +5 -0
  432. data/ext/enclave/mruby/mrbgems/mruby-pack/src/pack.c +2129 -0
  433. data/ext/enclave/mruby/mrbgems/mruby-pack/test/pack.rb +202 -0
  434. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/README.md +140 -0
  435. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/mrbgem.rake +10 -0
  436. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/src/proc_binding.c +76 -0
  437. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.c +14 -0
  438. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.rb +22 -0
  439. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/README.md +107 -0
  440. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrbgem.rake +5 -0
  441. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb +130 -0
  442. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/src/proc.c +267 -0
  443. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.c +62 -0
  444. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.rb +130 -0
  445. data/ext/enclave/mruby/mrbgems/mruby-random/README.md +272 -0
  446. data/ext/enclave/mruby/mrbgems/mruby-random/mrbgem.rake +5 -0
  447. data/ext/enclave/mruby/mrbgems/mruby-random/src/random.c +608 -0
  448. data/ext/enclave/mruby/mrbgems/mruby-random/test/random.rb +151 -0
  449. data/ext/enclave/mruby/mrbgems/mruby-range-ext/README.md +93 -0
  450. data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrbgem.rake +5 -0
  451. data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrblib/range.rb +155 -0
  452. data/ext/enclave/mruby/mrbgems/mruby-range-ext/src/range.c +236 -0
  453. data/ext/enclave/mruby/mrbgems/mruby-range-ext/test/range.rb +211 -0
  454. data/ext/enclave/mruby/mrbgems/mruby-rational/README.md +61 -0
  455. data/ext/enclave/mruby/mrbgems/mruby-rational/mrbgem.rake +7 -0
  456. data/ext/enclave/mruby/mrbgems/mruby-rational/mrblib/rational.rb +66 -0
  457. data/ext/enclave/mruby/mrbgems/mruby-rational/src/rational.c +1269 -0
  458. data/ext/enclave/mruby/mrbgems/mruby-rational/test/rational.rb +316 -0
  459. data/ext/enclave/mruby/mrbgems/mruby-set/LICENSE +24 -0
  460. data/ext/enclave/mruby/mrbgems/mruby-set/README.md +260 -0
  461. data/ext/enclave/mruby/mrbgems/mruby-set/mrbgem.rake +9 -0
  462. data/ext/enclave/mruby/mrbgems/mruby-set/mrblib/set.rb +325 -0
  463. data/ext/enclave/mruby/mrbgems/mruby-set/mruby-set.gem +6 -0
  464. data/ext/enclave/mruby/mrbgems/mruby-set/src/set.c +1535 -0
  465. data/ext/enclave/mruby/mrbgems/mruby-set/test/set.rb +764 -0
  466. data/ext/enclave/mruby/mrbgems/mruby-sleep/README.md +29 -0
  467. data/ext/enclave/mruby/mrbgems/mruby-sleep/example/sleep.rb +2 -0
  468. data/ext/enclave/mruby/mrbgems/mruby-sleep/mrbgem.rake +5 -0
  469. data/ext/enclave/mruby/mrbgems/mruby-sleep/src/sleep.c +187 -0
  470. data/ext/enclave/mruby/mrbgems/mruby-sleep/test/sleep_test.rb +29 -0
  471. data/ext/enclave/mruby/mrbgems/mruby-socket/README.md +56 -0
  472. data/ext/enclave/mruby/mrbgems/mruby-socket/include/socket_hal.h +83 -0
  473. data/ext/enclave/mruby/mrbgems/mruby-socket/mrbgem.rake +37 -0
  474. data/ext/enclave/mruby/mrbgems/mruby-socket/mrblib/socket.rb +1131 -0
  475. data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.cstub +480 -0
  476. data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.def +172 -0
  477. data/ext/enclave/mruby/mrbgems/mruby-socket/src/gen.rb +17 -0
  478. data/ext/enclave/mruby/mrbgems/mruby-socket/src/socket.c +1374 -0
  479. data/ext/enclave/mruby/mrbgems/mruby-socket/test/addrinfo.rb +91 -0
  480. data/ext/enclave/mruby/mrbgems/mruby-socket/test/basicsocket.rb +17 -0
  481. data/ext/enclave/mruby/mrbgems/mruby-socket/test/ipsocket.rb +44 -0
  482. data/ext/enclave/mruby/mrbgems/mruby-socket/test/socket.rb +38 -0
  483. data/ext/enclave/mruby/mrbgems/mruby-socket/test/sockettest.c +84 -0
  484. data/ext/enclave/mruby/mrbgems/mruby-socket/test/tcpsocket.rb +4 -0
  485. data/ext/enclave/mruby/mrbgems/mruby-socket/test/udpsocket.rb +16 -0
  486. data/ext/enclave/mruby/mrbgems/mruby-socket/test/unix.rb +130 -0
  487. data/ext/enclave/mruby/mrbgems/mruby-sprintf/README.md +235 -0
  488. data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrbgem.rake +5 -0
  489. data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrblib/string.rb +24 -0
  490. data/ext/enclave/mruby/mrbgems/mruby-sprintf/src/sprintf.c +1195 -0
  491. data/ext/enclave/mruby/mrbgems/mruby-sprintf/test/sprintf.rb +92 -0
  492. data/ext/enclave/mruby/mrbgems/mruby-strftime/README.md +140 -0
  493. data/ext/enclave/mruby/mrbgems/mruby-strftime/mrbgem.rake +7 -0
  494. data/ext/enclave/mruby/mrbgems/mruby-strftime/src/strftime.c +119 -0
  495. data/ext/enclave/mruby/mrbgems/mruby-strftime/test/strftime.rb +152 -0
  496. data/ext/enclave/mruby/mrbgems/mruby-string-ext/README.md +886 -0
  497. data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrbgem.rake +5 -0
  498. data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrblib/string.rb +166 -0
  499. data/ext/enclave/mruby/mrbgems/mruby-string-ext/src/string.c +2290 -0
  500. data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/numeric.rb +27 -0
  501. data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/range.rb +26 -0
  502. data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/string.rb +765 -0
  503. data/ext/enclave/mruby/mrbgems/mruby-struct/README.md +105 -0
  504. data/ext/enclave/mruby/mrbgems/mruby-struct/mrbgem.rake +5 -0
  505. data/ext/enclave/mruby/mrbgems/mruby-struct/mrblib/struct.rb +69 -0
  506. data/ext/enclave/mruby/mrbgems/mruby-struct/src/struct.c +812 -0
  507. data/ext/enclave/mruby/mrbgems/mruby-struct/test/struct.rb +303 -0
  508. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/README.md +50 -0
  509. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake +5 -0
  510. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb +72 -0
  511. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/src/symbol.c +79 -0
  512. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb +55 -0
  513. data/ext/enclave/mruby/mrbgems/mruby-task/README.md +770 -0
  514. data/ext/enclave/mruby/mrbgems/mruby-task/examples/inspection.rb +65 -0
  515. data/ext/enclave/mruby/mrbgems/mruby-task/examples/priority.rb +41 -0
  516. data/ext/enclave/mruby/mrbgems/mruby-task/examples/producer_consumer.rb +58 -0
  517. data/ext/enclave/mruby/mrbgems/mruby-task/examples/simple.rb +27 -0
  518. data/ext/enclave/mruby/mrbgems/mruby-task/examples/statistics.rb +59 -0
  519. data/ext/enclave/mruby/mrbgems/mruby-task/examples/suspend_resume.rb +47 -0
  520. data/ext/enclave/mruby/mrbgems/mruby-task/examples/task_pass.rb +21 -0
  521. data/ext/enclave/mruby/mrbgems/mruby-task/include/task.h +143 -0
  522. data/ext/enclave/mruby/mrbgems/mruby-task/include/task_hal.h +162 -0
  523. data/ext/enclave/mruby/mrbgems/mruby-task/mrbgem.rake +36 -0
  524. data/ext/enclave/mruby/mrbgems/mruby-task/src/task.c +1573 -0
  525. data/ext/enclave/mruby/mrbgems/mruby-task/test/task.rb +185 -0
  526. data/ext/enclave/mruby/mrbgems/mruby-test/README.md +7 -0
  527. data/ext/enclave/mruby/mrbgems/mruby-test/driver.c +315 -0
  528. data/ext/enclave/mruby/mrbgems/mruby-test/mrbgem.rake +173 -0
  529. data/ext/enclave/mruby/mrbgems/mruby-test/vformat.c +151 -0
  530. data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/mrbgem.rake +5 -0
  531. data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.c +92 -0
  532. data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.rb +118 -0
  533. data/ext/enclave/mruby/mrbgems/mruby-time/README.md +102 -0
  534. data/ext/enclave/mruby/mrbgems/mruby-time/include/mruby/time.h +27 -0
  535. data/ext/enclave/mruby/mrbgems/mruby-time/mrbgem.rake +5 -0
  536. data/ext/enclave/mruby/mrbgems/mruby-time/src/time.c +1739 -0
  537. data/ext/enclave/mruby/mrbgems/mruby-time/test/time.rb +313 -0
  538. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/README.md +32 -0
  539. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake +5 -0
  540. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb +24 -0
  541. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb +23 -0
  542. data/ext/enclave/mruby/mrbgems/stdlib-ext.gembox +21 -0
  543. data/ext/enclave/mruby/mrbgems/stdlib-io.gembox +15 -0
  544. data/ext/enclave/mruby/mrbgems/stdlib.gembox +63 -0
  545. data/ext/enclave/mruby/mrblib/10error.rb +23 -0
  546. data/ext/enclave/mruby/mrblib/array.rb +102 -0
  547. data/ext/enclave/mruby/mrblib/compar.rb +102 -0
  548. data/ext/enclave/mruby/mrblib/enum.rb +358 -0
  549. data/ext/enclave/mruby/mrblib/hash.rb +276 -0
  550. data/ext/enclave/mruby/mrblib/kernel.rb +45 -0
  551. data/ext/enclave/mruby/mrblib/numeric.rb +160 -0
  552. data/ext/enclave/mruby/mrblib/range.rb +98 -0
  553. data/ext/enclave/mruby/mrblib/string.rb +173 -0
  554. data/ext/enclave/mruby/mrblib/symbol.rb +8 -0
  555. data/ext/enclave/mruby/oss-fuzz/mruby_fuzzer.c +18 -0
  556. data/ext/enclave/mruby/oss-fuzz/proto_to_ruby.h +55 -0
  557. data/ext/enclave/mruby/src/allocf.c +37 -0
  558. data/ext/enclave/mruby/src/array.c +2302 -0
  559. data/ext/enclave/mruby/src/backtrace.c +294 -0
  560. data/ext/enclave/mruby/src/cdump.c +498 -0
  561. data/ext/enclave/mruby/src/class.c +4394 -0
  562. data/ext/enclave/mruby/src/codedump.c +693 -0
  563. data/ext/enclave/mruby/src/debug.c +290 -0
  564. data/ext/enclave/mruby/src/dump.c +998 -0
  565. data/ext/enclave/mruby/src/enum.c +30 -0
  566. data/ext/enclave/mruby/src/error.c +937 -0
  567. data/ext/enclave/mruby/src/etc.c +421 -0
  568. data/ext/enclave/mruby/src/fmt_fp.c +372 -0
  569. data/ext/enclave/mruby/src/gc.c +1610 -0
  570. data/ext/enclave/mruby/src/hash.c +2355 -0
  571. data/ext/enclave/mruby/src/init.c +50 -0
  572. data/ext/enclave/mruby/src/kernel.c +718 -0
  573. data/ext/enclave/mruby/src/load.c +760 -0
  574. data/ext/enclave/mruby/src/mempool.c +225 -0
  575. data/ext/enclave/mruby/src/numeric.c +2420 -0
  576. data/ext/enclave/mruby/src/numops.c +112 -0
  577. data/ext/enclave/mruby/src/object.c +883 -0
  578. data/ext/enclave/mruby/src/print.c +136 -0
  579. data/ext/enclave/mruby/src/proc.c +572 -0
  580. data/ext/enclave/mruby/src/range.c +597 -0
  581. data/ext/enclave/mruby/src/readfloat.c +228 -0
  582. data/ext/enclave/mruby/src/readint.c +27 -0
  583. data/ext/enclave/mruby/src/readnum.c +43 -0
  584. data/ext/enclave/mruby/src/state.c +247 -0
  585. data/ext/enclave/mruby/src/string.c +3577 -0
  586. data/ext/enclave/mruby/src/symbol.c +1023 -0
  587. data/ext/enclave/mruby/src/value_array.h +28 -0
  588. data/ext/enclave/mruby/src/variable.c +1475 -0
  589. data/ext/enclave/mruby/src/version.c +17 -0
  590. data/ext/enclave/mruby/src/vm.c +3696 -0
  591. data/ext/enclave/mruby/tasks/amalgam.rake +34 -0
  592. data/ext/enclave/mruby/tasks/benchmark.rake +93 -0
  593. data/ext/enclave/mruby/tasks/bin.rake +23 -0
  594. data/ext/enclave/mruby/tasks/core.rake +12 -0
  595. data/ext/enclave/mruby/tasks/doc.rake +118 -0
  596. data/ext/enclave/mruby/tasks/install.rake +40 -0
  597. data/ext/enclave/mruby/tasks/libmruby.rake +90 -0
  598. data/ext/enclave/mruby/tasks/mrbgems.rake +152 -0
  599. data/ext/enclave/mruby/tasks/mrblib.rake +29 -0
  600. data/ext/enclave/mruby/tasks/presym.rake +57 -0
  601. data/ext/enclave/mruby/tasks/test.rake +84 -0
  602. data/ext/enclave/mruby/tasks/toolchains/android.rake +228 -0
  603. data/ext/enclave/mruby/tasks/toolchains/clang.rake +8 -0
  604. data/ext/enclave/mruby/tasks/toolchains/emscripten.rake +57 -0
  605. data/ext/enclave/mruby/tasks/toolchains/gcc.rake +74 -0
  606. data/ext/enclave/mruby/tasks/toolchains/openwrt.rake +32 -0
  607. data/ext/enclave/mruby/tasks/toolchains/visualcpp.rake +48 -0
  608. data/ext/enclave/mruby/test/assert.rb +404 -0
  609. data/ext/enclave/mruby/test/bintest.rb +55 -0
  610. data/ext/enclave/mruby/test/t/argumenterror.rb +37 -0
  611. data/ext/enclave/mruby/test/t/array.rb +478 -0
  612. data/ext/enclave/mruby/test/t/basicobject.rb +10 -0
  613. data/ext/enclave/mruby/test/t/bs_block.rb +621 -0
  614. data/ext/enclave/mruby/test/t/bs_literal.rb +38 -0
  615. data/ext/enclave/mruby/test/t/class.rb +505 -0
  616. data/ext/enclave/mruby/test/t/codegen.rb +196 -0
  617. data/ext/enclave/mruby/test/t/comparable.rb +79 -0
  618. data/ext/enclave/mruby/test/t/ensure.rb +36 -0
  619. data/ext/enclave/mruby/test/t/enumerable.rb +134 -0
  620. data/ext/enclave/mruby/test/t/exception.rb +425 -0
  621. data/ext/enclave/mruby/test/t/false.rb +31 -0
  622. data/ext/enclave/mruby/test/t/float.rb +296 -0
  623. data/ext/enclave/mruby/test/t/gc.rb +45 -0
  624. data/ext/enclave/mruby/test/t/hash.rb +976 -0
  625. data/ext/enclave/mruby/test/t/indexerror.rb +6 -0
  626. data/ext/enclave/mruby/test/t/integer.rb +247 -0
  627. data/ext/enclave/mruby/test/t/iterations.rb +61 -0
  628. data/ext/enclave/mruby/test/t/kernel.rb +462 -0
  629. data/ext/enclave/mruby/test/t/lang.rb +74 -0
  630. data/ext/enclave/mruby/test/t/literals.rb +386 -0
  631. data/ext/enclave/mruby/test/t/localjumperror.rb +13 -0
  632. data/ext/enclave/mruby/test/t/methods.rb +138 -0
  633. data/ext/enclave/mruby/test/t/module.rb +931 -0
  634. data/ext/enclave/mruby/test/t/nameerror.rb +28 -0
  635. data/ext/enclave/mruby/test/t/nil.rb +39 -0
  636. data/ext/enclave/mruby/test/t/nomethoderror.rb +22 -0
  637. data/ext/enclave/mruby/test/t/numeric.rb +114 -0
  638. data/ext/enclave/mruby/test/t/object.rb +10 -0
  639. data/ext/enclave/mruby/test/t/proc.rb +198 -0
  640. data/ext/enclave/mruby/test/t/range.rb +194 -0
  641. data/ext/enclave/mruby/test/t/rangeerror.rb +6 -0
  642. data/ext/enclave/mruby/test/t/regexperror.rb +4 -0
  643. data/ext/enclave/mruby/test/t/runtimeerror.rb +6 -0
  644. data/ext/enclave/mruby/test/t/standarderror.rb +6 -0
  645. data/ext/enclave/mruby/test/t/string.rb +981 -0
  646. data/ext/enclave/mruby/test/t/superclass.rb +46 -0
  647. data/ext/enclave/mruby/test/t/symbol.rb +30 -0
  648. data/ext/enclave/mruby/test/t/syntax.rb +1296 -0
  649. data/ext/enclave/mruby/test/t/true.rb +31 -0
  650. data/ext/enclave/mruby/test/t/typeerror.rb +6 -0
  651. data/ext/enclave/mruby/test/t/unicode.rb +39 -0
  652. data/ext/enclave/mruby/test/t/vformat.rb +57 -0
  653. data/ext/enclave/mruby/tools/lrama/LEGAL.md +12 -0
  654. data/ext/enclave/mruby/tools/lrama/MIT +21 -0
  655. data/ext/enclave/mruby/tools/lrama/NEWS.md +696 -0
  656. data/ext/enclave/mruby/tools/lrama/exe/lrama +7 -0
  657. data/ext/enclave/mruby/tools/lrama/lib/lrama/bitmap.rb +34 -0
  658. data/ext/enclave/mruby/tools/lrama/lib/lrama/command.rb +68 -0
  659. data/ext/enclave/mruby/tools/lrama/lib/lrama/context.rb +499 -0
  660. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/derivation.rb +66 -0
  661. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/example.rb +129 -0
  662. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/path.rb +29 -0
  663. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/production_path.rb +19 -0
  664. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/start_path.rb +23 -0
  665. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/state_item.rb +8 -0
  666. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/transition_path.rb +19 -0
  667. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/triple.rb +23 -0
  668. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples.rb +298 -0
  669. data/ext/enclave/mruby/tools/lrama/lib/lrama/diagnostics.rb +36 -0
  670. data/ext/enclave/mruby/tools/lrama/lib/lrama/digraph.rb +83 -0
  671. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/auxiliary.rb +9 -0
  672. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/binding.rb +67 -0
  673. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/destructor_code.rb +42 -0
  674. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/initial_action_code.rb +36 -0
  675. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/no_reference_code.rb +30 -0
  676. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/printer_code.rb +42 -0
  677. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/rule_action.rb +92 -0
  678. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code.rb +53 -0
  679. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/counter.rb +17 -0
  680. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/destructor.rb +11 -0
  681. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/error_token.rb +11 -0
  682. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb +62 -0
  683. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb +40 -0
  684. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb +24 -0
  685. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule.rb +5 -0
  686. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/percent_code.rb +14 -0
  687. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/precedence.rb +13 -0
  688. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/printer.rb +11 -0
  689. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/reference.rb +16 -0
  690. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule.rb +75 -0
  691. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule_builder.rb +255 -0
  692. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/stdlib.y +122 -0
  693. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbol.rb +105 -0
  694. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols/resolver.rb +301 -0
  695. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols.rb +3 -0
  696. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/type.rb +20 -0
  697. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/union.rb +12 -0
  698. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar.rb +407 -0
  699. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar_validator.rb +37 -0
  700. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/grammar_file.rb +40 -0
  701. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/location.rb +115 -0
  702. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/char.rb +11 -0
  703. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/ident.rb +11 -0
  704. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/instantiate_rule.rb +30 -0
  705. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/tag.rb +16 -0
  706. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/user_code.rb +83 -0
  707. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token.rb +70 -0
  708. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer.rb +191 -0
  709. data/ext/enclave/mruby/tools/lrama/lib/lrama/logger.rb +21 -0
  710. data/ext/enclave/mruby/tools/lrama/lib/lrama/option_parser.rb +169 -0
  711. data/ext/enclave/mruby/tools/lrama/lib/lrama/options.rb +28 -0
  712. data/ext/enclave/mruby/tools/lrama/lib/lrama/output.rb +459 -0
  713. data/ext/enclave/mruby/tools/lrama/lib/lrama/parser.rb +2144 -0
  714. data/ext/enclave/mruby/tools/lrama/lib/lrama/report/duration.rb +27 -0
  715. data/ext/enclave/mruby/tools/lrama/lib/lrama/report/profile.rb +16 -0
  716. data/ext/enclave/mruby/tools/lrama/lib/lrama/report.rb +4 -0
  717. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce.rb +37 -0
  718. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce_reduce_conflict.rb +11 -0
  719. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/resolved_conflict.rb +31 -0
  720. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift.rb +15 -0
  721. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift_reduce_conflict.rb +11 -0
  722. data/ext/enclave/mruby/tools/lrama/lib/lrama/state.rb +433 -0
  723. data/ext/enclave/mruby/tools/lrama/lib/lrama/states/item.rb +91 -0
  724. data/ext/enclave/mruby/tools/lrama/lib/lrama/states.rb +595 -0
  725. data/ext/enclave/mruby/tools/lrama/lib/lrama/states_reporter.rb +362 -0
  726. data/ext/enclave/mruby/tools/lrama/lib/lrama/trace_reporter.rb +45 -0
  727. data/ext/enclave/mruby/tools/lrama/lib/lrama/version.rb +5 -0
  728. data/ext/enclave/mruby/tools/lrama/lib/lrama.rb +22 -0
  729. data/ext/enclave/mruby/tools/lrama/template/bison/_yacc.h +71 -0
  730. data/ext/enclave/mruby/tools/lrama/template/bison/yacc.c +2068 -0
  731. data/ext/enclave/mruby/tools/lrama/template/bison/yacc.h +40 -0
  732. data/ext/enclave/sandbox_build_config.rb +15 -0
  733. data/ext/enclave/sandbox_core.c +722 -0
  734. data/ext/enclave/sandbox_core.h +87 -0
  735. data/lib/enclave/result.rb +29 -0
  736. data/lib/enclave/tool.rb +38 -0
  737. data/lib/enclave/version.rb +3 -0
  738. data/lib/enclave.rb +73 -0
  739. metadata +819 -0
@@ -0,0 +1,2260 @@
1
+ /*
2
+ ** io.c - IO class
3
+ */
4
+
5
+ #include <mruby.h>
6
+ #include <mruby/array.h>
7
+ #include <mruby/class.h>
8
+ #include <mruby/data.h>
9
+ #include <mruby/hash.h>
10
+ #include <mruby/string.h>
11
+ #include <mruby/variable.h>
12
+ #include <mruby/io.h>
13
+ #include <mruby/error.h>
14
+ #include <mruby/internal.h>
15
+ #include <mruby/presym.h>
16
+ #include "io_hal.h"
17
+
18
+ #include <sys/types.h>
19
+ #include <sys/stat.h>
20
+
21
+ #if defined(_WIN32)
22
+ #include <winsock.h>
23
+ #include <io.h>
24
+ #include <basetsd.h>
25
+ #define open _open
26
+ #define close _close
27
+ #define dup _dup
28
+ #define dup2 _dup2
29
+ #define read _read
30
+ #define write _write
31
+ #define lseek _lseek
32
+ #define isatty _isatty
33
+ #define WEXITSTATUS(x) (x)
34
+ typedef int fsize_t;
35
+ typedef long ftime_t;
36
+ typedef long fsuseconds_t;
37
+ typedef int fmode_t;
38
+ typedef int fssize_t;
39
+
40
+ #ifndef O_TMPFILE
41
+ #define O_TMPFILE O_TEMPORARY
42
+ #endif
43
+
44
+ #else
45
+ #include <sys/wait.h>
46
+ #include <sys/time.h>
47
+ #include <unistd.h>
48
+ typedef size_t fsize_t;
49
+ typedef time_t ftime_t;
50
+ #ifdef __DJGPP__
51
+ typedef long fsuseconds_t;
52
+ #else
53
+ typedef suseconds_t fsuseconds_t;
54
+ #endif
55
+ typedef mode_t fmode_t;
56
+ typedef ssize_t fssize_t;
57
+ #endif
58
+
59
+ #ifdef _MSC_VER
60
+ typedef mrb_int pid_t;
61
+ #endif
62
+
63
+ #include <fcntl.h>
64
+
65
+ #include <errno.h>
66
+ #include <string.h>
67
+
68
+ #define OPEN_ACCESS_MODE_FLAGS (O_RDONLY | O_WRONLY | O_RDWR)
69
+ #define OPEN_RDONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDONLY))
70
+ #define OPEN_WRONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_WRONLY))
71
+ #define OPEN_RDWR_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDWR))
72
+ #define OPEN_READABLE_P(f) ((mrb_bool)(OPEN_RDONLY_P(f) || OPEN_RDWR_P(f)))
73
+ #define OPEN_WRITABLE_P(f) ((mrb_bool)(OPEN_WRONLY_P(f) || OPEN_RDWR_P(f)))
74
+
75
+ static void io_free(mrb_state *mrb, void *ptr);
76
+ struct mrb_data_type mrb_io_type = { "IO", io_free };
77
+
78
+
79
+ static int io_modestr_to_flags(mrb_state *mrb, const char *modestr);
80
+ static int io_mode_to_flags(mrb_state *mrb, mrb_value mode);
81
+ static void fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet);
82
+
83
+ static struct mrb_io*
84
+ io_get_open_fptr(mrb_state *mrb, mrb_value io)
85
+ {
86
+ struct mrb_io *fptr = (struct mrb_io*)mrb_data_get_ptr(mrb, io, &mrb_io_type);
87
+ if (fptr == NULL) {
88
+ mrb_raise(mrb, E_IO_ERROR, "uninitialized stream");
89
+ }
90
+ if (fptr->fd < 0) {
91
+ mrb_raise(mrb, E_IO_ERROR, "closed stream");
92
+ }
93
+ return fptr;
94
+ }
95
+
96
+ #if !defined(MRB_NO_IO_POPEN) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
97
+ # define MRB_NO_IO_POPEN 1
98
+ #endif
99
+
100
+ #ifndef MRB_NO_IO_POPEN
101
+ static void
102
+ io_set_process_status(mrb_state *mrb, pid_t pid, int status)
103
+ {
104
+ struct RClass *c_status = NULL;
105
+ mrb_value v;
106
+
107
+ if (mrb_class_defined_id(mrb, MRB_SYM(Process))) {
108
+ struct RClass *c_process = mrb_module_get_id(mrb, MRB_SYM(Process));
109
+ if (mrb_const_defined(mrb, mrb_obj_value(c_process), MRB_SYM(Status))) {
110
+ c_status = mrb_class_get_under_id(mrb, c_process, MRB_SYM(Status));
111
+ }
112
+ }
113
+ if (c_status != NULL) {
114
+ v = mrb_funcall_id(mrb, mrb_obj_value(c_status), MRB_SYM(new), 2, mrb_fixnum_value(pid), mrb_fixnum_value(status));
115
+ }
116
+ else {
117
+ v = mrb_fixnum_value(WEXITSTATUS(status));
118
+ }
119
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$?"), v);
120
+ }
121
+ #endif
122
+
123
+ static mrb_noreturn void
124
+ mode_error(mrb_state *mrb, const char *mode)
125
+ {
126
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode);
127
+ }
128
+
129
+ static int
130
+ io_modestr_to_flags(mrb_state *mrb, const char *mode)
131
+ {
132
+ int flags;
133
+ const char *m = mode;
134
+
135
+ switch (*m++) {
136
+ case 'r':
137
+ flags = O_RDONLY;
138
+ break;
139
+ case 'w':
140
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
141
+ break;
142
+ case 'a':
143
+ flags = O_WRONLY | O_CREAT | O_APPEND;
144
+ break;
145
+ default:
146
+ mode_error(mrb, mode);
147
+ }
148
+
149
+ while (*m) {
150
+ switch (*m++) {
151
+ case 'b':
152
+ #ifdef O_BINARY
153
+ flags |= O_BINARY;
154
+ #endif
155
+ break;
156
+ case 'x':
157
+ if (mode[0] != 'w') mode_error(mrb, mode);
158
+ flags |= O_EXCL;
159
+ break;
160
+ case '+':
161
+ flags = (flags & ~OPEN_ACCESS_MODE_FLAGS) | O_RDWR;
162
+ break;
163
+ case ':':
164
+ /* XXX: PASSTHROUGH*/
165
+ default:
166
+ mode_error(mrb, mode);
167
+ }
168
+ }
169
+
170
+ return flags;
171
+ }
172
+
173
+ static int
174
+ io_mode_to_flags(mrb_state *mrb, mrb_value mode)
175
+ {
176
+ if (mrb_nil_p(mode)) {
177
+ return O_RDONLY;
178
+ }
179
+ else if (mrb_string_p(mode)) {
180
+ return io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
181
+ }
182
+ else {
183
+ int flags = 0;
184
+ mrb_int flags0 = mrb_as_int(mrb, mode);
185
+
186
+ switch (flags0 & MRB_O_ACCMODE) {
187
+ case MRB_O_RDONLY:
188
+ flags |= O_RDONLY;
189
+ break;
190
+ case MRB_O_WRONLY:
191
+ flags |= O_WRONLY;
192
+ break;
193
+ case MRB_O_RDWR:
194
+ flags |= O_RDWR;
195
+ break;
196
+ default:
197
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %v", mode);
198
+ }
199
+
200
+ if (flags0 & MRB_O_APPEND) flags |= O_APPEND;
201
+ if (flags0 & MRB_O_CREAT) flags |= O_CREAT;
202
+ if (flags0 & MRB_O_EXCL) flags |= O_EXCL;
203
+ if (flags0 & MRB_O_TRUNC) flags |= O_TRUNC;
204
+ #ifdef O_NONBLOCK
205
+ if (flags0 & MRB_O_NONBLOCK) flags |= O_NONBLOCK;
206
+ #endif
207
+ #ifdef O_NOCTTY
208
+ if (flags0 & MRB_O_NOCTTY) flags |= O_NOCTTY;
209
+ #endif
210
+ #ifdef O_BINARY
211
+ if (flags0 & MRB_O_BINARY) flags |= O_BINARY;
212
+ #endif
213
+ #ifdef O_SHARE_DELETE
214
+ if (flags0 & MRB_O_SHARE_DELETE) flags |= O_SHARE_DELETE;
215
+ #endif
216
+ #ifdef O_SYNC
217
+ if (flags0 & MRB_O_SYNC) flags |= O_SYNC;
218
+ #endif
219
+ #ifdef O_DSYNC
220
+ if (flags0 & MRB_O_DSYNC) flags |= O_DSYNC;
221
+ #endif
222
+ #ifdef O_RSYNC
223
+ if (flags0 & MRB_O_RSYNC) flags |= O_RSYNC;
224
+ #endif
225
+ #ifdef O_NOFOLLOW
226
+ if (flags0 & MRB_O_NOFOLLOW) flags |= O_NOFOLLOW;
227
+ #endif
228
+ #ifdef O_NOATIME
229
+ if (flags0 & MRB_O_NOATIME) flags |= O_NOATIME;
230
+ #endif
231
+ #ifdef O_DIRECT
232
+ if (flags0 & MRB_O_DIRECT) flags |= O_DIRECT;
233
+ #endif
234
+ #ifdef O_TMPFILE
235
+ if (flags0 & MRB_O_TMPFILE) flags |= O_TMPFILE;
236
+ #endif
237
+
238
+ return flags;
239
+ }
240
+ }
241
+
242
+ static void
243
+ io_fd_cloexec(mrb_state *mrb, int fd)
244
+ {
245
+ #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
246
+ int flags = fcntl(fd, F_GETFD);
247
+ int flags2;
248
+
249
+ if (flags < 0) {
250
+ mrb_sys_fail(mrb, "cloexec GETFD");
251
+ }
252
+ if (fd <= 2) {
253
+ flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
254
+ }
255
+ else {
256
+ flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
257
+ }
258
+ if (flags != flags2) {
259
+ if (fcntl(fd, F_SETFD, flags2) < 0) {
260
+ mrb_sys_fail(mrb, "cloexec SETFD");
261
+ }
262
+ }
263
+ #endif
264
+ }
265
+
266
+
267
+ static void
268
+ io_free(mrb_state *mrb, void *ptr)
269
+ {
270
+ struct mrb_io *io = (struct mrb_io*)ptr;
271
+ if (io != NULL) {
272
+ fptr_finalize(mrb, io, TRUE);
273
+ mrb_free(mrb, io);
274
+ }
275
+ }
276
+
277
+ static void
278
+ io_init_buf(mrb_state *mrb, struct mrb_io *fptr)
279
+ {
280
+ if (fptr->readable) {
281
+ fptr->buf = (struct mrb_io_buf*)mrb_malloc(mrb, sizeof(struct mrb_io_buf));
282
+ fptr->buf->start = 0;
283
+ fptr->buf->len = 0;
284
+ }
285
+ }
286
+
287
+ static struct mrb_io *
288
+ io_alloc(mrb_state *mrb)
289
+ {
290
+ struct mrb_io *fptr = (struct mrb_io*)mrb_malloc(mrb, sizeof(struct mrb_io));
291
+ fptr->fd = -1;
292
+ fptr->fd2 = -1;
293
+ fptr->pid = 0;
294
+ fptr->buf = 0;
295
+ fptr->readable = 0;
296
+ fptr->writable = 0;
297
+ fptr->sync = 0;
298
+ fptr->eof = 0;
299
+ fptr->is_socket = 0;
300
+ fptr->close_fd = 1;
301
+ fptr->close_fd2 = 1;
302
+ return fptr;
303
+ }
304
+
305
+ #ifndef NOFILE
306
+ #define NOFILE 64
307
+ #endif
308
+
309
+ #ifdef MRB_NO_IO_POPEN
310
+ # define io_s_popen mrb_notimplement_m
311
+ #else
312
+ struct popen_params {
313
+ mrb_value klass;
314
+ const char *cmd;
315
+ int flags;
316
+ int doexec;
317
+ int opt_in, opt_out, opt_err;
318
+ };
319
+
320
+ static int
321
+ option_to_fd(mrb_state *mrb, mrb_value v)
322
+ {
323
+ if (mrb_undef_p(v)) return -1;
324
+ if (mrb_nil_p(v)) return -1;
325
+
326
+ switch (mrb_type(v)) {
327
+ case MRB_TT_CDATA: /* IO */
328
+ return mrb_io_fileno(mrb, v);
329
+ case MRB_TT_INTEGER:
330
+ return (int)mrb_integer(v);
331
+ default:
332
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong exec redirect action");
333
+ break;
334
+ }
335
+ return -1; /* never reached */
336
+ }
337
+
338
+ static void
339
+ parse_popen_args(mrb_state *mrb, struct popen_params *p)
340
+ {
341
+ mrb_value mode = mrb_nil_value();
342
+ struct { mrb_value opt_in, opt_out, opt_err; } kv;
343
+ mrb_sym knames[3] = {MRB_SYM(in), MRB_SYM(out), MRB_SYM(err)};
344
+ const mrb_kwargs kw = {
345
+ 3, 0,
346
+ knames,
347
+ &kv.opt_in,
348
+ NULL,
349
+ };
350
+
351
+ mrb_get_args(mrb, "zo:", &p->cmd, &mode, &kw);
352
+
353
+ p->flags = io_mode_to_flags(mrb, mode);
354
+ p->doexec = (strcmp("-", p->cmd) != 0);
355
+ p->opt_in = option_to_fd(mrb, kv.opt_in);
356
+ p->opt_out = option_to_fd(mrb, kv.opt_out);
357
+ p->opt_err = option_to_fd(mrb, kv.opt_err);
358
+ }
359
+
360
+ static mrb_value
361
+ io_s_popen(mrb_state *mrb, mrb_value klass)
362
+ {
363
+ struct popen_params p;
364
+ p.klass = klass;
365
+ int pid = 0;
366
+ int pr[2] = { -1, -1 }; /* read pipe: parent reads, child writes */
367
+ int pw[2] = { -1, -1 }; /* write pipe: parent writes, child reads */
368
+ int readable, writable;
369
+ int stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
370
+
371
+ mrb->c->ci->mid = 0;
372
+ parse_popen_args(mrb, &p);
373
+
374
+ readable = OPEN_READABLE_P(p.flags);
375
+ writable = OPEN_WRITABLE_P(p.flags);
376
+
377
+ /* Create pipes for communication */
378
+ if (readable) {
379
+ if (mrb_hal_io_pipe(mrb, pr) == -1) {
380
+ mrb_sys_fail(mrb, "pipe");
381
+ }
382
+ }
383
+
384
+ if (writable) {
385
+ if (mrb_hal_io_pipe(mrb, pw) == -1) {
386
+ if (pr[0] != -1) {
387
+ mrb_hal_io_close(mrb, pr[0]);
388
+ mrb_hal_io_close(mrb, pr[1]);
389
+ }
390
+ mrb_sys_fail(mrb, "pipe");
391
+ }
392
+ }
393
+
394
+ /* Set up child process file descriptors */
395
+ if (p.doexec) {
396
+ /* Child stdin: either write pipe read end or opt_in */
397
+ stdin_fd = (p.opt_in != -1) ? p.opt_in : (writable ? pw[0] : -1);
398
+
399
+ /* Child stdout: either read pipe write end or opt_out */
400
+ stdout_fd = (p.opt_out != -1) ? p.opt_out : (readable ? pr[1] : -1);
401
+
402
+ /* Child stderr: opt_err or stdout */
403
+ stderr_fd = (p.opt_err != -1) ? p.opt_err : stdout_fd;
404
+
405
+ /* Spawn child process using HAL */
406
+ if (mrb_hal_io_spawn_process(mrb, p.cmd, stdin_fd, stdout_fd, stderr_fd, &pid) == -1) {
407
+ int saved_errno = errno;
408
+ if (readable) {
409
+ mrb_hal_io_close(mrb, pr[0]);
410
+ mrb_hal_io_close(mrb, pr[1]);
411
+ }
412
+ if (writable) {
413
+ mrb_hal_io_close(mrb, pw[0]);
414
+ mrb_hal_io_close(mrb, pw[1]);
415
+ }
416
+ errno = saved_errno;
417
+ mrb_raisef(mrb, E_IO_ERROR, "command not found: %s", p.cmd);
418
+ }
419
+
420
+ /* Close child ends of pipes in parent */
421
+ if (readable) {
422
+ mrb_hal_io_close(mrb, pr[1]); /* close write end */
423
+ }
424
+ if (writable) {
425
+ mrb_hal_io_close(mrb, pw[0]); /* close read end */
426
+ }
427
+ }
428
+
429
+ /* Set up parent IO object */
430
+ mrb_value io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
431
+ struct mrb_io *fptr = io_alloc(mrb);
432
+
433
+ if (readable && writable) {
434
+ fptr->fd = pr[0]; /* parent reads from here */
435
+ fptr->fd2 = pw[1]; /* parent writes to here */
436
+ }
437
+ else if (readable) {
438
+ fptr->fd = pr[0]; /* parent reads from here */
439
+ fptr->fd2 = -1;
440
+ }
441
+ else {
442
+ fptr->fd = pw[1]; /* parent writes to here */
443
+ fptr->fd2 = -1;
444
+ }
445
+
446
+ fptr->pid = pid;
447
+ fptr->readable = readable;
448
+ fptr->writable = writable;
449
+ io_init_buf(mrb, fptr);
450
+
451
+ DATA_TYPE(io) = &mrb_io_type;
452
+ DATA_PTR(io) = fptr;
453
+ return io;
454
+ }
455
+ #endif /* MRB_NO_IO_POPEN */
456
+
457
+ static int
458
+ symdup(mrb_state *mrb, int fd, mrb_bool *failed)
459
+ {
460
+ int new_fd;
461
+
462
+ *failed = TRUE;
463
+ if (fd < 0)
464
+ return fd;
465
+
466
+ new_fd = dup(fd);
467
+ if (new_fd > 0) *failed = FALSE;
468
+ return new_fd;
469
+ }
470
+
471
+ static mrb_value
472
+ io_init_copy(mrb_state *mrb, mrb_value copy)
473
+ {
474
+ mrb_value orig = mrb_get_arg1(mrb);
475
+ struct mrb_io *fptr_copy;
476
+ struct mrb_io *fptr_orig;
477
+ mrb_bool failed = TRUE;
478
+
479
+ fptr_orig = io_get_open_fptr(mrb, orig);
480
+ fptr_copy = (struct mrb_io*)DATA_PTR(copy);
481
+ if (fptr_orig == fptr_copy) return copy;
482
+ if (fptr_copy != NULL) {
483
+ fptr_finalize(mrb, fptr_copy, FALSE);
484
+ mrb_free(mrb, fptr_copy);
485
+ }
486
+ fptr_copy = (struct mrb_io*)io_alloc(mrb);
487
+ fptr_copy->pid = fptr_orig->pid;
488
+ fptr_copy->readable = fptr_orig->readable;
489
+ fptr_copy->writable = fptr_orig->writable;
490
+ fptr_copy->sync = fptr_orig->sync;
491
+ fptr_copy->is_socket = fptr_orig->is_socket;
492
+
493
+ io_init_buf(mrb, fptr_copy);
494
+
495
+ DATA_TYPE(copy) = &mrb_io_type;
496
+ DATA_PTR(copy) = fptr_copy;
497
+
498
+ fptr_copy->fd = symdup(mrb, fptr_orig->fd, &failed);
499
+ if (failed) {
500
+ mrb_sys_fail(mrb, 0);
501
+ }
502
+ io_fd_cloexec(mrb, fptr_copy->fd);
503
+
504
+ if (fptr_orig->fd2 != -1) {
505
+ fptr_copy->fd2 = symdup(mrb, fptr_orig->fd2, &failed);
506
+ if (failed) {
507
+ close(fptr_copy->fd);
508
+ mrb_sys_fail(mrb, 0);
509
+ }
510
+ io_fd_cloexec(mrb, fptr_copy->fd2);
511
+ }
512
+
513
+ return copy;
514
+ }
515
+
516
+ static mrb_noreturn void
517
+ badfd_error(mrb_state *mrb)
518
+ {
519
+ mrb_sys_fail(mrb, "bad file descriptor");
520
+ }
521
+
522
+ static void
523
+ check_file_descriptor(mrb_state *mrb, mrb_int fd)
524
+ {
525
+ struct stat sb;
526
+ int fdi = (int)fd;
527
+
528
+ #if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
529
+ if (fdi != fd) {
530
+ errno = EBADF;
531
+ badfd_error(mrb);
532
+ }
533
+ #endif
534
+
535
+ #ifdef _WIN32
536
+ {
537
+ DWORD err;
538
+ int len = sizeof(err);
539
+
540
+ if (getsockopt(fdi, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0) {
541
+ return;
542
+ }
543
+ }
544
+
545
+ if (fdi < 0 || fdi > _getmaxstdio()) {
546
+ errno = EBADF;
547
+ badfd_error(mrb);
548
+ }
549
+ #endif /* _WIN32 */
550
+
551
+ if (fstat(fdi, &sb) == 0) return;
552
+ if (errno == EBADF) badfd_error(mrb);
553
+ }
554
+
555
+ static mrb_value
556
+ io_init(mrb_state *mrb, mrb_value io)
557
+ {
558
+ mrb_int fd;
559
+ mrb_value mode = mrb_nil_value();
560
+ mrb_value opt = mrb_nil_value();
561
+
562
+ if (mrb_block_given_p(mrb)) {
563
+ mrb_warn(mrb, "File.new() does not take block; use File.open() instead");
564
+ }
565
+ mrb_get_args(mrb, "i|oH", &fd, &mode, &opt);
566
+ switch (fd) {
567
+ case 0: /* STDIN_FILENO */
568
+ case 1: /* STDOUT_FILENO */
569
+ case 2: /* STDERR_FILENO */
570
+ break;
571
+ default:
572
+ check_file_descriptor(mrb, fd);
573
+ break;
574
+ }
575
+ int flags = io_mode_to_flags(mrb, mode);
576
+
577
+ struct mrb_io *fptr = (struct mrb_io*)DATA_PTR(io);
578
+ if (fptr != NULL) {
579
+ fptr_finalize(mrb, fptr, TRUE);
580
+ mrb_free(mrb, fptr);
581
+ }
582
+ fptr = io_alloc(mrb);
583
+
584
+ DATA_TYPE(io) = &mrb_io_type;
585
+ DATA_PTR(io) = fptr;
586
+
587
+ fptr->fd = (int)fd;
588
+ fptr->readable = OPEN_READABLE_P(flags);
589
+ fptr->writable = OPEN_WRITABLE_P(flags);
590
+ io_init_buf(mrb, fptr);
591
+ return io;
592
+ }
593
+
594
+ static void
595
+ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet)
596
+ {
597
+ int saved_errno = 0;
598
+ int limit = quiet ? 3 : 0;
599
+
600
+ if (fptr == NULL) {
601
+ return;
602
+ }
603
+
604
+ if (fptr->fd >= limit) {
605
+ #ifdef _WIN32
606
+ if (fptr->is_socket) {
607
+ if (fptr->close_fd && closesocket(fptr->fd) != 0) {
608
+ saved_errno = WSAGetLastError();
609
+ }
610
+ fptr->fd = -1;
611
+ }
612
+ #endif
613
+ if (fptr->fd != -1 && fptr->close_fd) {
614
+ if (close(fptr->fd) == -1) {
615
+ saved_errno = errno;
616
+ }
617
+ }
618
+ fptr->fd = -1;
619
+ }
620
+
621
+ if (fptr->fd2 >= limit) {
622
+ if (fptr->close_fd2 && close(fptr->fd2) == -1) {
623
+ if (saved_errno == 0) {
624
+ saved_errno = errno;
625
+ }
626
+ }
627
+ fptr->fd2 = -1;
628
+ }
629
+
630
+ #ifndef MRB_NO_IO_POPEN
631
+ if (fptr->pid != 0) {
632
+ #if !defined(_WIN32)
633
+ pid_t pid;
634
+ int status;
635
+ do {
636
+ pid = waitpid(fptr->pid, &status, 0);
637
+ } while (pid == -1 && errno == EINTR);
638
+ if (!quiet && pid == fptr->pid) {
639
+ io_set_process_status(mrb, pid, status);
640
+ }
641
+ #else
642
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, fptr->pid);
643
+ DWORD status;
644
+ if (WaitForSingleObject(h, INFINITE) && GetExitCodeProcess(h, &status))
645
+ if (!quiet)
646
+ io_set_process_status(mrb, fptr->pid, (int)status);
647
+ CloseHandle(h);
648
+ #endif
649
+ fptr->pid = 0;
650
+ /* Note: we don't raise an exception when waitpid(3) fails */
651
+ }
652
+ #endif
653
+
654
+ if (fptr->buf) {
655
+ mrb_free(mrb, fptr->buf);
656
+ fptr->buf = NULL;
657
+ }
658
+
659
+ if (!quiet && saved_errno != 0) {
660
+ errno = saved_errno;
661
+ mrb_sys_fail(mrb, "fptr_finalize failed");
662
+ }
663
+ }
664
+
665
+ static struct mrb_io*
666
+ io_get_read_fptr(mrb_state *mrb, mrb_value io)
667
+ {
668
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
669
+ if (!fptr->readable) {
670
+ mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
671
+ }
672
+ return fptr;
673
+ }
674
+
675
+ static struct mrb_io*
676
+ io_get_write_fptr(mrb_state *mrb, mrb_value io)
677
+ {
678
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
679
+ if (!fptr->writable) {
680
+ mrb_raise(mrb, E_IO_ERROR, "not opened for writing");
681
+ }
682
+ return fptr;
683
+ }
684
+
685
+ static int
686
+ io_get_write_fd(struct mrb_io *fptr)
687
+ {
688
+ if (fptr->fd2 == -1) {
689
+ return fptr->fd;
690
+ }
691
+ else {
692
+ return fptr->fd2;
693
+ }
694
+ }
695
+
696
+ static mrb_value
697
+ io_isatty(mrb_state *mrb, mrb_value io)
698
+ {
699
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
700
+ if (isatty(fptr->fd) == 0)
701
+ return mrb_false_value();
702
+ return mrb_true_value();
703
+ }
704
+
705
+ static mrb_value
706
+ io_s_for_fd(mrb_state *mrb, mrb_value klass)
707
+ {
708
+ struct RClass *c = mrb_class_ptr(klass);
709
+ enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
710
+
711
+ /* copied from mrb_instance_alloc() */
712
+ if (ttype == 0) ttype = MRB_TT_OBJECT;
713
+
714
+ mrb_value obj = mrb_obj_value((struct RObject*)mrb_obj_alloc(mrb, ttype, c));
715
+ return io_init(mrb, obj);
716
+ }
717
+
718
+ static mrb_value
719
+ io_s_sysclose(mrb_state *mrb, mrb_value klass)
720
+ {
721
+ mrb_int fd;
722
+ mrb->c->ci->mid = 0;
723
+ mrb_get_args(mrb, "i", &fd);
724
+ if (close((int)fd) == -1) {
725
+ mrb_sys_fail(mrb, "close");
726
+ }
727
+ return mrb_fixnum_value(0);
728
+ }
729
+
730
+ static int
731
+ io_cloexec_open(mrb_state *mrb, const char *pathname, int flags, fmode_t mode)
732
+ {
733
+ int retry = FALSE;
734
+ char *fname = mrb_locale_from_utf8(pathname, -1);
735
+ int fd;
736
+
737
+ #ifdef O_CLOEXEC
738
+ /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
739
+ flags |= O_CLOEXEC;
740
+ #elif defined O_NOINHERIT
741
+ flags |= O_NOINHERIT;
742
+ #endif
743
+ reopen:
744
+ fd = open(fname, flags, mode);
745
+ if (fd == -1) {
746
+ if (!retry) {
747
+ switch (errno) {
748
+ case ENFILE:
749
+ case EMFILE:
750
+ mrb_garbage_collect(mrb);
751
+ retry = TRUE;
752
+ goto reopen;
753
+ }
754
+ }
755
+ mrb_sys_fail(mrb, RSTRING_CSTR(mrb, mrb_format(mrb, "open %s", pathname)));
756
+ }
757
+ mrb_locale_free(fname);
758
+
759
+ if (fd <= 2) {
760
+ io_fd_cloexec(mrb, fd);
761
+ }
762
+ return fd;
763
+ }
764
+
765
+ static mrb_value
766
+ io_s_sysopen(mrb_state *mrb, mrb_value klass)
767
+ {
768
+ mrb_value path = mrb_nil_value();
769
+ mrb_value mode = mrb_nil_value();
770
+ mrb_int perm = -1;
771
+
772
+ mrb_get_args(mrb, "S|oi", &path, &mode, &perm);
773
+ if (perm < 0) {
774
+ perm = 0666;
775
+ }
776
+
777
+ const char *pat = RSTRING_CSTR(mrb, path);
778
+ int flags = io_mode_to_flags(mrb, mode);
779
+ mrb_int fd = io_cloexec_open(mrb, pat, flags, (fmode_t)perm);
780
+ return mrb_fixnum_value(fd);
781
+ }
782
+
783
+ static void
784
+ eof_error(mrb_state *mrb)
785
+ {
786
+ mrb_raise(mrb, E_EOF_ERROR, "end of file reached");
787
+ }
788
+
789
+ static mrb_value
790
+ io_read_common(mrb_state *mrb,
791
+ fssize_t (*readfunc)(int, void*, fsize_t, off_t),
792
+ mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset)
793
+ {
794
+ if (maxlen < 0) {
795
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative expanding string size");
796
+ }
797
+ else if (maxlen == 0) {
798
+ return mrb_str_new(mrb, NULL, maxlen);
799
+ }
800
+
801
+ if (mrb_nil_p(buf)) {
802
+ buf = mrb_str_new(mrb, NULL, maxlen);
803
+ }
804
+
805
+ if (RSTRING_LEN(buf) != maxlen) {
806
+ buf = mrb_str_resize(mrb, buf, maxlen);
807
+ }
808
+ else {
809
+ mrb_str_modify(mrb, RSTRING(buf));
810
+ }
811
+
812
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
813
+ int ret = readfunc(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen, offset);
814
+ if (ret < 0) {
815
+ mrb_sys_fail(mrb, "sysread failed");
816
+ }
817
+ if (RSTRING_LEN(buf) != ret) {
818
+ buf = mrb_str_resize(mrb, buf, ret);
819
+ }
820
+ if (ret == 0 && maxlen > 0) {
821
+ fptr->eof = 1;
822
+ eof_error(mrb);
823
+ }
824
+ return buf;
825
+ }
826
+
827
+ static fssize_t
828
+ sysread(int fd, void *buf, fsize_t nbytes, off_t offset)
829
+ {
830
+ return (fssize_t)read(fd, buf, nbytes);
831
+ }
832
+
833
+ static mrb_value
834
+ io_sysread(mrb_state *mrb, mrb_value io)
835
+ {
836
+ mrb_value buf = mrb_nil_value();
837
+ mrb_int maxlen;
838
+
839
+ mrb_get_args(mrb, "i|S", &maxlen, &buf);
840
+
841
+ return io_read_common(mrb, sysread, io, buf, maxlen, 0);
842
+ }
843
+
844
+ static mrb_value
845
+ io_sysseek(mrb_state *mrb, mrb_value io)
846
+ {
847
+ mrb_int offset, whence = -1;
848
+
849
+ mrb_get_args(mrb, "i|i", &offset, &whence);
850
+ if (whence < 0) {
851
+ whence = 0;
852
+ }
853
+
854
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
855
+ off_t pos = lseek(fptr->fd, (off_t)offset, (int)whence);
856
+ if (pos == -1) {
857
+ mrb_sys_fail(mrb, "sysseek");
858
+ }
859
+ fptr->eof = 0;
860
+ if (sizeof(off_t) > sizeof(mrb_int) && pos > (off_t)MRB_INT_MAX) {
861
+ mrb_raise(mrb, E_IO_ERROR, "sysseek reached too far for mrb_int");
862
+ }
863
+ return mrb_int_value(mrb, (mrb_int)pos);
864
+ }
865
+
866
+ static mrb_value
867
+ io_seek(mrb_state *mrb, mrb_value io)
868
+ {
869
+ mrb_value pos = io_sysseek(mrb, io);
870
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
871
+ if (fptr->buf) {
872
+ fptr->buf->start = 0;
873
+ fptr->buf->len = 0;
874
+ }
875
+ return pos;
876
+ }
877
+
878
+ static mrb_value
879
+ io_write_common(mrb_state *mrb,
880
+ fssize_t (*writefunc)(int, const void*, fsize_t, off_t),
881
+ struct mrb_io *fptr, const void *buf, mrb_ssize blen, off_t offset)
882
+ {
883
+ int fd = io_get_write_fd(fptr);
884
+ fssize_t length = writefunc(fd, buf, (fsize_t)blen, offset);
885
+ if (length == -1) {
886
+ mrb_sys_fail(mrb, "syswrite");
887
+ }
888
+ return mrb_int_value(mrb, (mrb_int)length);
889
+ }
890
+
891
+ static fssize_t
892
+ syswrite(int fd, const void *buf, fsize_t nbytes, off_t offset)
893
+ {
894
+ return (fssize_t)write(fd, buf, nbytes);
895
+ }
896
+
897
+ static mrb_value
898
+ io_syswrite(mrb_state *mrb, mrb_value io)
899
+ {
900
+ mrb_value buf;
901
+
902
+ mrb_get_args(mrb, "S", &buf);
903
+
904
+ return io_write_common(mrb, syswrite, io_get_write_fptr(mrb, io), RSTRING_PTR(buf), RSTRING_LEN(buf), 0);
905
+ }
906
+
907
+ /* def write(string) */
908
+ /* str = string.is_a?(String) ? string : string.to_s */
909
+ /* return 0 if str.empty? */
910
+ /* len = syswrite(str) */
911
+ /* len */
912
+ /* end */
913
+
914
+ static mrb_int
915
+ fd_write(mrb_state *mrb, int fd, mrb_value str)
916
+ {
917
+ fssize_t n;
918
+
919
+ str = mrb_obj_as_string(mrb, str);
920
+ fssize_t len = (fssize_t)RSTRING_LEN(str);
921
+ if (len == 0) return 0;
922
+
923
+ const char *ptr = RSTRING_PTR(str);
924
+ fssize_t sum = 0;
925
+ while (sum < len) {
926
+ n = write(fd, ptr + sum, len - sum);
927
+ if (n == -1) {
928
+ if (errno == EINTR) continue;
929
+ mrb_sys_fail(mrb, "syswrite");
930
+ }
931
+ sum += n;
932
+ }
933
+ return len;
934
+ }
935
+
936
+ /* Helper function to prepare IO object for writing by adjusting buffer state */
937
+ static void
938
+ io_prepare_write(mrb_state *mrb, struct mrb_io *fptr)
939
+ {
940
+ if (fptr->buf && fptr->buf->len > 0) {
941
+ int fd = io_get_write_fd(fptr);
942
+ off_t n;
943
+
944
+ /* get current position */
945
+ n = lseek(fd, 0, SEEK_CUR);
946
+ if (n == -1) mrb_sys_fail(mrb, "lseek");
947
+ /* move cursor */
948
+ n = lseek(fd, n - fptr->buf->len, SEEK_SET);
949
+ if (n == -1) mrb_sys_fail(mrb, "lseek(2)");
950
+ fptr->buf->start = fptr->buf->len = 0;
951
+ }
952
+ }
953
+
954
+ static mrb_value
955
+ io_write(mrb_state *mrb, mrb_value io)
956
+ {
957
+ struct mrb_io *fptr = io_get_write_fptr(mrb, io);
958
+ int fd = io_get_write_fd(fptr);
959
+
960
+ io_prepare_write(mrb, fptr);
961
+
962
+ mrb_int len = 0;
963
+ if (mrb_get_argc(mrb) == 1) {
964
+ len = fd_write(mrb, fd, mrb_get_arg1(mrb));
965
+ }
966
+ else {
967
+ mrb_value *argv;
968
+ mrb_int argc;
969
+
970
+ mrb_get_args(mrb, "*", &argv, &argc);
971
+ while (argc--) {
972
+ len += fd_write(mrb, fd, *argv++);
973
+ }
974
+ }
975
+ return mrb_int_value(mrb, len);
976
+ }
977
+
978
+ /* Helper function to write a string followed by newline if needed */
979
+ static void
980
+ io_puts_str(mrb_state *mrb, int fd, mrb_value str)
981
+ {
982
+ str = mrb_obj_as_string(mrb, str);
983
+ const char *ptr = RSTRING_PTR(str);
984
+ mrb_int len = RSTRING_LEN(str);
985
+
986
+ /* Write the original string */
987
+ fd_write(mrb, fd, str);
988
+
989
+ /* Add newline if string doesn't end with one */
990
+ if (len == 0 || ptr[len-1] != '\n') {
991
+ mrb_value newline = mrb_str_new_lit(mrb, "\n");
992
+ fd_write(mrb, fd, newline);
993
+ }
994
+ }
995
+
996
+ /* Recursive helper for puts with arrays */
997
+ static void
998
+ io_puts_ary(mrb_state *mrb, int fd, mrb_value ary)
999
+ {
1000
+ mrb_int len = RARRAY_LEN(ary);
1001
+
1002
+ if (len == 0) {
1003
+ /* Empty array - write a single newline */
1004
+ mrb_value newline = mrb_str_new_lit(mrb, "\n");
1005
+ fd_write(mrb, fd, newline);
1006
+ return;
1007
+ }
1008
+
1009
+ for (mrb_int i = 0; i < len; i++) {
1010
+ mrb_value elem = RARRAY_PTR(ary)[i];
1011
+ if (mrb_array_p(elem)) {
1012
+ io_puts_ary(mrb, fd, elem); /* Recursive call for nested arrays */
1013
+ }
1014
+ else {
1015
+ io_puts_str(mrb, fd, elem);
1016
+ }
1017
+ }
1018
+ }
1019
+
1020
+ static mrb_value
1021
+ io_puts(mrb_state *mrb, mrb_value io)
1022
+ {
1023
+ struct mrb_io *fptr = io_get_write_fptr(mrb, io);
1024
+ int fd = io_get_write_fd(fptr);
1025
+
1026
+ /* Prepare IO for writing (handle read buffer adjustment) */
1027
+ io_prepare_write(mrb, fptr);
1028
+
1029
+ mrb_value *argv;
1030
+ mrb_int argc;
1031
+ mrb_get_args(mrb, "*", &argv, &argc);
1032
+
1033
+ if (argc == 0) {
1034
+ /* No arguments - just write a newline */
1035
+ mrb_value newline = mrb_str_new_lit(mrb, "\n");
1036
+ fd_write(mrb, fd, newline);
1037
+ return mrb_nil_value();
1038
+ }
1039
+
1040
+ /* Process each argument */
1041
+ for (mrb_int i = 0; i < argc; i++) {
1042
+ mrb_value arg = argv[i];
1043
+ if (mrb_array_p(arg)) {
1044
+ io_puts_ary(mrb, fd, arg);
1045
+ }
1046
+ else {
1047
+ io_puts_str(mrb, fd, arg);
1048
+ }
1049
+ }
1050
+
1051
+ return mrb_nil_value();
1052
+ }
1053
+
1054
+ /*
1055
+ * call-seq:
1056
+ * ios.print() -> nil
1057
+ * ios.print(obj, ...) -> nil
1058
+ *
1059
+ * Writes the given object(s) to ios. Objects that aren't strings will be
1060
+ * converted by calling their to_s method.
1061
+ */
1062
+ static mrb_value
1063
+ io_print(mrb_state *mrb, mrb_value io)
1064
+ {
1065
+ struct mrb_io *fptr = io_get_write_fptr(mrb, io);
1066
+ int fd = io_get_write_fd(fptr);
1067
+
1068
+ /* Prepare IO for writing (handle read buffer adjustment) */
1069
+ io_prepare_write(mrb, fptr);
1070
+
1071
+ mrb_value *argv;
1072
+ mrb_int argc;
1073
+ mrb_get_args(mrb, "*", &argv, &argc);
1074
+
1075
+ /* Convert each argument to string and write it */
1076
+ for (mrb_int i = 0; i < argc; i++) {
1077
+ mrb_value str = mrb_obj_as_string(mrb, argv[i]);
1078
+ fd_write(mrb, fd, str);
1079
+ }
1080
+
1081
+ return mrb_nil_value();
1082
+ }
1083
+
1084
+ /*
1085
+ * call-seq:
1086
+ * ios.putc(obj) -> obj
1087
+ *
1088
+ * If obj is Integer, write the byte (mod 256).
1089
+ * If obj is String, write the first character.
1090
+ * Returns obj.
1091
+ */
1092
+ static mrb_value
1093
+ io_putc(mrb_state *mrb, mrb_value io)
1094
+ {
1095
+ struct mrb_io *fptr = io_get_write_fptr(mrb, io);
1096
+ int fd = io_get_write_fd(fptr);
1097
+ mrb_value c = mrb_get_arg1(mrb);
1098
+ const char *ptr;
1099
+ mrb_int write_len;
1100
+
1101
+ io_prepare_write(mrb, fptr);
1102
+
1103
+ if (mrb_integer_p(c)) {
1104
+ unsigned char byte = (unsigned char)(mrb_integer(c) & 0xff);
1105
+ ssize_t n;
1106
+ do {
1107
+ n = write(fd, &byte, 1);
1108
+ } while (n == -1 && errno == EINTR);
1109
+ if (n == -1) mrb_sys_fail(mrb, "write");
1110
+ return c;
1111
+ }
1112
+
1113
+ mrb_value str;
1114
+ if (mrb_string_p(c)) {
1115
+ str = c;
1116
+ }
1117
+ else {
1118
+ str = mrb_obj_as_string(mrb, c);
1119
+ }
1120
+
1121
+ ptr = RSTRING_PTR(str);
1122
+ mrb_int len = RSTRING_LEN(str);
1123
+
1124
+ if (len == 0) return c;
1125
+
1126
+ #ifdef MRB_UTF8_STRING
1127
+ write_len = mrb_utf8len(ptr, ptr + len);
1128
+ #else
1129
+ write_len = 1; /* Non-UTF8: write single byte */
1130
+ #endif
1131
+
1132
+ /* Write the character bytes */
1133
+ while (write_len > 0) {
1134
+ ssize_t n = write(fd, ptr, write_len);
1135
+ if (n == -1) {
1136
+ if (errno == EINTR) continue;
1137
+ mrb_sys_fail(mrb, "write");
1138
+ }
1139
+ ptr += n;
1140
+ write_len -= n;
1141
+ }
1142
+
1143
+ return c;
1144
+ }
1145
+
1146
+ /*
1147
+ * call-seq:
1148
+ * ios << obj -> ios
1149
+ *
1150
+ * String Output - Writes obj to ios. obj will be converted to a string using
1151
+ * to_s.
1152
+ */
1153
+ static mrb_value
1154
+ io_lshift(mrb_state *mrb, mrb_value io)
1155
+ {
1156
+ struct mrb_io *fptr = io_get_write_fptr(mrb, io);
1157
+ int fd = io_get_write_fd(fptr);
1158
+
1159
+ /* Prepare IO for writing (handle read buffer adjustment) */
1160
+ io_prepare_write(mrb, fptr);
1161
+
1162
+ mrb_value str = mrb_get_arg1(mrb);
1163
+ str = mrb_obj_as_string(mrb, str);
1164
+ fd_write(mrb, fd, str);
1165
+
1166
+ return io;
1167
+ }
1168
+
1169
+ static mrb_value
1170
+ io_close(mrb_state *mrb, mrb_value io)
1171
+ {
1172
+ struct mrb_io *fptr;
1173
+ fptr = io_get_open_fptr(mrb, io);
1174
+ fptr_finalize(mrb, fptr, FALSE);
1175
+ return mrb_nil_value();
1176
+ }
1177
+
1178
+ /*
1179
+ * call-seq:
1180
+ * ios.close_write -> nil
1181
+ *
1182
+ * Closes the write end of a duplex I/O stream (i.e., a pipe).
1183
+ * It will raise an `IOError` if the stream is not duplex.
1184
+ *
1185
+ * r, w = IO.pipe
1186
+ * w.close_write
1187
+ * r.read #=> ""
1188
+ */
1189
+ static mrb_value
1190
+ io_close_write(mrb_state *mrb, mrb_value io)
1191
+ {
1192
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1193
+ if (close((int)fptr->fd2) == -1) {
1194
+ mrb_sys_fail(mrb, "close");
1195
+ }
1196
+ return mrb_nil_value();
1197
+ }
1198
+
1199
+ /*
1200
+ * call-seq:
1201
+ * ios.closed? -> true or false
1202
+ *
1203
+ * Returns `true` if the stream is closed, `false` otherwise.
1204
+ *
1205
+ * f = File.new("testfile")
1206
+ * f.close #=> nil
1207
+ * f.closed? #=> true
1208
+ */
1209
+ static mrb_value
1210
+ io_closed(mrb_state *mrb, mrb_value io)
1211
+ {
1212
+ struct mrb_io *fptr = (struct mrb_io*)mrb_data_get_ptr(mrb, io, &mrb_io_type);
1213
+ if (fptr == NULL || fptr->fd >= 0) {
1214
+ return mrb_false_value();
1215
+ }
1216
+
1217
+ return mrb_true_value();
1218
+ }
1219
+
1220
+ static mrb_value
1221
+ io_pos(mrb_state *mrb, mrb_value io)
1222
+ {
1223
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1224
+ off_t pos = lseek(fptr->fd, 0, SEEK_CUR);
1225
+ if (pos == -1) mrb_sys_fail(mrb, 0);
1226
+
1227
+ if (fptr->buf) {
1228
+ return mrb_int_value(mrb, pos - fptr->buf->len);
1229
+ }
1230
+ else {
1231
+ return mrb_int_value(mrb, pos);
1232
+ }
1233
+ }
1234
+
1235
+ /*
1236
+ * call-seq:
1237
+ * ios.pid -> integer or nil
1238
+ *
1239
+ * Returns the process ID of a child process on a pipe, or `nil` if the
1240
+ * stream is not a pipe.
1241
+ *
1242
+ * r, w = IO.pipe
1243
+ * fork do
1244
+ * r.close
1245
+ * w.write "hello"
1246
+ * w.close
1247
+ * end
1248
+ * w.close
1249
+ * p r.pid #=> 2056
1250
+ * r.read #=> "hello"
1251
+ * r.close
1252
+ */
1253
+ static mrb_value
1254
+ io_pid(mrb_state *mrb, mrb_value io)
1255
+ {
1256
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1257
+
1258
+ if (fptr->pid > 0) {
1259
+ return mrb_fixnum_value(fptr->pid);
1260
+ }
1261
+
1262
+ return mrb_nil_value();
1263
+ }
1264
+
1265
+ static mrb_io_timeval
1266
+ time2timeval(mrb_state *mrb, mrb_value time)
1267
+ {
1268
+ mrb_io_timeval t = { 0, 0 };
1269
+
1270
+ switch (mrb_type(time)) {
1271
+ case MRB_TT_INTEGER:
1272
+ t.tv_sec = (int64_t)mrb_integer(time);
1273
+ t.tv_usec = 0;
1274
+ break;
1275
+
1276
+ #ifndef MRB_NO_FLOAT
1277
+ case MRB_TT_FLOAT:
1278
+ t.tv_sec = (int64_t)mrb_float(time);
1279
+ t.tv_usec = (int64_t)((mrb_float(time) - t.tv_sec) * 1000000.0);
1280
+ break;
1281
+ #endif
1282
+
1283
+ default:
1284
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
1285
+ }
1286
+
1287
+ return t;
1288
+ }
1289
+
1290
+ /*
1291
+ * call-seq:
1292
+ * IO.new(fd, mode="r") -> io
1293
+ *
1294
+ * Returns a new `IO` object for the given integer file descriptor `fd` and
1295
+ * `mode` string.
1296
+ *
1297
+ * f = IO.new(1, "w") # STDOUT
1298
+ * f.puts "hello"
1299
+ */
1300
+
1301
+ #if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
1302
+ static mrb_value
1303
+ io_s_pipe(mrb_state *mrb, mrb_value klass)
1304
+ {
1305
+ int pipes[2];
1306
+
1307
+ if (mrb_hal_io_pipe(mrb, pipes) == -1) {
1308
+ mrb_sys_fail(mrb, "pipe");
1309
+ }
1310
+
1311
+ mrb_value r = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
1312
+ struct mrb_io *fptr_r = io_alloc(mrb);
1313
+ fptr_r->fd = pipes[0];
1314
+ fptr_r->readable = 1;
1315
+ DATA_TYPE(r) = &mrb_io_type;
1316
+ DATA_PTR(r) = fptr_r;
1317
+ io_init_buf(mrb, fptr_r);
1318
+
1319
+ mrb_value w = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
1320
+ struct mrb_io *fptr_w = io_alloc(mrb);
1321
+ fptr_w->fd = pipes[1];
1322
+ fptr_w->writable = 1;
1323
+ fptr_w->sync = 1;
1324
+ DATA_TYPE(w) = &mrb_io_type;
1325
+ DATA_PTR(w) = fptr_w;
1326
+
1327
+ return mrb_assoc_new(mrb, r, w);
1328
+ }
1329
+ #endif
1330
+
1331
+ static int
1332
+ mrb_io_read_data_pending(mrb_state *mrb, struct mrb_io *fptr)
1333
+ {
1334
+ if (fptr->buf && fptr->buf->len > 0) return 1;
1335
+ return 0;
1336
+ }
1337
+
1338
+ /*
1339
+ * call-seq:
1340
+ * IO.select(read_array, write_array=nil, error_array=nil, timeout=nil) -> array or nil
1341
+ *
1342
+ * Performs a `select(2)` system call on the given arrays of `IO` objects.
1343
+ *
1344
+ * For each array, it can contain `IO` objects or `nil`.
1345
+ *
1346
+ * The `timeout` argument is a number of seconds.
1347
+ *
1348
+ * It returns a three-element array containing the `IO` objects that are
1349
+ * ready for reading, writing, or have an error, respectively.
1350
+ *
1351
+ * If the `timeout` is reached, it returns `nil`.
1352
+ *
1353
+ * r, w = IO.pipe
1354
+ * IO.select([r], [w]) #=> [[#<IO:fd 6>], [#<IO:fd 7>], []]
1355
+ */
1356
+ static mrb_value
1357
+ io_s_select(mrb_state *mrb, mrb_value klass)
1358
+ {
1359
+ const mrb_value *argv;
1360
+ mrb_int argc;
1361
+ mrb_value read_io, list;
1362
+ struct mrb_io *fptr;
1363
+ int pending = 0;
1364
+ mrb_value result;
1365
+ int max = 0;
1366
+ int interrupt_flag = 0;
1367
+
1368
+ mrb_get_args(mrb, "*", &argv, &argc);
1369
+
1370
+ if (argc < 1 || argc > 4) {
1371
+ mrb_argnum_error(mrb, argc, 1, 4);
1372
+ }
1373
+
1374
+ mrb_value timeout = mrb_nil_value();
1375
+ mrb_value except = mrb_nil_value();
1376
+ mrb_value write = mrb_nil_value();
1377
+ if (argc > 3)
1378
+ timeout = argv[3];
1379
+ if (argc > 2)
1380
+ except = argv[2];
1381
+ if (argc > 1)
1382
+ write = argv[1];
1383
+ mrb_value read = argv[0];
1384
+
1385
+ mrb_io_timeval *tp, timerec;
1386
+ if (mrb_nil_p(timeout)) {
1387
+ tp = NULL;
1388
+ }
1389
+ else {
1390
+ timerec = time2timeval(mrb, timeout);
1391
+ tp = &timerec;
1392
+ }
1393
+
1394
+ mrb_io_fdset *pset = mrb_hal_io_fdset_alloc(mrb);
1395
+ mrb_io_fdset *rset = NULL;
1396
+ mrb_io_fdset *rp = NULL;
1397
+ mrb_hal_io_fdset_zero(mrb, pset);
1398
+ if (!mrb_nil_p(read)) {
1399
+ mrb_check_type(mrb, read, MRB_TT_ARRAY);
1400
+ rset = mrb_hal_io_fdset_alloc(mrb);
1401
+ rp = rset;
1402
+ mrb_hal_io_fdset_zero(mrb, rp);
1403
+ /* Hoist pointer retrieval outside loop */
1404
+ mrb_value *read_ptr = RARRAY_PTR(read);
1405
+ for (int i = 0; i < RARRAY_LEN(read); i++) {
1406
+ read_io = read_ptr[i];
1407
+ fptr = io_get_open_fptr(mrb, read_io);
1408
+ mrb_hal_io_fdset_set(mrb, fptr->fd, rp);
1409
+ if (mrb_io_read_data_pending(mrb, fptr)) {
1410
+ pending++;
1411
+ mrb_hal_io_fdset_set(mrb, fptr->fd, pset);
1412
+ }
1413
+ if (max < fptr->fd)
1414
+ max = fptr->fd;
1415
+ }
1416
+ if (pending) {
1417
+ timerec.tv_sec = timerec.tv_usec = 0;
1418
+ tp = &timerec;
1419
+ }
1420
+ }
1421
+
1422
+ mrb_io_fdset *wset = NULL;
1423
+ mrb_io_fdset *wp = NULL;
1424
+ if (!mrb_nil_p(write)) {
1425
+ mrb_check_type(mrb, write, MRB_TT_ARRAY);
1426
+ wset = mrb_hal_io_fdset_alloc(mrb);
1427
+ wp = wset;
1428
+ mrb_hal_io_fdset_zero(mrb, wp);
1429
+ /* Hoist pointer retrieval outside loop */
1430
+ mrb_value *write_ptr = RARRAY_PTR(write);
1431
+ for (int i = 0; i < RARRAY_LEN(write); i++) {
1432
+ fptr = io_get_open_fptr(mrb, write_ptr[i]);
1433
+ mrb_hal_io_fdset_set(mrb, fptr->fd, wp);
1434
+ if (max < fptr->fd)
1435
+ max = fptr->fd;
1436
+ if (fptr->fd2 >= 0) {
1437
+ mrb_hal_io_fdset_set(mrb, fptr->fd2, wp);
1438
+ if (max < fptr->fd2)
1439
+ max = fptr->fd2;
1440
+ }
1441
+ }
1442
+ }
1443
+
1444
+ mrb_io_fdset *eset = NULL;
1445
+ mrb_io_fdset *ep = NULL;
1446
+ if (!mrb_nil_p(except)) {
1447
+ mrb_check_type(mrb, except, MRB_TT_ARRAY);
1448
+ eset = mrb_hal_io_fdset_alloc(mrb);
1449
+ ep = eset;
1450
+ mrb_hal_io_fdset_zero(mrb, ep);
1451
+ /* Hoist pointer retrieval outside loop */
1452
+ mrb_value *except_ptr = RARRAY_PTR(except);
1453
+ for (int i = 0; i < RARRAY_LEN(except); i++) {
1454
+ fptr = io_get_open_fptr(mrb, except_ptr[i]);
1455
+ mrb_hal_io_fdset_set(mrb, fptr->fd, ep);
1456
+ if (max < fptr->fd)
1457
+ max = fptr->fd;
1458
+ if (fptr->fd2 >= 0) {
1459
+ mrb_hal_io_fdset_set(mrb, fptr->fd2, ep);
1460
+ if (max < fptr->fd2)
1461
+ max = fptr->fd2;
1462
+ }
1463
+ }
1464
+ }
1465
+
1466
+ max++;
1467
+
1468
+ int n;
1469
+ retry:
1470
+ n = mrb_hal_io_select(mrb, max, rp, wp, ep, tp);
1471
+ if (n < 0) {
1472
+ if (errno != EINTR) {
1473
+ mrb_hal_io_fdset_free(mrb, pset);
1474
+ mrb_hal_io_fdset_free(mrb, rset);
1475
+ mrb_hal_io_fdset_free(mrb, wset);
1476
+ mrb_hal_io_fdset_free(mrb, eset);
1477
+ mrb_sys_fail(mrb, "select failed");
1478
+ }
1479
+ if (tp == NULL)
1480
+ goto retry;
1481
+ interrupt_flag = 1;
1482
+ }
1483
+
1484
+ if (!pending && n == 0) {
1485
+ mrb_hal_io_fdset_free(mrb, pset);
1486
+ mrb_hal_io_fdset_free(mrb, rset);
1487
+ mrb_hal_io_fdset_free(mrb, wset);
1488
+ mrb_hal_io_fdset_free(mrb, eset);
1489
+ return mrb_nil_value();
1490
+ }
1491
+
1492
+ result = mrb_ary_new_capa(mrb, 3);
1493
+ mrb_ary_push(mrb, result, rp ? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
1494
+ mrb_ary_push(mrb, result, wp ? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
1495
+ mrb_ary_push(mrb, result, ep ? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
1496
+
1497
+ if (interrupt_flag == 0) {
1498
+ if (rp) {
1499
+ list = RARRAY_PTR(result)[0];
1500
+ /* Hoist pointer retrieval outside loop */
1501
+ mrb_value *read_ptr = RARRAY_PTR(read);
1502
+ for (int i = 0; i < RARRAY_LEN(read); i++) {
1503
+ mrb_value io = read_ptr[i];
1504
+ fptr = io_get_open_fptr(mrb, io);
1505
+ if (mrb_hal_io_fdset_isset(mrb, fptr->fd, rp) ||
1506
+ mrb_hal_io_fdset_isset(mrb, fptr->fd, pset)) {
1507
+ mrb_ary_push(mrb, list, io);
1508
+ }
1509
+ }
1510
+ }
1511
+
1512
+ if (wp) {
1513
+ list = RARRAY_PTR(result)[1];
1514
+ /* Hoist pointer retrieval outside loop */
1515
+ mrb_value *write_ptr = RARRAY_PTR(write);
1516
+ for (int i = 0; i < RARRAY_LEN(write); i++) {
1517
+ mrb_value io = write_ptr[i];
1518
+ fptr = io_get_open_fptr(mrb, io);
1519
+ if (mrb_hal_io_fdset_isset(mrb, fptr->fd, wp)) {
1520
+ mrb_ary_push(mrb, list, io);
1521
+ }
1522
+ else if (fptr->fd2 >= 0 && mrb_hal_io_fdset_isset(mrb, fptr->fd2, wp)) {
1523
+ mrb_ary_push(mrb, list, io);
1524
+ }
1525
+ }
1526
+ }
1527
+
1528
+ if (ep) {
1529
+ list = RARRAY_PTR(result)[2];
1530
+ /* Hoist pointer retrieval outside loop */
1531
+ mrb_value *except_ptr = RARRAY_PTR(except);
1532
+ for (int i = 0; i < RARRAY_LEN(except); i++) {
1533
+ mrb_value io = except_ptr[i];
1534
+ fptr = io_get_open_fptr(mrb, io);
1535
+ if (mrb_hal_io_fdset_isset(mrb, fptr->fd, ep)) {
1536
+ mrb_ary_push(mrb, list, io);
1537
+ }
1538
+ else if (fptr->fd2 >= 0 && mrb_hal_io_fdset_isset(mrb, fptr->fd2, ep)) {
1539
+ mrb_ary_push(mrb, list, io);
1540
+ }
1541
+ }
1542
+ }
1543
+ }
1544
+
1545
+ mrb_hal_io_fdset_free(mrb, pset);
1546
+ mrb_hal_io_fdset_free(mrb, rset);
1547
+ mrb_hal_io_fdset_free(mrb, wset);
1548
+ mrb_hal_io_fdset_free(mrb, eset);
1549
+
1550
+ return result;
1551
+ }
1552
+
1553
+ int
1554
+ mrb_io_fileno(mrb_state *mrb, mrb_value io)
1555
+ {
1556
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1557
+ return fptr->fd;
1558
+ }
1559
+
1560
+ /*
1561
+ * call-seq:
1562
+ * ios.fileno -> integer
1563
+ *
1564
+ * Returns the integer file descriptor number for the `IO` object.
1565
+ *
1566
+ * $stdin.fileno #=> 0
1567
+ * $stdout.fileno #=> 1
1568
+ */
1569
+ static mrb_value
1570
+ io_fileno(mrb_state *mrb, mrb_value io)
1571
+ {
1572
+ int fd = mrb_io_fileno(mrb, io);
1573
+ return mrb_fixnum_value(fd);
1574
+ }
1575
+
1576
+ #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
1577
+ /*
1578
+ * call-seq:
1579
+ * ios.close_on_exec? -> true or false
1580
+ *
1581
+ * Returns `true` if the `FD_CLOEXEC` flag is set for the `IO` object, `false`
1582
+ * otherwise.
1583
+ *
1584
+ * f = IO.new(1, "w")
1585
+ * f.close_on_exec? #=> true
1586
+ */
1587
+ static mrb_value
1588
+ io_close_on_exec_p(mrb_state *mrb, mrb_value io)
1589
+ {
1590
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1591
+ int ret;
1592
+
1593
+ if (fptr->fd2 >= 0) {
1594
+ if ((ret = fcntl(fptr->fd2, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
1595
+ if (!(ret & FD_CLOEXEC)) return mrb_false_value();
1596
+ }
1597
+
1598
+ if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
1599
+ if (!(ret & FD_CLOEXEC)) return mrb_false_value();
1600
+ return mrb_true_value();
1601
+ }
1602
+ #else
1603
+ # define io_close_on_exec_p mrb_notimplement_m
1604
+ #endif
1605
+
1606
+ #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
1607
+ /*
1608
+ * call-seq:
1609
+ * ios.close_on_exec = bool -> bool
1610
+ *
1611
+ * Sets the `FD_CLOEXEC` flag on the `IO` object.
1612
+ *
1613
+ * f = IO.new(1, "w")
1614
+ * f.close_on_exec = false
1615
+ * f.close_on_exec? #=> false
1616
+ */
1617
+ static mrb_value
1618
+ io_set_close_on_exec(mrb_state *mrb, mrb_value io)
1619
+ {
1620
+
1621
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1622
+ mrb_bool b;
1623
+
1624
+ mrb_get_args(mrb, "b", &b);
1625
+
1626
+ int flag = b ? FD_CLOEXEC : 0;
1627
+ int ret;
1628
+
1629
+ if (fptr->fd2 >= 0) {
1630
+ if ((ret = fcntl(fptr->fd2, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
1631
+ if ((ret & FD_CLOEXEC) != flag) {
1632
+ ret = (ret & ~FD_CLOEXEC) | flag;
1633
+ ret = fcntl(fptr->fd2, F_SETFD, ret);
1634
+
1635
+ if (ret == -1) mrb_sys_fail(mrb, "F_SETFD failed");
1636
+ }
1637
+ }
1638
+
1639
+ if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
1640
+ if ((ret & FD_CLOEXEC) != flag) {
1641
+ ret = (ret & ~FD_CLOEXEC) | flag;
1642
+ ret = fcntl(fptr->fd, F_SETFD, ret);
1643
+ if (ret == -1) mrb_sys_fail(mrb, "F_SETFD failed");
1644
+ }
1645
+
1646
+ return mrb_bool_value(b);
1647
+ }
1648
+ #else
1649
+ # define io_set_close_on_exec mrb_notimplement_m
1650
+ #endif
1651
+
1652
+ /*
1653
+ * call-seq:
1654
+ * ios.sync = bool -> bool
1655
+ *
1656
+ * Sets the sync mode for the `IO` object.
1657
+ *
1658
+ * If `true`, all output is immediately flushed to the underlying operating
1659
+ * system and is not buffered internally.
1660
+ *
1661
+ * f = File.new("testfile", "w")
1662
+ * f.sync = true
1663
+ */
1664
+ static mrb_value
1665
+ io_set_sync(mrb_state *mrb, mrb_value io)
1666
+ {
1667
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1668
+ mrb_bool b;
1669
+
1670
+ mrb_get_args(mrb, "b", &b);
1671
+ fptr->sync = b;
1672
+ return mrb_bool_value(b);
1673
+ }
1674
+
1675
+ /*
1676
+ * call-seq:
1677
+ * ios.sync -> true or false
1678
+ *
1679
+ * Returns the sync mode for the `IO` object.
1680
+ *
1681
+ * f = File.new("testfile", "w")
1682
+ * f.sync #=> false
1683
+ */
1684
+ static mrb_value
1685
+ io_sync(mrb_state *mrb, mrb_value io)
1686
+ {
1687
+ struct mrb_io *fptr = io_get_open_fptr(mrb, io);
1688
+ return mrb_bool_value(fptr->sync);
1689
+ }
1690
+
1691
+ #ifndef MRB_USE_IO_PREAD_PWRITE
1692
+ # define io_pread mrb_notimplement_m
1693
+ # define io_pwrite mrb_notimplement_m
1694
+ #else
1695
+ static off_t
1696
+ value2off(mrb_state *mrb, mrb_value offv)
1697
+ {
1698
+ return (off_t)mrb_as_int(mrb, offv);
1699
+ }
1700
+
1701
+ /*
1702
+ * call-seq:
1703
+ * pread(maxlen, offset, outbuf = "") -> outbuf
1704
+ */
1705
+ static mrb_value
1706
+ io_pread(mrb_state *mrb, mrb_value io)
1707
+ {
1708
+ mrb_value buf = mrb_nil_value();
1709
+ mrb_value off;
1710
+ mrb_int maxlen;
1711
+
1712
+ mrb_get_args(mrb, "io|S!", &maxlen, &off, &buf);
1713
+
1714
+ return io_read_common(mrb, pread, io, buf, maxlen, value2off(mrb, off));
1715
+ }
1716
+
1717
+ /*
1718
+ * call-seq:
1719
+ * pwrite(buffer, offset) -> wrote_bytes
1720
+ */
1721
+ static mrb_value
1722
+ io_pwrite(mrb_state *mrb, mrb_value io)
1723
+ {
1724
+ mrb_value buf, off;
1725
+
1726
+ mrb_get_args(mrb, "So", &buf, &off);
1727
+
1728
+ return io_write_common(mrb, pwrite, io_get_write_fptr(mrb, io), RSTRING_PTR(buf), RSTRING_LEN(buf), value2off(mrb, off));
1729
+ }
1730
+ #endif /* MRB_USE_IO_PREAD_PWRITE */
1731
+
1732
+ /*
1733
+ * call-seq:
1734
+ * ios.ungetc(string) -> nil
1735
+ *
1736
+ * Pushes back characters (passed as a parameter) onto ios, such that a
1737
+ * subsequent buffered character read will return it. Has no effect with
1738
+ * unbuffered reads (such as IO#sysread).
1739
+ *
1740
+ * f = File.new("testfile") #=> #<File:testfile>
1741
+ * c = f.getc #=> "H"
1742
+ * f.ungetc(c) #=> nil
1743
+ * f.getc #=> "H"
1744
+ */
1745
+ /* Helper function for ungetc operations with raw data */
1746
+ static void
1747
+ io_unget_data(mrb_state *mrb, struct mrb_io *fptr, const char *ptr, mrb_int len)
1748
+ {
1749
+ struct mrb_io_buf *buf = fptr->buf;
1750
+
1751
+ if (len > SHRT_MAX) {
1752
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string too long to ungetc");
1753
+ }
1754
+ if (buf->len + len > SHRT_MAX) {
1755
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "total ungetc buffer exceeds maximum size");
1756
+ }
1757
+ if (buf->len + len > MRB_IO_BUF_SIZE) {
1758
+ fptr->buf = (struct mrb_io_buf*)mrb_realloc(mrb, buf, sizeof(struct mrb_io_buf)+buf->len+len-MRB_IO_BUF_SIZE);
1759
+ buf = fptr->buf;
1760
+ }
1761
+ memmove(buf->mem+len, buf->mem+buf->start, buf->len);
1762
+ memcpy(buf->mem, ptr, len);
1763
+ buf->start = 0;
1764
+ buf->len += (short)len;
1765
+ }
1766
+
1767
+ static mrb_value
1768
+ io_ungetc(mrb_state *mrb, mrb_value io)
1769
+ {
1770
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
1771
+ mrb_value str;
1772
+
1773
+ mrb_get_args(mrb, "S", &str);
1774
+ io_unget_data(mrb, fptr, RSTRING_PTR(str), RSTRING_LEN(str));
1775
+ return mrb_nil_value();
1776
+ }
1777
+
1778
+ /*
1779
+ * call-seq:
1780
+ * ios.ungetbyte(string) -> nil
1781
+ * ios.ungetbyte(integer) -> nil
1782
+ *
1783
+ * Pushes back bytes (passed as a parameter) onto ios, such that a subsequent
1784
+ * buffered character read will return it. Only one byte may be pushed back
1785
+ * before a subsequent read operation (that is, you will be able to read only
1786
+ * the last of several bytes that have been pushed back). Has no effect with
1787
+ * unbuffered reads (such as IO#sysread).
1788
+ */
1789
+ static mrb_value
1790
+ io_ungetbyte(mrb_state *mrb, mrb_value io)
1791
+ {
1792
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
1793
+ mrb_value c = mrb_get_arg1(mrb);
1794
+ unsigned char byte_val;
1795
+
1796
+ if (mrb_string_p(c)) {
1797
+ if (RSTRING_LEN(c) == 0) {
1798
+ return mrb_nil_value(); /* Empty string, do nothing */
1799
+ }
1800
+ byte_val = (unsigned char)RSTRING_PTR(c)[0];
1801
+ }
1802
+ else {
1803
+ mrb_int val = mrb_integer(c);
1804
+ byte_val = (unsigned char)(val & 0xff);
1805
+ }
1806
+
1807
+ /* Use helper function with single byte */
1808
+ io_unget_data(mrb, fptr, (const char*)&byte_val, 1);
1809
+ return mrb_nil_value();
1810
+ }
1811
+
1812
+ static void
1813
+ io_buf_reset(struct mrb_io_buf *buf)
1814
+ {
1815
+ buf->start = 0;
1816
+ buf->len = 0;
1817
+ }
1818
+
1819
+ static void
1820
+ io_buf_shift(struct mrb_io_buf *buf, mrb_int n)
1821
+ {
1822
+ mrb_assert(n <= SHRT_MAX);
1823
+ buf->start += (short)n;
1824
+ buf->len -= (short)n;
1825
+ }
1826
+
1827
+ #ifdef MRB_UTF8_STRING
1828
+ static void
1829
+ io_fill_buf_comp(mrb_state *mrb, struct mrb_io *fptr)
1830
+ {
1831
+ struct mrb_io_buf *buf = fptr->buf;
1832
+ int keep = buf->len;
1833
+
1834
+ memmove(buf->mem, buf->mem+buf->start, keep);
1835
+ int n = read(fptr->fd, buf->mem+keep, MRB_IO_BUF_SIZE-keep);
1836
+ if (n < 0) mrb_sys_fail(mrb, 0);
1837
+ if (n == 0) fptr->eof = 1;
1838
+ buf->start = 0;
1839
+ buf->len += (short)n;
1840
+ }
1841
+ #endif
1842
+
1843
+ static void
1844
+ io_fill_buf(mrb_state *mrb, struct mrb_io *fptr)
1845
+ {
1846
+ struct mrb_io_buf *buf = fptr->buf;
1847
+
1848
+ if (buf->len > 0) return;
1849
+
1850
+ int n = read(fptr->fd, buf->mem, MRB_IO_BUF_SIZE);
1851
+ if (n < 0) mrb_sys_fail(mrb, 0);
1852
+ if (n == 0) fptr->eof = 1;
1853
+ buf->start = 0;
1854
+ buf->len = (short)n;
1855
+ }
1856
+
1857
+ static mrb_value
1858
+ io_eof(mrb_state *mrb, mrb_value io)
1859
+ {
1860
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
1861
+
1862
+ if (fptr->eof) return mrb_true_value();
1863
+ if (fptr->buf->len > 0) return mrb_false_value();
1864
+ io_fill_buf(mrb, fptr);
1865
+ return mrb_bool_value(fptr->eof);
1866
+ }
1867
+
1868
+ static void
1869
+ io_buf_cat(mrb_state *mrb, mrb_value outbuf, struct mrb_io_buf *buf, mrb_int n)
1870
+ {
1871
+ mrb_assert(n <= buf->len);
1872
+ mrb_str_cat(mrb, outbuf, buf->mem+buf->start, n);
1873
+ io_buf_shift(buf, n);
1874
+ }
1875
+
1876
+ static void
1877
+ io_buf_cat_all(mrb_state *mrb, mrb_value outbuf, struct mrb_io_buf *buf)
1878
+ {
1879
+ mrb_str_cat(mrb, outbuf, buf->mem+buf->start, buf->len);
1880
+ io_buf_reset(buf);
1881
+ }
1882
+
1883
+ static mrb_value
1884
+ io_read_all(mrb_state *mrb, struct mrb_io *fptr, mrb_value outbuf)
1885
+ {
1886
+ for (;;) {
1887
+ io_fill_buf(mrb, fptr);
1888
+ if (fptr->eof) {
1889
+ return outbuf;
1890
+ }
1891
+ io_buf_cat_all(mrb, outbuf, fptr->buf);
1892
+ }
1893
+ }
1894
+
1895
+ static mrb_value
1896
+ io_reset_outbuf(mrb_state *mrb, mrb_value outbuf, mrb_int len)
1897
+ {
1898
+ if (mrb_nil_p(outbuf)) {
1899
+ outbuf = mrb_str_new(mrb, NULL, 0);
1900
+ }
1901
+ else {
1902
+ mrb_str_modify(mrb, mrb_str_ptr(outbuf));
1903
+ RSTR_SET_LEN(mrb_str_ptr(outbuf), 0);
1904
+ }
1905
+ return outbuf;
1906
+ }
1907
+
1908
+ /*
1909
+ * call-seq:
1910
+ * ios.read(length = nil, outbuf = "") -> string, outbuf, or nil
1911
+ *
1912
+ * Reads `length` bytes from the I/O stream.
1913
+ *
1914
+ * If `length` is `nil`, it reads until end of file.
1915
+ * If `outbuf` is given, it will be used as the buffer.
1916
+ *
1917
+ * f = File.new("testfile")
1918
+ * f.read(16) #=> "This is line one"
1919
+ */
1920
+ static mrb_value
1921
+ io_read(mrb_state *mrb, mrb_value io)
1922
+ {
1923
+ mrb_value outbuf = mrb_nil_value();
1924
+ mrb_value len;
1925
+ mrb_int length = 0;
1926
+ mrb_bool length_given;
1927
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
1928
+
1929
+ mrb_get_args(mrb, "|o?S", &len, &length_given, &outbuf);
1930
+ if (length_given) {
1931
+ if (mrb_nil_p(len)) {
1932
+ length_given = FALSE;
1933
+ }
1934
+ else {
1935
+ length = mrb_as_int(mrb, len);
1936
+ if (length < 0) {
1937
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative length %i given", length);
1938
+ }
1939
+ if (length == 0) {
1940
+ return io_reset_outbuf(mrb, outbuf, 0);
1941
+ }
1942
+ }
1943
+ }
1944
+
1945
+ outbuf = io_reset_outbuf(mrb, outbuf, MRB_IO_BUF_SIZE);
1946
+ if (!length_given) { /* read as much as possible */
1947
+ return io_read_all(mrb, fptr, outbuf);
1948
+ }
1949
+
1950
+ struct mrb_io_buf *buf = fptr->buf;
1951
+
1952
+ for (;;) {
1953
+ io_fill_buf(mrb, fptr);
1954
+ if (fptr->eof || length == 0) {
1955
+ if (RSTRING_LEN(outbuf) == 0)
1956
+ return mrb_nil_value();
1957
+ return outbuf;
1958
+ }
1959
+ if (buf->len < length) {
1960
+ length -= buf->len;
1961
+ io_buf_cat_all(mrb, outbuf, buf);
1962
+ }
1963
+ else {
1964
+ io_buf_cat(mrb, outbuf, buf, length);
1965
+ return outbuf;
1966
+ }
1967
+ }
1968
+ }
1969
+
1970
+ static mrb_int
1971
+ io_find_index(struct mrb_io *fptr, const char *rs, mrb_int rslen)
1972
+ {
1973
+ struct mrb_io_buf *buf = fptr->buf;
1974
+
1975
+ mrb_assert(rslen > 0);
1976
+ const char c = rs[0];
1977
+ const mrb_int limit = buf->len - rslen + 1;
1978
+ const char *p = buf->mem+buf->start;
1979
+ for (mrb_int i=0; i<limit; i++) {
1980
+ if (p[i] == c && (rslen == 1 || memcmp(p+i, rs, rslen) == 0)) {
1981
+ return i;
1982
+ }
1983
+ }
1984
+ return -1;
1985
+ }
1986
+
1987
+ static mrb_value
1988
+ io_gets(mrb_state *mrb, mrb_value io)
1989
+ {
1990
+ mrb_value rs = mrb_nil_value();
1991
+ mrb_bool rs_given = FALSE; /* newline break */
1992
+ mrb_int limit = 0;
1993
+ mrb_bool limit_given = FALSE; /* no limit */
1994
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
1995
+ struct mrb_io_buf *buf = fptr->buf;
1996
+
1997
+ mrb_get_args(mrb, "|o?i?", &rs, &rs_given, &limit, &limit_given);
1998
+
1999
+ if (limit_given == FALSE) {
2000
+ if (rs_given) {
2001
+ if (mrb_nil_p(rs)) {
2002
+ rs_given = FALSE;
2003
+ }
2004
+ else if (mrb_integer_p(rs)) {
2005
+ limit = mrb_integer(rs);
2006
+ limit_given = TRUE;
2007
+ rs = mrb_nil_value();
2008
+ }
2009
+ else if (!mrb_string_p(rs)) {
2010
+ mrb_ensure_int_type(mrb, rs);
2011
+ }
2012
+ }
2013
+ }
2014
+ if (rs_given) {
2015
+ if (mrb_nil_p(rs)) {
2016
+ rs_given = FALSE;
2017
+ }
2018
+ else {
2019
+ mrb_ensure_string_type(mrb, rs);
2020
+ if (RSTRING_LEN(rs) == 0) { /* paragraph mode */
2021
+ rs = mrb_str_new_lit(mrb, "\n\n");
2022
+ }
2023
+ }
2024
+ }
2025
+ else {
2026
+ rs = mrb_str_new_lit(mrb, "\n");
2027
+ rs_given = TRUE;
2028
+ }
2029
+
2030
+ /* from now on rs_given==FALSE means no RS */
2031
+ if (mrb_nil_p(rs) && !limit_given) {
2032
+ return io_read_all(mrb, fptr, mrb_str_new_capa(mrb, MRB_IO_BUF_SIZE));
2033
+ }
2034
+
2035
+ io_fill_buf(mrb, fptr);
2036
+ if (fptr->eof) return mrb_nil_value();
2037
+
2038
+ mrb_value outbuf;
2039
+ if (limit_given) {
2040
+ if (limit < 0) {
2041
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative length %i given", limit);
2042
+ }
2043
+ if (limit == 0) return mrb_str_new(mrb, NULL, 0);
2044
+ outbuf = mrb_str_new_capa(mrb, limit);
2045
+ }
2046
+ else {
2047
+ outbuf = mrb_str_new(mrb, NULL, 0);
2048
+ }
2049
+
2050
+ for (;;) {
2051
+ if (rs_given) { /* with RS */
2052
+ mrb_int rslen = RSTRING_LEN(rs);
2053
+ mrb_int idx = io_find_index(fptr, RSTRING_PTR(rs), rslen);
2054
+ if (idx >= 0) { /* found */
2055
+ mrb_int n = idx+rslen;
2056
+ if (limit_given && limit < n) {
2057
+ n = limit;
2058
+ }
2059
+ io_buf_cat(mrb, outbuf, buf, n);
2060
+ return outbuf;
2061
+ }
2062
+ }
2063
+ if (limit_given) {
2064
+ if (limit <= buf->len) {
2065
+ io_buf_cat(mrb, outbuf, buf, limit);
2066
+ return outbuf;
2067
+ }
2068
+ limit -= buf->len;
2069
+ }
2070
+ io_buf_cat_all(mrb, outbuf, buf);
2071
+ io_fill_buf(mrb, fptr);
2072
+ if (fptr->eof) {
2073
+ if (RSTRING_LEN(outbuf) == 0) return mrb_nil_value();
2074
+ return outbuf;
2075
+ }
2076
+ }
2077
+ }
2078
+
2079
+ static mrb_value
2080
+ io_readline(mrb_state *mrb, mrb_value io)
2081
+ {
2082
+ mrb_value result = io_gets(mrb, io);
2083
+ if (mrb_nil_p(result)) {
2084
+ eof_error(mrb);
2085
+ }
2086
+ return result;
2087
+ }
2088
+
2089
+ static mrb_value
2090
+ io_readlines(mrb_state *mrb, mrb_value io)
2091
+ {
2092
+ mrb_value ary = mrb_ary_new(mrb);
2093
+ for (;;) {
2094
+ mrb_value line = io_gets(mrb, io);
2095
+
2096
+ if (mrb_nil_p(line)) return ary;
2097
+ mrb_ary_push(mrb, ary, line);
2098
+ }
2099
+ }
2100
+
2101
+ static mrb_value
2102
+ io_getc(mrb_state *mrb, mrb_value io)
2103
+ {
2104
+ mrb_int len = 1;
2105
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
2106
+ struct mrb_io_buf *buf = fptr->buf;
2107
+
2108
+ io_fill_buf(mrb, fptr);
2109
+ if (fptr->eof) return mrb_nil_value();
2110
+ #ifdef MRB_UTF8_STRING
2111
+ const char *p = &buf->mem[buf->start];
2112
+ if ((*p) & 0x80) {
2113
+ len = mrb_utf8len(p, p+buf->len);
2114
+ if (len == 1 && buf->len < 4) { /* partial UTF-8 */
2115
+ io_fill_buf_comp(mrb, fptr);
2116
+ p = &buf->mem[buf->start];
2117
+ len = mrb_utf8len(p, p+buf->len);
2118
+ }
2119
+ }
2120
+ #endif
2121
+ mrb_value str = mrb_str_new(mrb, buf->mem+buf->start, len);
2122
+ io_buf_shift(buf, len);
2123
+ return str;
2124
+ }
2125
+
2126
+ static mrb_value
2127
+ io_readchar(mrb_state *mrb, mrb_value io)
2128
+ {
2129
+ mrb_value result = io_getc(mrb, io);
2130
+ if (mrb_nil_p(result)) {
2131
+ eof_error(mrb);
2132
+ }
2133
+ return result;
2134
+ }
2135
+
2136
+ /*
2137
+ * call-seq:
2138
+ * ios.getbyte -> integer or nil
2139
+ *
2140
+ * Reads a byte from the `IO` stream.
2141
+ *
2142
+ * Returns the byte as an integer, or `nil` at end of file.
2143
+ *
2144
+ * f = File.new("testfile")
2145
+ * f.getbyte #=> 72
2146
+ */
2147
+ static mrb_value
2148
+ io_getbyte(mrb_state *mrb, mrb_value io)
2149
+ {
2150
+ struct mrb_io *fptr = io_get_read_fptr(mrb, io);
2151
+ struct mrb_io_buf *buf = fptr->buf;
2152
+
2153
+ io_fill_buf(mrb, fptr);
2154
+ if (fptr->eof) return mrb_nil_value();
2155
+
2156
+ unsigned char c = buf->mem[buf->start];
2157
+ io_buf_shift(buf, 1);
2158
+ return mrb_int_value(mrb, (mrb_int)c);
2159
+ }
2160
+
2161
+ /*
2162
+ * call-seq:
2163
+ * ios.readbyte -> integer
2164
+ *
2165
+ * Reads a byte from the `IO` stream.
2166
+ *
2167
+ * Returns the byte as an integer. Raises `EOFError` at end of file.
2168
+ *
2169
+ * f = File.new("testfile")
2170
+ * f.readbyte #=> 72
2171
+ */
2172
+ static mrb_value
2173
+ io_readbyte(mrb_state *mrb, mrb_value io)
2174
+ {
2175
+ mrb_value result = io_getbyte(mrb, io);
2176
+ if (mrb_nil_p(result)) {
2177
+ eof_error(mrb);
2178
+ }
2179
+ return result;
2180
+ }
2181
+
2182
+ /*
2183
+ * call-seq:
2184
+ * ios.flush -> ios
2185
+ *
2186
+ * Flushes any buffered data within the `IO` object to the underlying
2187
+ * operating system.
2188
+ *
2189
+ * $stdout.print "no newline"
2190
+ * $stdout.flush
2191
+ */
2192
+ static mrb_value
2193
+ io_flush(mrb_state *mrb, mrb_value io)
2194
+ {
2195
+ io_get_open_fptr(mrb, io);
2196
+ return io;
2197
+ }
2198
+
2199
+ /* ---------------------------*/
2200
+ static const mrb_mt_entry io_rom_entries[] = {
2201
+ MRB_MT_ENTRY(io_init, MRB_SYM(initialize), MRB_ARGS_ARG(1,2)),
2202
+ MRB_MT_ENTRY(io_init_copy, MRB_SYM(initialize_copy), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE),
2203
+ MRB_MT_ENTRY(io_isatty, MRB_SYM(isatty), MRB_ARGS_NONE()),
2204
+ MRB_MT_ENTRY(io_eof, MRB_SYM_Q(eof), MRB_ARGS_NONE()), /* 15.2.20.5.6 */
2205
+ MRB_MT_ENTRY(io_getc, MRB_SYM(getc), MRB_ARGS_NONE()), /* 15.2.20.5.8 */
2206
+ MRB_MT_ENTRY(io_gets, MRB_SYM(gets), MRB_ARGS_OPT(2)), /* 15.2.20.5.9 */
2207
+ MRB_MT_ENTRY(io_read, MRB_SYM(read), MRB_ARGS_OPT(2)), /* 15.2.20.5.14 */
2208
+ MRB_MT_ENTRY(io_readchar, MRB_SYM(readchar), MRB_ARGS_NONE()), /* 15.2.20.5.15 */
2209
+ MRB_MT_ENTRY(io_readline, MRB_SYM(readline), MRB_ARGS_OPT(2)), /* 15.2.20.5.16 */
2210
+ MRB_MT_ENTRY(io_readlines, MRB_SYM(readlines), MRB_ARGS_OPT(2)), /* 15.2.20.5.17 */
2211
+ MRB_MT_ENTRY(io_sync, MRB_SYM(sync), MRB_ARGS_NONE()), /* 15.2.20.5.18 */
2212
+ MRB_MT_ENTRY(io_set_sync, MRB_SYM_E(sync), MRB_ARGS_REQ(1)), /* 15.2.20.5.19 */
2213
+ MRB_MT_ENTRY(io_sysread, MRB_SYM(sysread), MRB_ARGS_ARG(1,1)),
2214
+ MRB_MT_ENTRY(io_sysseek, MRB_SYM(sysseek), MRB_ARGS_ARG(1,1)),
2215
+ MRB_MT_ENTRY(io_syswrite, MRB_SYM(syswrite), MRB_ARGS_REQ(1)),
2216
+ MRB_MT_ENTRY(io_seek, MRB_SYM(seek), MRB_ARGS_ARG(1,1)),
2217
+ MRB_MT_ENTRY(io_close, MRB_SYM(close), MRB_ARGS_NONE()), /* 15.2.20.5.1 */
2218
+ MRB_MT_ENTRY(io_close_write, MRB_SYM(close_write), MRB_ARGS_NONE()),
2219
+ MRB_MT_ENTRY(io_set_close_on_exec, MRB_SYM_E(close_on_exec), MRB_ARGS_REQ(1)),
2220
+ MRB_MT_ENTRY(io_close_on_exec_p, MRB_SYM_Q(close_on_exec), MRB_ARGS_NONE()),
2221
+ MRB_MT_ENTRY(io_closed, MRB_SYM_Q(closed), MRB_ARGS_NONE()), /* 15.2.20.5.2 */
2222
+ MRB_MT_ENTRY(io_flush, MRB_SYM(flush), MRB_ARGS_NONE()), /* 15.2.20.5.7 */
2223
+ MRB_MT_ENTRY(io_ungetc, MRB_SYM(ungetc), MRB_ARGS_REQ(1)),
2224
+ MRB_MT_ENTRY(io_ungetbyte, MRB_SYM(ungetbyte), MRB_ARGS_REQ(1)),
2225
+ MRB_MT_ENTRY(io_pos, MRB_SYM(pos), MRB_ARGS_NONE()),
2226
+ MRB_MT_ENTRY(io_pid, MRB_SYM(pid), MRB_ARGS_NONE()),
2227
+ MRB_MT_ENTRY(io_fileno, MRB_SYM(fileno), MRB_ARGS_NONE()),
2228
+ MRB_MT_ENTRY(io_write, MRB_SYM(write), MRB_ARGS_ANY()), /* 15.2.20.5.20 */
2229
+ MRB_MT_ENTRY(io_puts, MRB_SYM(puts), MRB_ARGS_ANY()),
2230
+ MRB_MT_ENTRY(io_print, MRB_SYM(print), MRB_ARGS_ANY()),
2231
+ MRB_MT_ENTRY(io_putc, MRB_SYM(putc), MRB_ARGS_REQ(1)),
2232
+ MRB_MT_ENTRY(io_lshift, MRB_OPSYM(lshift), MRB_ARGS_REQ(1)),
2233
+ MRB_MT_ENTRY(io_pread, MRB_SYM(pread), MRB_ARGS_ANY()), /* Ruby 2.5 feature */
2234
+ MRB_MT_ENTRY(io_pwrite, MRB_SYM(pwrite), MRB_ARGS_ANY()), /* Ruby 2.5 feature */
2235
+ MRB_MT_ENTRY(io_getbyte, MRB_SYM(getbyte), MRB_ARGS_NONE()),
2236
+ MRB_MT_ENTRY(io_readbyte, MRB_SYM(readbyte), MRB_ARGS_NONE()),
2237
+ };
2238
+
2239
+ void
2240
+ mrb_init_io(mrb_state *mrb)
2241
+ {
2242
+ struct RClass *io = mrb_define_class_id(mrb, MRB_SYM(IO), mrb->object_class);
2243
+ MRB_SET_INSTANCE_TT(io, MRB_TT_CDATA);
2244
+
2245
+ mrb_include_module(mrb, io, mrb_module_get_id(mrb, MRB_SYM(Enumerable))); /* 15.2.20.3 */
2246
+ mrb_define_class_method_id(mrb, io, MRB_SYM(_popen), io_s_popen, MRB_ARGS_ARG(1,2));
2247
+ mrb_define_class_method_id(mrb, io, MRB_SYM(_sysclose), io_s_sysclose, MRB_ARGS_REQ(1));
2248
+ mrb_define_class_method_id(mrb, io, MRB_SYM(for_fd), io_s_for_fd, MRB_ARGS_ARG(1,2));
2249
+ mrb_define_class_method_id(mrb, io, MRB_SYM(select), io_s_select, MRB_ARGS_ARG(1,3));
2250
+ mrb_define_class_method_id(mrb, io, MRB_SYM(sysopen), io_s_sysopen, MRB_ARGS_ARG(1,2));
2251
+ #if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
2252
+ mrb_define_class_method_id(mrb, io, MRB_SYM(_pipe), io_s_pipe, MRB_ARGS_NONE());
2253
+ #endif
2254
+
2255
+ MRB_MT_INIT_ROM(mrb, io, io_rom_entries);
2256
+
2257
+ mrb_define_const_id(mrb, io, MRB_SYM(SEEK_SET), mrb_fixnum_value(SEEK_SET));
2258
+ mrb_define_const_id(mrb, io, MRB_SYM(SEEK_CUR), mrb_fixnum_value(SEEK_CUR));
2259
+ mrb_define_const_id(mrb, io, MRB_SYM(SEEK_END), mrb_fixnum_value(SEEK_END));
2260
+ }