summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/mruby
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/.gitignore5
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/Makefile14
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/README.md55
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/mrbgem.rake4
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/mrblib/digest.rb46
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/run_test.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/src/digest.c1007
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/src/picohash.h751
-rw-r--r--web/server/h2o/libh2o/deps/mruby-digest/test/digest.rb203
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/.gitignore5
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/README.md56
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/mrbgem.rake6
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/mrblib/dir.rb64
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/run_test.rb26
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/src/Win/dirent.c154
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/src/dir.c281
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/test/dir.rb128
-rw-r--r--web/server/h2o/libh2o/deps/mruby-dir/test/dirtest.c114
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/.gitignore1
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/README.md52
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/mrbgem.rake4
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/mrblib/env.rb16
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/run_test.rb27
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/src/env.c243
-rw-r--r--web/server/h2o/libh2o/deps/mruby-env/test/env_test.rb121
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/.gitignore1
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/README.md27
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/mrbgem.rake6
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/run_test.rb26
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/src/errno.c175
-rwxr-xr-xweb/server/h2o/libh2o/deps/mruby-errno/src/gen.rb25
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/src/known_errors.def145
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_def.cstub725
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_e2c.cstub435
-rw-r--r--web/server/h2o/libh2o/deps/mruby-errno/test/errno.rb60
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/.gitignore5
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/.travis.yml15
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/.travis_build_config.rb7
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/README.md82
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/appveyor.yml19
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/config.h.in19
-rwxr-xr-xweb/server/h2o/libh2o/deps/mruby-file-stat/configure4320
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/configure.ac20
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/mrbgem.rake32
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/ext.rb5
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/file-stat.rb52
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/src/file-stat.c873
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/test/executable0
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.c30
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.rb369
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/test/io.rb7
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/test/readable0
-rw-r--r--web/server/h2o/libh2o/deps/mruby-file-stat/test/writable0
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/.gitignore1
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/README.md87
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/mrbgem.rake6
-rwxr-xr-xweb/server/h2o/libh2o/deps/mruby-iijson/mrblib/json.rb129
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/mrblib/to_json.rb47
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/run_test.rb23
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/src/json.c641
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/test/json.rb145
-rw-r--r--web/server/h2o/libh2o/deps/mruby-iijson/test/testjson.c11
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/.travis.yml6
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/LICENSE19
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/README.md28
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/Rakefile28
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/build_config_sample.rb17
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/mrbgem.rake6
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/mrblib/input_stream.rb16
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c278
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.h19
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/test/input_stream.rb111
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/.gitignore1
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/README.md185
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/include/mruby/ext/io.h36
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/mrbgem.rake16
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/mrblib/file.rb173
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/mrblib/file_constants.rb29
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/mrblib/io.rb372
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/mrblib/kernel.rb15
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/run_test.rb25
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/src/file.c325
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/src/file_test.c365
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/src/io.c941
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/src/mruby_io_gem.c20
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/test/file.rb108
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/test/file_test.rb95
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/test/gc_filedes.sh4
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/test/io.rb416
-rw-r--r--web/server/h2o/libh2o/deps/mruby-io/test/mruby_io_test.c141
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis.yml10
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis_config.rb21
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/Onigmo-6.1.1.tar.gzbin0 -> 821378 bytes
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/README.md45
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/mrbgem.rake113
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/mrblib/onig_regexp.rb140
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/src/mruby_onig_regexp.c1064
-rw-r--r--web/server/h2o/libh2o/deps/mruby-onig-regexp/test/mruby_onig_regexp.rb398
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/.gitignore5
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/README.md67
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/mrbgem.rake6
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/packtest.rb154
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/run_test.rb26
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/src/pack.c1144
-rw-r--r--web/server/h2o/libh2o/deps/mruby-pack/test/pack.rb147
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/.gitignore1
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/.travis.yml2
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/README.md59
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/mrbgem.rake15
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/mrblib/require.rb97
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/run_test.rb29
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/src/require.c208
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/test/d/required.rb19
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/test/require.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/test/test.rb34
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/test/test2.rb139
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/test/test_context.rb33
-rw-r--r--web/server/h2o/libh2o/deps/mruby-require/test/test_nest_loop.rb58
-rw-r--r--web/server/h2o/libh2o/deps/mruby/.gitignore26
-rw-r--r--web/server/h2o/libh2o/deps/mruby/.gitlab-ci.yml3214
-rw-r--r--web/server/h2o/libh2o/deps/mruby/.travis.yml18
-rw-r--r--web/server/h2o/libh2o/deps/mruby/.yardopts17
-rw-r--r--web/server/h2o/libh2o/deps/mruby/AUTHORS39
-rw-r--r--web/server/h2o/libh2o/deps/mruby/CONTRIBUTING.md68
-rw-r--r--web/server/h2o/libh2o/deps/mruby/LEGAL6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/MITL20
-rw-r--r--web/server/h2o/libh2o/deps/mruby/Makefile17
-rw-r--r--web/server/h2o/libh2o/deps/mruby/NEWS13
-rw-r--r--web/server/h2o/libh2o/deps/mruby/README.md92
-rw-r--r--web/server/h2o/libh2o/deps/mruby/Rakefile152
-rw-r--r--web/server/h2o/libh2o/deps/mruby/TODO10
-rw-r--r--web/server/h2o/libh2o/deps/mruby/appveyor.yml27
-rw-r--r--web/server/h2o/libh2o/deps/mruby/appveyor_config.rb50
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/bm_ao_render.rb314
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/bm_app_lc_fizzbuzz.rb52
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/bm_fib.rb7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/bm_so_lists.rb47
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/build_config_boxing.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/build_config_cc.rb13
-rw-r--r--web/server/h2o/libh2o/deps/mruby/benchmark/plot.gpl5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/bin/.gitkeep0
-rw-r--r--web/server/h2o/libh2o/deps/mruby/build_config.rb152
-rw-r--r--web/server/h2o/libh2o/deps/mruby/doc/guides/compile.md488
-rw-r--r--web/server/h2o/libh2o/deps/mruby/doc/guides/debugger.md370
-rw-r--r--web/server/h2o/libh2o/deps/mruby/doc/guides/gc-arena-howto.md177
-rw-r--r--web/server/h2o/libh2o/deps/mruby/doc/guides/mrbconf.md146
-rw-r--r--web/server/h2o/libh2o/deps/mruby/doc/guides/mrbgems.md340
-rw-r--r--web/server/h2o/libh2o/deps/mruby/doc/limitations.md208
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md4
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake23
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c20
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/README.md4
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/mrbgem.rake23
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/src/example.c20
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.c7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.rb3
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/README.md4
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake25
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/test/example.rb3
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_ArduinoDue.rb90
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelEdison.rb69
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelGalileo.rb106
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_RX630.rb81
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_arm64-v8a.rb26
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi.rb26
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi_v7a_neon_hard.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_chipKITMax32.rb86
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mrbconf.h130
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby.h1257
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/array.h279
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_nan.h98
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_no.h48
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_word.h120
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/class.h92
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/common.h72
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/compile.h195
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/data.h75
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/debug.h66
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/dump.h196
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/error.h76
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/gc.h80
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/hash.h182
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/irep.h64
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/istruct.h47
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/khash.h274
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/numeric.h155
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/object.h43
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/opcode.h161
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/proc.h83
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/range.h49
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/re.h16
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/string.h430
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/throw.h55
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/value.h303
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/variable.h138
-rw-r--r--web/server/h2o/libh2o/deps/mruby/include/mruby/version.h110
-rw-r--r--web/server/h2o/libh2o/deps/mruby/lib/mruby-core-ext.rb79
-rw-r--r--web/server/h2o/libh2o/deps/mruby/lib/mruby/build.rb355
-rw-r--r--web/server/h2o/libh2o/deps/mruby/lib/mruby/build/command.rb324
-rw-r--r--web/server/h2o/libh2o/deps/mruby/lib/mruby/build/load_gems.rb122
-rw-r--r--web/server/h2o/libh2o/deps/mruby/lib/mruby/gem.rb459
-rw-r--r--web/server/h2o/libh2o/deps/mruby/lib/mruby/source.rb30
-rwxr-xr-xweb/server/h2o/libh2o/deps/mruby/minirake484
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/default.gembox79
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/full-core.gembox9
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrblib/array.rb811
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/src/array.c244
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/test/array.rb383
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb286
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb701
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake9
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c507
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h26
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c239
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h14
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c78
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h13
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c436
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c501
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c58
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c64
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c759
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h165
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h16
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h20
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb12
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake33
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c584
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake16
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c336
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake30
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config20
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat42
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb60
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake12
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c254
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb73
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/mrbgem.rake6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c155
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/src/class.c30
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/test/module.rb34
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb30
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/codegen.c3026
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/keywords50
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/lex.def212
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/node.h118
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/parse.y6652
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/mrbgem.rake40
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb711
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/test/enum.rb171
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb163
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb53
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrbgem.rake7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb645
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/test/enumerator.rb546
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/mrbgem.rake10
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/src/exception.c100
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.c59
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.rb55
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/mrbgem.rake7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/src/eval.c346
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/test/eval.rb101
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/src/mruby-exit.c24
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c420
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb208
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrbgem.rake8
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb477
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c88
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/test/hash.rb294
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.c83
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.rb151
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/src/kernel.c243
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb86
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/src/math.c783
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/test/math.rb152
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb17
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c30
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrblib/object.rb19
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/src/object.c106
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/nil.rb11
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/object.rb53
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c187
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/test/objectspace.rb60
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrblib/print.rb64
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/src/print.c64
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb42
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/src/proc.c173
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.c56
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.rb96
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.c224
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.h80
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c349
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.h12
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/test/random.rb88
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrblib/range.rb31
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/src/range.c176
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/test/range.rb32
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrblib/string.rb9
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/kernel.c30
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/sprintf.c1113
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/test/sprintf.rb109
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrbgem.rake6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrblib/string.rb355
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/src/string.c685
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/test/string.rb667
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrblib/struct.rb103
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c714
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/test/struct.rb212
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb65
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/src/symbol.c64
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb48
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/README.md7
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/driver.c172
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/init_mrbtest.c38
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/mrbgem.rake187
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrblib/time.rb9
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/src/time.c869
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/test/time.rb228
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake5
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb11
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb24
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/00class.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/10error.rb56
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/array.rb243
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/compar.rb84
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/enum.rb348
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/hash.rb358
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/init_mrblib.c11
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/kernel.rb50
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/mrblib.rake18
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/numeric.rb173
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/range.rb67
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrblib/string.rb275
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mruby-source.gemspec18
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/array.c1249
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/backtrace.c281
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/class.c2474
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/codedump.c474
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/compar.c13
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/crc.c39
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/debug.c217
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/dump.c1100
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/enum.c14
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/error.c503
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/error.h3
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/etc.c234
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/ext/.gitkeep0
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/fmt_fp.c372
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/gc.c1824
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/hash.c905
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/init.c51
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/kernel.c1238
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/load.c704
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/mruby_core.rake19
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/numeric.c1355
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/object.c610
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/opcode.h2
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/pool.c198
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/print.c47
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/proc.c294
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/range.c442
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/state.c303
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/string.c3013
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/symbol.c494
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/value_array.h27
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/variable.c987
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/version.c17
-rw-r--r--web/server/h2o/libh2o/deps/mruby/src/vm.c2909
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/benchmark.rake91
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/gitlab.rake118
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/libmruby.rake24
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/mrbgems.rake96
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/toolchains/android.rake321
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/toolchains/clang.rake9
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/toolchains/gcc.rake58
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/toolchains/openwrt.rake38
-rw-r--r--web/server/h2o/libh2o/deps/mruby/tasks/toolchains/visualcpp.rake68
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/assert.rb248
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/bintest.rb33
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/report.rb4
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/argumenterror.rb16
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/array.rb394
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/basicobject.rb11
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/bs_block.rb521
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/bs_literal.rb38
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/class.rb451
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/codegen.rb197
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/comparable.rb80
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/ensure.rb54
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/enumerable.rb134
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/exception.rb422
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/false.rb31
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/float.rb205
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/gc.rb45
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/hash.rb375
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/indexerror.rb6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/integer.rb268
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/iterations.rb61
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/kernel.rb643
-rwxr-xr-xweb/server/h2o/libh2o/deps/mruby/test/t/lang.rb74
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/literals.rb337
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/localjumperror.rb13
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/methods.rb109
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/module.rb914
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/nameerror.rb28
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/nil.rb39
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/nomethoderror.rb22
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/numeric.rb43
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/object.rb11
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/proc.rb180
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/range.rb95
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/rangeerror.rb6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/regexperror.rb4
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/runtimeerror.rb6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/standarderror.rb6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/string.rb727
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/superclass.rb47
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/symbol.rb30
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/syntax.rb468
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/true.rb31
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/typeerror.rb6
-rw-r--r--web/server/h2o/libh2o/deps/mruby/test/t/unicode.rb39
-rw-r--r--web/server/h2o/libh2o/deps/mruby/travis_config.rb53
454 files changed, 96933 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/.gitignore b/web/server/h2o/libh2o/deps/mruby-digest/.gitignore
new file mode 100644
index 00000000..55ef3162
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/.gitignore
@@ -0,0 +1,5 @@
+gem_*
+gem-*
+mrb-*.a
+src/*.o
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/.travis.yml b/web/server/h2o/libh2o/deps/mruby-digest/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/Makefile b/web/server/h2o/libh2o/deps/mruby-digest/Makefile
new file mode 100644
index 00000000..21f8afe0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/Makefile
@@ -0,0 +1,14 @@
+GEM := mruby-digest
+
+include $(MAKEFILE_4_GEM)
+
+GEM_C_FILES := $(wildcard $(SRC_DIR)/*.c)
+GEM_OBJECTS := $(patsubst %.c, %.o, $(GEM_C_FILES))
+
+GEM_RB_FILES := $(wildcard $(MRB_DIR)/*.rb)
+
+gem-all : $(GEM_OBJECTS) gem-c-and-rb-files
+
+gem-clean : gem-clean-c-and-rb-files
+
+gem-test : gem-test-c-and-rb-files
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/README.md b/web/server/h2o/libh2o/deps/mruby-digest/README.md
new file mode 100644
index 00000000..2ae6552c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/README.md
@@ -0,0 +1,55 @@
+mruby-digest
+=========
+
+This library is a fork of [github.com/iij/mruby-digest](https://github.com/iij/mruby-digest).
+Unlike the original, this fork does not have any dependencies; it uses [picohash](https://github.com/kazuho/picohash) - a public domain library for hash calculation.
+
+## Features
+
+Message Digest and HMAC classes are available. They are compatible with CRuby's ones.
+
+- Digest::MD5, Digest::RMD160, Digest::SHA1, Digest::SHA256, Digest::SHA384 and
+ Digest::SHA512
+ - Note: some of them are not available if libcrypto.a does not support them on your system.
+- Digest::HMAC
+
+## Install
+ - add conf.gem line to `build_config.rb`
+
+```ruby
+MRuby::Build.new do |conf|
+
+ # ... (snip) ...
+
+ conf.gem :git => 'https://github.com/iij/mruby-digest.git'
+end
+```
+
+## Usage
+```ruby
+Digest::MD5.digest('ruby')
+Digest::MD5.hexdigest('ruby')
+```
+
+## License
+
+Copyright (c) 2012-2015 Internet Initiative Japan Inc., Kazuho Oku
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-digest/mrbgem.rake
new file mode 100644
index 00000000..9324f169
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-digest') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Internet Initiative Japan Inc.'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/mrblib/digest.rb b/web/server/h2o/libh2o/deps/mruby-digest/mrblib/digest.rb
new file mode 100644
index 00000000..7779f54b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/mrblib/digest.rb
@@ -0,0 +1,46 @@
+if Object.const_defined? :Digest
+module Digest
+ class Base
+ def self.digest(data)
+ self.new.update(data).digest
+ end
+ def self.file(path)
+ self.new.update(File.open(path).read)
+ end
+ def self.hexdigest(data)
+ self.new.update(data).hexdigest
+ end
+ def ==(other)
+ if other.kind_of? String
+ self.hexdigest == other
+ else
+ self.digest == other.digest
+ end
+ end
+ def file(path)
+ self.update(File.open(path).read)
+ end
+ def hexdigest!
+ x = self.hexdigest
+ self.reset
+ x
+ end
+
+ alias length digest_length
+ alias size digest_length
+ alias to_s hexdigest
+ alias << update
+ end
+
+ class HMAC
+ def self.digest(data, key, digest)
+ self.new(key, digest).update(data).digest
+ end
+ def self.hexdigest(data, key, digest)
+ self.new(key, digest).update(data).hexdigest
+ end
+
+ alias << update
+ end
+end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/run_test.rb b/web/server/h2o/libh2o/deps/mruby-digest/run_test.rb
new file mode 100644
index 00000000..3401ed86
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/run_test.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+gemname = File.basename(File.dirname(File.expand_path __FILE__))
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+ build_args = ['all', 'test'] if build_args.nil? or build_args.empty?
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ enable_debug
+ enable_test
+ conf.gembox 'default'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/src/digest.c b/web/server/h2o/libh2o/deps/mruby-digest/src/digest.c
new file mode 100644
index 00000000..634376d9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/src/digest.c
@@ -0,0 +1,1007 @@
+/*
+** digest.c - Digest and subclasses
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include "mruby.h"
+
+#define USE_DIGEST_PICOHASH
+
+#if !defined(USE_DIGEST_PICOHASH)
+#elif defined(__APPLE__)
+#define USE_DIGEST_OSX_COMMONCRYPTO
+#else
+#define USE_DIGEST_OPENSSL
+#endif
+
+#if defined(USE_DIGEST_PICOHASH)
+#include "picohash.h"
+#elif defined(USE_DIGEST_OPENSSL)
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#elif defined(USE_DIGEST_OSX_COMMONCRYPTO)
+#include <CommonCrypto/CommonDigest.h>
+#include <CommonCrypto/CommonHMAC.h>
+#else
+#error "define USE_DIGEST_PICOHASH or USE_DIGEST_OPENSSL or USE_DIGEST_OSX_COMMONCRYPTO"
+#endif
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include "mruby/array.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+
+#define TYPESYM "__type__"
+
+
+/*
+ * library-independent layer API
+ */
+enum {
+ MD_TYPE_MD5,
+ MD_TYPE_RMD160,
+ MD_TYPE_SHA1,
+ MD_TYPE_SHA256,
+ MD_TYPE_SHA384,
+ MD_TYPE_SHA512,
+};
+
+struct mrb_md;
+struct mrb_hmac;
+
+static void lib_init(void);
+static int lib_md_block_length(const struct mrb_md *);
+static mrb_value lib_md_digest(mrb_state *, const struct mrb_md *);
+static mrb_value lib_md_digest_bang(mrb_state *, struct mrb_md *);
+static int lib_md_digest_length(const struct mrb_md *);
+static void lib_md_free(mrb_state *, void *);
+static void lib_md_init(mrb_state *, struct mrb_md *, int);
+static void lib_md_init_copy(mrb_state *, struct mrb_md *, struct mrb_md *);
+static void lib_md_reset(mrb_state *, struct mrb_md *);
+static void lib_md_update(mrb_state *, struct mrb_md *, unsigned char *, mrb_int);
+
+static mrb_value lib_hmac_digest(mrb_state *, const struct mrb_hmac *);
+static int lib_hmac_block_length(const struct mrb_hmac *);
+static int lib_hmac_digest_length(const struct mrb_hmac *);
+static void lib_hmac_free(mrb_state *, void *);
+static void lib_hmac_init(mrb_state *, struct mrb_hmac *, int, const unsigned char *, mrb_int);
+static void lib_hmac_update(mrb_state *, struct mrb_hmac *, unsigned char *, mrb_int);
+
+
+#if defined(USE_DIGEST_PICOHASH)
+
+#define HAVE_MD5
+#define HAVE_SHA1
+
+struct mrb_md {
+ picohash_ctx_t ctx;
+};
+
+struct mrb_hmac {
+ picohash_ctx_t ctx;
+};
+
+static void
+lib_md_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_md *md = ptr;
+ if (md != NULL)
+ mrb_free(mrb, md);
+}
+
+static void
+lib_hmac_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_hmac *hmac = ptr;
+ if (hmac != NULL)
+ mrb_free(mrb, hmac);
+}
+
+static struct mrb_data_type mrb_md_type = { "MD", lib_md_free };
+static struct mrb_data_type mrb_hmac_type = { "HMAC", lib_hmac_free };
+
+static void
+lib_init(void)
+{
+}
+
+static int
+lib_md_block_length(const struct mrb_md *md)
+{
+ return (int)md->ctx.block_length;
+}
+
+static mrb_value
+lib_md_digest(mrb_state *mrb, const struct mrb_md *md)
+{
+ picohash_ctx_t ctx;
+ unsigned char mdstr[PICOHASH_MAX_DIGEST_LENGTH];
+
+ ctx = md->ctx;
+ picohash_final(&ctx, mdstr);
+ return mrb_str_new(mrb, (char *)mdstr, ctx.digest_length);
+}
+
+static mrb_value
+lib_md_digest_bang(mrb_state *mrb, struct mrb_md *md)
+{
+ unsigned char mdstr[PICOHASH_MAX_DIGEST_LENGTH];
+
+ picohash_final(&md->ctx, mdstr);
+ picohash_reset(&md->ctx);
+ return mrb_str_new(mrb, (char *)mdstr, md->ctx.digest_length);
+}
+
+static int
+lib_md_digest_length(const struct mrb_md *md)
+{
+ return md->ctx.digest_length;
+}
+
+static void (*md_type_md(int type))(picohash_ctx_t *)
+{
+ switch (type) {
+ case MD_TYPE_MD5: return picohash_init_md5;
+ case MD_TYPE_SHA1: return picohash_init_sha1;
+ default: return NULL;
+ }
+}
+
+static void
+lib_md_init(mrb_state *mrb, struct mrb_md *md, int type)
+{
+ void (*ctor)(picohash_ctx_t *) = md_type_md(type);
+ if (ctor == NULL)
+ mrb_raise(mrb, E_NOTIMP_ERROR, "not supported");
+ ctor(&md->ctx);
+}
+
+static void
+lib_md_init_copy(mrb_state *mrb, struct mrb_md *mdnew, struct mrb_md *mdold)
+{
+ mdnew->ctx = mdold->ctx;
+ picohash_reset(&mdnew->ctx);
+}
+
+static void
+lib_md_reset(mrb_state *mrb, struct mrb_md *md)
+{
+ picohash_reset(&md->ctx);
+}
+
+static void
+lib_md_update(mrb_state *mrb, struct mrb_md *md, unsigned char *str, mrb_int len)
+{
+#if MRB_INT_MAX > SIZE_MAX
+ if (len > SIZE_MAX)
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string (not supported yet)");
+#endif
+ picohash_update(&md->ctx, str, len);
+}
+
+static mrb_value
+lib_hmac_digest(mrb_state *mrb, const struct mrb_hmac *hmac)
+{
+ picohash_ctx_t ctx;
+ unsigned char mdstr[PICOHASH_MAX_DIGEST_LENGTH];
+
+ ctx = hmac->ctx;
+ picohash_final(&ctx, mdstr);
+ return mrb_str_new(mrb, (char *)mdstr, ctx.digest_length);
+}
+
+static int
+lib_hmac_block_length(const struct mrb_hmac *hmac)
+{
+ return hmac->ctx.block_length;
+}
+
+static int
+lib_hmac_digest_length(const struct mrb_hmac *hmac)
+{
+ return hmac->ctx.digest_length;
+}
+
+static void
+lib_hmac_init(mrb_state *mrb, struct mrb_hmac *hmac, int type, const unsigned char *key, mrb_int keylen)
+{
+ void (*ctor)(picohash_ctx_t *) = md_type_md(type);
+
+#if MRB_INT_MAX > SIZE_MAX
+ if (keylen > SIZE_MAX)
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long key");
+#endif
+ if (ctor == NULL)
+ mrb_raise(mrb, E_NOTIMP_ERROR, "not supported");
+ picohash_init_hmac(&hmac->ctx, ctor, key, keylen);
+}
+
+static void
+lib_hmac_update(mrb_state *mrb, struct mrb_hmac *hmac, unsigned char *data, mrb_int len)
+{
+#if MRB_INT_MAX > SIZE_MAX
+ if (len > SIZE_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string (not supported yet)");
+ }
+#endif
+ picohash_update(&hmac->ctx, data, len);
+}
+
+#elif defined(USE_DIGEST_OPENSSL)
+/*
+ * OpenSSL Implementation
+ */
+
+#define HAVE_MD5
+
+#ifndef OPENSSL_NO_RIPEMD
+#define HAVE_RMD160
+#endif
+
+#define HAVE_SHA1
+#ifdef SHA256_DIGEST_LENGTH
+#define HAVE_SHA256
+#endif
+#ifdef SHA512_DIGEST_LENGTH
+#define HAVE_SHA384
+#define HAVE_SHA512
+#endif
+
+struct mrb_md {
+ EVP_MD_CTX *ctx;
+};
+
+struct mrb_hmac {
+ HMAC_CTX ctx;
+ const EVP_MD *md;
+};
+
+static void
+lib_md_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_md *md = ptr;
+
+ if (md != NULL) {
+ if (md->ctx != NULL) {
+ EVP_MD_CTX_destroy(md->ctx);
+ }
+ mrb_free(mrb, md);
+ }
+}
+
+static void
+lib_hmac_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_hmac *hmac = ptr;
+
+ if (hmac != NULL) {
+ HMAC_CTX_cleanup(&hmac->ctx);
+ mrb_free(mrb, hmac);
+ }
+}
+
+static struct mrb_data_type mrb_md_type = { "MD", lib_md_free };
+static struct mrb_data_type mrb_hmac_type = { "HMAC", lib_hmac_free };
+
+static void
+lib_init(void)
+{
+ OpenSSL_add_all_digests();
+}
+
+static int
+lib_md_block_length(const struct mrb_md *md)
+{
+ return EVP_MD_CTX_block_size(md->ctx);
+}
+
+static mrb_value
+lib_md_digest(mrb_state *mrb, const struct mrb_md *md)
+{
+ EVP_MD_CTX ctx;
+ unsigned int mdlen;
+ unsigned char mdstr[EVP_MAX_MD_SIZE];
+
+ EVP_MD_CTX_copy(&ctx, md->ctx);
+ EVP_DigestFinal(&ctx, mdstr, &mdlen);
+ return mrb_str_new(mrb, (char *)mdstr, mdlen);
+}
+
+static mrb_value
+lib_md_digest_bang(mrb_state *mrb, struct mrb_md *md)
+{
+ unsigned int mdlen;
+ unsigned char mdstr[EVP_MAX_MD_SIZE];
+
+ EVP_DigestFinal_ex(md->ctx, mdstr, &mdlen);
+ EVP_DigestInit_ex(md->ctx, EVP_MD_CTX_md(md->ctx), NULL);
+ return mrb_str_new(mrb, (char *)mdstr, mdlen);
+}
+
+static int
+lib_md_digest_length(const struct mrb_md *md)
+{
+ return EVP_MD_CTX_size(md->ctx);
+}
+
+const EVP_MD *
+md_type_md(int type)
+{
+ switch (type) {
+ case MD_TYPE_MD5: return EVP_md5();
+#ifdef HAVE_RMD160
+ case MD_TYPE_RMD160: return EVP_ripemd160();
+#endif
+ case MD_TYPE_SHA1: return EVP_sha1();
+#ifdef HAVE_SHA256
+ case MD_TYPE_SHA256: return EVP_sha256();
+#endif
+#ifdef HAVE_SHA512
+ case MD_TYPE_SHA384: return EVP_sha384();
+ case MD_TYPE_SHA512: return EVP_sha512();
+#endif
+ default: return NULL;
+ }
+}
+
+static void
+lib_md_init(mrb_state *mrb, struct mrb_md *md, int type)
+{
+ const EVP_MD *evpmd;
+
+ md->ctx = NULL;
+ evpmd = md_type_md(type);
+ if (!evpmd) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "not supported");
+ }
+ md->ctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(md->ctx, evpmd, NULL);
+}
+
+static void
+lib_md_init_copy(mrb_state *mrb, struct mrb_md *mdnew, struct mrb_md *mdold)
+{
+ mdnew->ctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdnew->ctx, EVP_MD_CTX_md(mdold->ctx), NULL);
+}
+
+static void
+lib_md_reset(mrb_state *mrb, struct mrb_md *md)
+{
+ //EVP_MD_CTX_init(&md->ctx);
+ EVP_DigestInit_ex(md->ctx, EVP_MD_CTX_md(md->ctx), NULL);
+}
+
+static void
+lib_md_update(mrb_state *mrb, struct mrb_md *md, unsigned char *str, mrb_int len)
+{
+#if MRB_INT_MAX > SIZE_MAX
+ if (len > SIZE_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string (not supported yet)");
+ }
+#endif
+ EVP_DigestUpdate(md->ctx, str, len);
+}
+
+static mrb_value
+lib_hmac_digest(mrb_state *mrb, const struct mrb_hmac *hmac)
+{
+ HMAC_CTX ctx;
+ unsigned int mdlen;
+ unsigned char mdstr[EVP_MAX_MD_SIZE];
+
+ memcpy(&ctx, &hmac->ctx, sizeof(ctx));
+ HMAC_Final(&ctx, mdstr, &mdlen);
+ return mrb_str_new(mrb, (char *)mdstr, mdlen);
+}
+
+static int
+lib_hmac_block_length(const struct mrb_hmac *hmac)
+{
+ return EVP_MD_block_size(hmac->md);
+}
+
+static int
+lib_hmac_digest_length(const struct mrb_hmac *hmac)
+{
+ return EVP_MD_size(hmac->md);
+}
+
+static void
+lib_hmac_init(mrb_state *mrb, struct mrb_hmac *hmac, int type, const unsigned char *key, mrb_int keylen)
+{
+#if MRB_INT_MAX > INT_MAX
+ if (keylen > INT_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long key");
+ }
+#endif
+ hmac->md = md_type_md(type);
+ HMAC_CTX_init(&hmac->ctx);
+ HMAC_Init_ex(&hmac->ctx, key, keylen, hmac->md, NULL);
+}
+
+static void
+lib_hmac_update(mrb_state *mrb, struct mrb_hmac *hmac, unsigned char *data, mrb_int len)
+{
+#if MRB_INT_MAX > INT_MAX
+ if (len > INT_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string (not supported yet)");
+ }
+#endif
+ HMAC_Update(&hmac->ctx, data, len);
+}
+
+#elif defined(USE_DIGEST_OSX_COMMONCRYPTO)
+/*
+ * Mac OS X CommonCrypto Implementation
+ */
+
+#define HAVE_MD5
+/* #define HAVE_RMD160 */
+#define HAVE_SHA1
+#define HAVE_SHA256
+#define HAVE_SHA384
+#define HAVE_SHA512
+
+struct mrb_md {
+ int type;
+ void *ctx;
+ int ctx_size;
+};
+
+struct mrb_hmac {
+ int type;
+ CCHmacContext ctx;
+};
+
+static int
+md_ctx_size(int type)
+{
+ switch (type) {
+ case MD_TYPE_MD5: return sizeof(CC_MD5_CTX);
+ case MD_TYPE_SHA1: return sizeof(CC_SHA1_CTX);
+ case MD_TYPE_SHA256: return sizeof(CC_SHA256_CTX);
+ case MD_TYPE_SHA384: return sizeof(CC_SHA512_CTX); /* ! */
+ case MD_TYPE_SHA512: return sizeof(CC_SHA512_CTX);
+ default: return 0;
+ }
+}
+
+static void
+lib_md_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_md *md = ptr;
+
+ memset(md->ctx, 0, md_ctx_size(md->type));
+ mrb_free(mrb, md->ctx);
+ mrb_free(mrb, md);
+}
+
+static void
+lib_hmac_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_hmac *hmac = ptr;
+
+ memset(&hmac->ctx, 0, sizeof(hmac->ctx));
+ mrb_free(mrb, hmac);
+}
+
+static struct mrb_data_type mrb_md_type = { "MD", lib_md_free };
+static struct mrb_data_type mrb_hmac_type = { "HMAC", lib_hmac_free };
+
+#define MAX_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
+
+union ctx_union {
+ CC_MD5_CTX md5;
+ CC_SHA1_CTX sha1;
+ CC_SHA256_CTX sha256;
+ /* we don't have CC_SHA384_CTX! */
+ CC_SHA512_CTX sha512;
+};
+
+static void
+lib_init(void)
+{
+}
+
+static int
+md_block_length(int type)
+{
+ switch (type) {
+ case MD_TYPE_MD5: return CC_MD5_BLOCK_BYTES;
+ case MD_TYPE_SHA1: return CC_SHA1_BLOCK_BYTES;
+ case MD_TYPE_SHA256: return CC_SHA256_BLOCK_BYTES;
+ case MD_TYPE_SHA384: return CC_SHA384_BLOCK_BYTES;
+ case MD_TYPE_SHA512: return CC_SHA512_BLOCK_BYTES;
+ default: return 0;
+ }
+}
+
+static int
+lib_md_block_length(const struct mrb_md *md)
+{
+ return md_block_length(md->type);
+}
+
+static void
+md_init(int type, void *ctxp)
+{
+ switch (type) {
+ case MD_TYPE_MD5: CC_MD5_Init(ctxp); break;
+ case MD_TYPE_SHA1: CC_SHA1_Init(ctxp); break;
+ case MD_TYPE_SHA256: CC_SHA256_Init(ctxp); break;
+ case MD_TYPE_SHA384: CC_SHA384_Init(ctxp); break;
+ case MD_TYPE_SHA512: CC_SHA512_Init(ctxp); break;
+ default: break;
+ }
+}
+
+static void
+md_final(int type, unsigned char *str, void *ctx)
+{
+ switch (type) {
+ case MD_TYPE_MD5: CC_MD5_Final(str, ctx); break;
+ case MD_TYPE_SHA1: CC_SHA1_Final(str, ctx); break;
+ case MD_TYPE_SHA256: CC_SHA256_Final(str, ctx); break;
+ case MD_TYPE_SHA384: CC_SHA384_Final(str, ctx); break;
+ case MD_TYPE_SHA512: CC_SHA512_Final(str, ctx); break;
+ default: break;
+ }
+}
+
+static int
+md_digest_length(int type)
+{
+ switch (type) {
+ case MD_TYPE_MD5: return 16;
+ case MD_TYPE_SHA1: return 20;
+ case MD_TYPE_SHA256: return 32;
+ case MD_TYPE_SHA384: return 48;
+ case MD_TYPE_SHA512: return 64;
+ default: return 0;
+ }
+}
+
+static mrb_value
+lib_md_digest(mrb_state *mrb, const struct mrb_md *md)
+{
+ union ctx_union ctx;
+ unsigned char mdstr[MAX_DIGEST_LENGTH];
+
+ memcpy(&ctx, md->ctx, md_ctx_size(md->type));
+ md_final(md->type, mdstr, &ctx);
+ return mrb_str_new(mrb, (char *)mdstr, md_digest_length(md->type));
+}
+
+static mrb_value
+lib_md_digest_bang(mrb_state *mrb, struct mrb_md *md)
+{
+ unsigned char mdstr[MAX_DIGEST_LENGTH];
+
+ md_final(md->type, mdstr, md->ctx);
+ md_init(md->type, md->ctx);
+ return mrb_str_new(mrb, (char *)mdstr, md_digest_length(md->type));
+}
+
+static int
+lib_md_digest_length(const struct mrb_md *md)
+{
+ return md_digest_length(md->type);
+}
+
+static void
+lib_md_init(mrb_state *mrb, struct mrb_md *md, int type)
+{
+ int ctxsize;
+
+ ctxsize = md_ctx_size(type);
+ if (ctxsize == 0) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "not supported");
+ }
+ md->type = type;
+ md->ctx = NULL;
+ md->ctx = mrb_malloc(mrb, ctxsize);
+ md_init(type, md->ctx);
+}
+
+static void
+lib_md_init_copy(mrb_state *mrb, struct mrb_md *mdnew, struct mrb_md *mdold)
+{
+ lib_md_init(mrb, mdnew, mdold->type);
+}
+
+static void
+lib_md_reset(mrb_state *mrb, struct mrb_md *md)
+{
+ md_init(md->type, md->ctx);
+}
+
+static void
+lib_md_update(mrb_state *mrb, struct mrb_md *md, unsigned char *data, mrb_int len)
+{
+ if (sizeof(len) > sizeof(CC_LONG)) {
+ if (len != (CC_LONG)len) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string (not supported yet)");
+ }
+ }
+ switch (md->type) {
+ case MD_TYPE_MD5: CC_MD5_Update(md->ctx, data, len); break;
+ case MD_TYPE_SHA1: CC_SHA1_Update(md->ctx, data, len); break;
+ case MD_TYPE_SHA256: CC_SHA256_Update(md->ctx, data, len); break;
+ case MD_TYPE_SHA384: CC_SHA384_Update(md->ctx, data, len); break;
+ case MD_TYPE_SHA512: CC_SHA512_Update(md->ctx, data, len); break;
+ default: break;
+ }
+}
+
+static int
+lib_hmac_block_length(const struct mrb_hmac *hmac)
+{
+ return md_block_length(hmac->type);
+}
+
+static mrb_value
+lib_hmac_digest(mrb_state *mrb, const struct mrb_hmac *hmac)
+{
+ CCHmacContext ctx;
+ unsigned char str[MAX_DIGEST_LENGTH];
+
+ memcpy(&ctx, &hmac->ctx, sizeof(ctx));
+ CCHmacFinal(&ctx, str);
+ return mrb_str_new(mrb, (const char *)str, md_digest_length(hmac->type));
+}
+
+static int
+lib_hmac_digest_length(const struct mrb_hmac *hmac)
+{
+ return md_digest_length(hmac->type);
+}
+
+static void
+lib_hmac_init(mrb_state *mrb, struct mrb_hmac *hmac, int type, const unsigned char *key, mrb_int keylen)
+{
+ CCHmacAlgorithm algorithm;
+
+#if MRB_INT_MAX > SIZE_MAX
+ if (len > SIZE_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long key");
+ }
+#endif
+ switch (type) {
+ case MD_TYPE_MD5: algorithm = kCCHmacAlgMD5; break;
+ case MD_TYPE_SHA1: algorithm = kCCHmacAlgSHA1; break;
+ case MD_TYPE_SHA256: algorithm = kCCHmacAlgSHA256; break;
+ case MD_TYPE_SHA384: algorithm = kCCHmacAlgSHA384; break;
+ case MD_TYPE_SHA512: algorithm = kCCHmacAlgSHA512; break;
+ default:
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "mruby-digest: internal error: unexpected HMAC type: %S", mrb_fixnum_value(type));
+ algorithm = 0;
+ break;
+ }
+ hmac->type = type;
+ CCHmacInit(&hmac->ctx, algorithm, key, keylen);
+}
+
+static void
+lib_hmac_update(mrb_state *mrb, struct mrb_hmac *hmac, unsigned char *data, mrb_int len)
+{
+#if MRB_INT_MAX > SIZE_MAX
+ if (len > SIZE_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too long string");
+ }
+#endif
+ CCHmacUpdate(&hmac->ctx, data, len);
+}
+
+#endif
+
+static void
+basecheck(mrb_state *mrb, mrb_value self, struct mrb_md **mdp)
+{
+ struct RClass *c;
+ struct mrb_md *md;
+ mrb_value t;
+
+ c = mrb_obj_class(mrb, self);
+ t = mrb_const_get(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, TYPESYM));
+ if (mrb_nil_p(t)) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "Digest::Base is an abstract class");
+ }
+ md = (struct mrb_md *)DATA_PTR(self);
+ if (!md) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "no md found (BUG?)");
+ }
+ if (mdp) *mdp = md;
+}
+
+static mrb_value
+mrb_digest_block_length(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_md *md;
+
+ basecheck(mrb, self, &md);
+ return mrb_fixnum_value(lib_md_block_length(md));
+}
+
+static mrb_value
+mrb_digest_digest(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_md *md;
+
+ md = (struct mrb_md *)DATA_PTR(self);
+ if (!md) return mrb_nil_value();
+ return lib_md_digest(mrb, md);
+}
+
+static mrb_value
+mrb_digest_digest_bang(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_md *md;
+
+ md = (struct mrb_md *)DATA_PTR(self);
+ if (!md) return mrb_nil_value();
+ return lib_md_digest_bang(mrb, md);
+}
+
+static mrb_value
+mrb_digest_digest_length(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_md *md;
+
+ basecheck(mrb, self, &md);
+ return mrb_fixnum_value(lib_md_digest_length(md));
+}
+
+static mrb_value
+digest2hexdigest(mrb_state *mrb, mrb_value b)
+{
+ mrb_value h;
+ int i, len;
+ char *bp, buf[3];
+
+ bp = RSTRING_PTR(b);
+ len = RSTRING_LEN(b);
+ h = mrb_str_buf_new(mrb, len * 2);
+ for (i = 0; i < len; i++) {
+ snprintf(buf, sizeof(buf), "%02x", (unsigned char )bp[i]);
+ mrb_str_buf_cat(mrb, h, buf, 2);
+ }
+ return h;
+}
+
+static mrb_value
+mrb_digest_hexdigest(mrb_state *mrb, mrb_value self)
+{
+ return digest2hexdigest(mrb, mrb_digest_digest(mrb, self));
+}
+
+static mrb_value
+mrb_digest_init(mrb_state *mrb, mrb_value self)
+{
+ struct RClass *c;
+ struct mrb_md *md;
+ mrb_value t;
+
+ md = (struct mrb_md *)DATA_PTR(self);
+ if (md) {
+ lib_md_free(mrb, md);
+ }
+ DATA_TYPE(self) = &mrb_md_type;
+ DATA_PTR(self) = NULL;
+
+ c = mrb_obj_class(mrb, self);
+ if (!mrb_const_defined(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, TYPESYM))) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "Digest::Base is an abstract class");
+ }
+ t = mrb_const_get(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, TYPESYM));
+#if 0
+ if (lib_md_supported(t)) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "unknown algorithm");
+ }
+#endif
+
+ md = (struct mrb_md *)mrb_malloc(mrb, sizeof(*md));
+ DATA_PTR(self) = md;
+ lib_md_init(mrb, md, mrb_fixnum(t));
+ return self;
+}
+
+static mrb_value
+mrb_digest_init_copy(mrb_state *mrb, mrb_value copy)
+{
+ struct mrb_md *m1, *m2;
+ mrb_value src;
+
+ mrb_get_args(mrb, "o", &src);
+ if (mrb_obj_equal(mrb, copy, src)) return copy;
+ if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+ if (!DATA_PTR(copy)) {
+ DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct mrb_md));
+ DATA_TYPE(copy) = &mrb_md_type;
+ }
+ m1 = DATA_PTR(src);
+ m2 = DATA_PTR(copy);
+ lib_md_init_copy(mrb, m2, m1);
+ return copy;
+}
+
+static mrb_value
+mrb_digest_reset(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_md *md;
+
+ md = (struct mrb_md *)DATA_PTR(self);
+ if (!md) return mrb_nil_value();
+ lib_md_reset(mrb, md);
+ return self;
+}
+
+static mrb_value
+mrb_digest_update(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_md *md;
+ mrb_int len;
+ char *str;
+
+ md = (struct mrb_md *)DATA_PTR(self);
+ if (!md) return mrb_nil_value();
+ mrb_get_args(mrb, "s", &str, &len);
+ lib_md_update(mrb, md, (unsigned char *)str, len);
+ return self;
+}
+
+static mrb_value
+mrb_hmac_block_length(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_hmac *hmac;
+
+ hmac = (struct mrb_hmac *)DATA_PTR(self);
+ if (!hmac) return mrb_nil_value();
+ return mrb_fixnum_value(lib_hmac_block_length(hmac));
+}
+
+static mrb_value
+mrb_hmac_digest(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_hmac *hmac;
+
+ hmac = (struct mrb_hmac *)DATA_PTR(self);
+ if (!hmac) return mrb_nil_value();
+ return lib_hmac_digest(mrb, hmac);
+}
+
+static mrb_value
+mrb_hmac_digest_length(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_hmac *hmac;
+
+ hmac = (struct mrb_hmac *)DATA_PTR(self);
+ if (!hmac) return mrb_nil_value();
+ return mrb_fixnum_value(lib_hmac_digest_length(hmac));
+}
+
+static mrb_value
+mrb_hmac_hexdigest(mrb_state *mrb, mrb_value self)
+{
+ return digest2hexdigest(mrb, mrb_hmac_digest(mrb, self));
+}
+
+static mrb_value
+mrb_hmac_init(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_hmac *hmac;
+ mrb_value digest, t;
+ mrb_int keylen;
+ char *key;
+
+ hmac = (struct mrb_hmac *)DATA_PTR(self);
+ if (hmac) {
+ lib_hmac_free(mrb, hmac);
+ }
+ DATA_TYPE(self) = &mrb_hmac_type;
+ DATA_PTR(self) = NULL;
+
+ mrb_get_args(mrb, "so", &key, &keylen, &digest);
+ t = mrb_const_get(mrb, digest, mrb_intern_lit(mrb, TYPESYM));
+ if (mrb_nil_p(t)) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "not a digester");
+ }
+
+ hmac = (struct mrb_hmac *)mrb_malloc(mrb, sizeof(*hmac));
+ DATA_PTR(self) = hmac;
+ lib_hmac_init(mrb, hmac, mrb_fixnum(t), (unsigned char *)key, keylen);
+ return self;
+}
+
+static mrb_value
+mrb_hmac_init_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_raise(mrb, E_RUNTIME_ERROR, "cannot duplicate HMAC");
+ return copy;
+}
+
+static mrb_value
+mrb_hmac_update(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_hmac *hmac;
+ mrb_int len;
+ char *str;
+
+ hmac = (struct mrb_hmac *)DATA_PTR(self);
+ if (!hmac) return mrb_nil_value();
+ mrb_get_args(mrb, "s", &str, &len);
+ lib_hmac_update(mrb, hmac, (unsigned char *)str, len);
+ return self;
+}
+
+
+void
+mrb_mruby_digest_gem_init(mrb_state *mrb)
+{
+ struct RClass *b, *d, *h;
+
+ lib_init();
+
+ d = mrb_define_module(mrb, "Digest");
+
+ b = mrb_define_class_under(mrb, d, "Base", mrb->object_class);
+ mrb_define_method(mrb, b, "block_length", mrb_digest_block_length, MRB_ARGS_NONE());
+ mrb_define_method(mrb, b, "digest", mrb_digest_digest, MRB_ARGS_NONE());
+ mrb_define_method(mrb, b, "digest!", mrb_digest_digest_bang, MRB_ARGS_NONE()); /* XXX: can be defined in mrblib... */
+ mrb_define_method(mrb, b, "digest_length", mrb_digest_digest_length, MRB_ARGS_NONE());
+ //mrb_define_method(mrb, b, "file", mrb_digest_file, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, b, "hexdigest", mrb_digest_hexdigest, MRB_ARGS_NONE());
+ //mrb_define_method(mrb, b, "hexdigest!", mrb_digest_hexdigest_bang, MRB_ARGS_NONE()); /* XXX: can be defined in mrblib... */
+ mrb_define_method(mrb, b, "initialize", mrb_digest_init, MRB_ARGS_NONE());
+ mrb_define_method(mrb, b, "initialize_copy", mrb_digest_init_copy, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, b, "reset", mrb_digest_reset, MRB_ARGS_NONE());
+ mrb_define_method(mrb, b, "update", mrb_digest_update, MRB_ARGS_REQ(1));
+
+#define DEFCLASS(n) \
+do { \
+ struct RClass *a = mrb_define_class_under(mrb, d, #n, b); \
+ MRB_SET_INSTANCE_TT(a, MRB_TT_DATA); \
+ mrb_define_const(mrb, a, TYPESYM, mrb_fixnum_value(MD_TYPE_##n)); \
+} while (0)
+
+#ifdef HAVE_MD5
+ DEFCLASS(MD5);
+#endif
+#ifdef HAVE_RMD160
+ DEFCLASS(RMD160);
+#endif
+#ifdef HAVE_SHA1
+ DEFCLASS(SHA1);
+#endif
+#ifdef HAVE_SHA256
+ DEFCLASS(SHA256);
+#endif
+#ifdef HAVE_SHA384
+ DEFCLASS(SHA384);
+#endif
+#ifdef HAVE_SHA512
+ DEFCLASS(SHA512);
+#endif
+
+ h = mrb_define_class_under(mrb, d, "HMAC", mrb->object_class);
+ MRB_SET_INSTANCE_TT(h, MRB_TT_DATA);
+ mrb_define_method(mrb, h, "block_length", mrb_hmac_block_length, MRB_ARGS_NONE());
+ mrb_define_method(mrb, h, "digest", mrb_hmac_digest, MRB_ARGS_NONE());
+ mrb_define_method(mrb, h, "digest_length", mrb_hmac_digest_length, MRB_ARGS_NONE());
+ mrb_define_method(mrb, h, "hexdigest", mrb_hmac_hexdigest, MRB_ARGS_NONE());
+ mrb_define_method(mrb, h, "initialize", mrb_hmac_init, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, h, "initialize_copy", mrb_hmac_init_copy, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, h, "update", mrb_hmac_update, MRB_ARGS_REQ(1));
+}
+
+void
+mrb_mruby_digest_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/src/picohash.h b/web/server/h2o/libh2o/deps/mruby-digest/src/picohash.h
new file mode 100644
index 00000000..4c0206d9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/src/picohash.h
@@ -0,0 +1,751 @@
+/*
+ * The code is placed under public domain by Kazuho Oku <kazuhooku@gmail.com>.
+ *
+ * The MD5 implementation is based on a public domain implementation written by
+ * Solar Designer <solar@openwall.com> in 2001, which is used by Dovecot.
+ *
+ * The SHA1 implementation is based on a public domain implementation written
+ * by Wei Dai and other contributors for libcrypt, used also in liboauth.
+ *
+ * The SHA224/SHA256 implementation is based on a public domain implementation
+ * by Sam Hocevar <sam@hocevar.net> for LibTomCrypt.
+ */
+#ifndef _picohash_h_
+#define _picohash_h_
+
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+
+#ifdef __BIG_ENDIAN__
+#define _PICOHASH_BIG_ENDIAN
+#elif defined __LITTLE_ENDIAN__
+/* override */
+#elif defined __BYTE_ORDER
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _PICOHASH_BIG_ENDIAN
+#endif
+#else // ! defined __LITTLE_ENDIAN__
+#include <endian.h> // machine/endian.h
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _PICOHASH_BIG_ENDIAN
+#endif
+#endif
+
+#define PICOHASH_MD5_BLOCK_LENGTH 64
+#define PICOHASH_MD5_DIGEST_LENGTH 16
+
+typedef struct {
+ uint_fast32_t lo, hi;
+ uint_fast32_t a, b, c, d;
+ unsigned char buffer[64];
+ uint_fast32_t block[PICOHASH_MD5_DIGEST_LENGTH];
+} _picohash_md5_ctx_t;
+
+static void _picohash_md5_init(_picohash_md5_ctx_t *ctx);
+static void _picohash_md5_update(_picohash_md5_ctx_t *ctx, const void *data, size_t size);
+static void _picohash_md5_final(_picohash_md5_ctx_t *ctx, void *digest);
+
+#define PICOHASH_SHA1_BLOCK_LENGTH 64
+#define PICOHASH_SHA1_DIGEST_LENGTH 20
+
+typedef struct {
+ uint32_t buffer[PICOHASH_SHA1_BLOCK_LENGTH / 4];
+ uint32_t state[PICOHASH_SHA1_DIGEST_LENGTH / 4];
+ uint64_t byteCount;
+ uint8_t bufferOffset;
+} _picohash_sha1_ctx_t;
+
+static void _picohash_sha1_init(_picohash_sha1_ctx_t *ctx);
+static void _picohash_sha1_update(_picohash_sha1_ctx_t *ctx, const void *input, size_t len);
+static void _picohash_sha1_final(_picohash_sha1_ctx_t *ctx, void *digest);
+
+#define PICOHASH_SHA256_BLOCK_LENGTH 64
+#define PICOHASH_SHA256_DIGEST_LENGTH 32
+#define PICOHASH_SHA224_BLOCK_LENGTH PICOHASH_SHA256_BLOCK_LENGTH
+#define PICOHASH_SHA224_DIGEST_LENGTH 28
+
+typedef struct {
+ uint64_t length;
+ uint32_t state[PICOHASH_SHA256_DIGEST_LENGTH / 4];
+ uint32_t curlen;
+ unsigned char buf[PICOHASH_SHA256_BLOCK_LENGTH];
+} _picohash_sha256_ctx_t;
+
+static void _picohash_sha256_init(_picohash_sha256_ctx_t *ctx);
+static void _picohash_sha256_update(_picohash_sha256_ctx_t *ctx, const void *data, size_t len);
+static void _picohash_sha256_final(_picohash_sha256_ctx_t *ctx, void *digest);
+static void _picohash_sha224_init(_picohash_sha256_ctx_t *ctx);
+static void _picohash_sha224_final(_picohash_sha256_ctx_t *ctx, void *digest);
+
+#define PICOHASH_MAX_BLOCK_LENGTH 64
+#define PICOHASH_MAX_DIGEST_LENGTH 32
+
+typedef struct {
+ union {
+ _picohash_md5_ctx_t _md5;
+ _picohash_sha1_ctx_t _sha1;
+ _picohash_sha256_ctx_t _sha256;
+ };
+ size_t block_length;
+ size_t digest_length;
+ void (*_reset)(void *ctx);
+ void (*_update)(void *ctx, const void *input, size_t len);
+ void (*_final)(void *ctx, void *digest);
+ struct {
+ unsigned char key[PICOHASH_MAX_BLOCK_LENGTH];
+ void (*hash_reset)(void *ctx);
+ void (*hash_final)(void *ctx, void *digest);
+ } _hmac;
+} picohash_ctx_t;
+
+static void picohash_init_md5(picohash_ctx_t *ctx);
+static void picohash_init_sha1(picohash_ctx_t *ctx);
+static void picohash_init_sha224(picohash_ctx_t *ctx);
+static void picohash_init_sha256(picohash_ctx_t *ctx);
+static void picohash_update(picohash_ctx_t *ctx, const void *input, size_t len);
+static void picohash_final(picohash_ctx_t *ctx, void *digest);
+static void picohash_reset(picohash_ctx_t *ctx);
+
+static void picohash_init_hmac(picohash_ctx_t *ctx, void (*initf)(picohash_ctx_t *), const void *key, size_t key_len);
+
+/* following are private definitions */
+
+/*
+ * The basic MD5 functions.
+ *
+ * F is optimized compared to its RFC 1321 definition just like in Colin
+ * Plumb's implementation.
+ */
+#define _PICOHASH_MD5_F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define _PICOHASH_MD5_G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define _PICOHASH_MD5_H(x, y, z) ((x) ^ (y) ^ (z))
+#define _PICOHASH_MD5_I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define _PICOHASH_MD5_STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them
+ * in a properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures which tolerate unaligned
+ * memory accesses is just an optimization. Nothing will break if it
+ * doesn't work.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define _PICOHASH_MD5_SET(n) (*(const uint32_t *)&ptr[(n)*4])
+#define _PICOHASH_MD5_GET(n) _PICOHASH_MD5_SET(n)
+#else
+#define _PICOHASH_MD5_SET(n) \
+ (ctx->block[(n)] = (uint_fast32_t)ptr[(n)*4] | ((uint_fast32_t)ptr[(n)*4 + 1] << 8) | ((uint_fast32_t)ptr[(n)*4 + 2] << 16) | \
+ ((uint_fast32_t)ptr[(n)*4 + 3] << 24))
+#define _PICOHASH_MD5_GET(n) (ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update
+ * the bit counters. There're no alignment requirements.
+ */
+static const void *_picohash_md5_body(_picohash_md5_ctx_t *ctx, const void *data, size_t size)
+{
+ const unsigned char *ptr;
+ uint_fast32_t a, b, c, d;
+ uint_fast32_t saved_a, saved_b, saved_c, saved_d;
+
+ ptr = data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+ /* Round 1 */
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, a, b, c, d, _PICOHASH_MD5_SET(0), 0xd76aa478, 7)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, d, a, b, c, _PICOHASH_MD5_SET(1), 0xe8c7b756, 12)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, c, d, a, b, _PICOHASH_MD5_SET(2), 0x242070db, 17)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, b, c, d, a, _PICOHASH_MD5_SET(3), 0xc1bdceee, 22)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, a, b, c, d, _PICOHASH_MD5_SET(4), 0xf57c0faf, 7)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, d, a, b, c, _PICOHASH_MD5_SET(5), 0x4787c62a, 12)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, c, d, a, b, _PICOHASH_MD5_SET(6), 0xa8304613, 17)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, b, c, d, a, _PICOHASH_MD5_SET(7), 0xfd469501, 22)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, a, b, c, d, _PICOHASH_MD5_SET(8), 0x698098d8, 7)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, d, a, b, c, _PICOHASH_MD5_SET(9), 0x8b44f7af, 12)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, c, d, a, b, _PICOHASH_MD5_SET(10), 0xffff5bb1, 17)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, b, c, d, a, _PICOHASH_MD5_SET(11), 0x895cd7be, 22)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, a, b, c, d, _PICOHASH_MD5_SET(12), 0x6b901122, 7)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, d, a, b, c, _PICOHASH_MD5_SET(13), 0xfd987193, 12)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, c, d, a, b, _PICOHASH_MD5_SET(14), 0xa679438e, 17)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_F, b, c, d, a, _PICOHASH_MD5_SET(15), 0x49b40821, 22)
+
+ /* Round 2 */
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, a, b, c, d, _PICOHASH_MD5_GET(1), 0xf61e2562, 5)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, d, a, b, c, _PICOHASH_MD5_GET(6), 0xc040b340, 9)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, c, d, a, b, _PICOHASH_MD5_GET(11), 0x265e5a51, 14)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, b, c, d, a, _PICOHASH_MD5_GET(0), 0xe9b6c7aa, 20)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, a, b, c, d, _PICOHASH_MD5_GET(5), 0xd62f105d, 5)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, d, a, b, c, _PICOHASH_MD5_GET(10), 0x02441453, 9)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, c, d, a, b, _PICOHASH_MD5_GET(15), 0xd8a1e681, 14)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, b, c, d, a, _PICOHASH_MD5_GET(4), 0xe7d3fbc8, 20)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, a, b, c, d, _PICOHASH_MD5_GET(9), 0x21e1cde6, 5)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, d, a, b, c, _PICOHASH_MD5_GET(14), 0xc33707d6, 9)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, c, d, a, b, _PICOHASH_MD5_GET(3), 0xf4d50d87, 14)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, b, c, d, a, _PICOHASH_MD5_GET(8), 0x455a14ed, 20)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, a, b, c, d, _PICOHASH_MD5_GET(13), 0xa9e3e905, 5)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, d, a, b, c, _PICOHASH_MD5_GET(2), 0xfcefa3f8, 9)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, c, d, a, b, _PICOHASH_MD5_GET(7), 0x676f02d9, 14)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_G, b, c, d, a, _PICOHASH_MD5_GET(12), 0x8d2a4c8a, 20)
+
+ /* Round 3 */
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, a, b, c, d, _PICOHASH_MD5_GET(5), 0xfffa3942, 4)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, d, a, b, c, _PICOHASH_MD5_GET(8), 0x8771f681, 11)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, c, d, a, b, _PICOHASH_MD5_GET(11), 0x6d9d6122, 16)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, b, c, d, a, _PICOHASH_MD5_GET(14), 0xfde5380c, 23)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, a, b, c, d, _PICOHASH_MD5_GET(1), 0xa4beea44, 4)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, d, a, b, c, _PICOHASH_MD5_GET(4), 0x4bdecfa9, 11)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, c, d, a, b, _PICOHASH_MD5_GET(7), 0xf6bb4b60, 16)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, b, c, d, a, _PICOHASH_MD5_GET(10), 0xbebfbc70, 23)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, a, b, c, d, _PICOHASH_MD5_GET(13), 0x289b7ec6, 4)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, d, a, b, c, _PICOHASH_MD5_GET(0), 0xeaa127fa, 11)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, c, d, a, b, _PICOHASH_MD5_GET(3), 0xd4ef3085, 16)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, b, c, d, a, _PICOHASH_MD5_GET(6), 0x04881d05, 23)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, a, b, c, d, _PICOHASH_MD5_GET(9), 0xd9d4d039, 4)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, d, a, b, c, _PICOHASH_MD5_GET(12), 0xe6db99e5, 11)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, c, d, a, b, _PICOHASH_MD5_GET(15), 0x1fa27cf8, 16)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_H, b, c, d, a, _PICOHASH_MD5_GET(2), 0xc4ac5665, 23)
+
+ /* Round 4 */
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, a, b, c, d, _PICOHASH_MD5_GET(0), 0xf4292244, 6)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, d, a, b, c, _PICOHASH_MD5_GET(7), 0x432aff97, 10)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, c, d, a, b, _PICOHASH_MD5_GET(14), 0xab9423a7, 15)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, b, c, d, a, _PICOHASH_MD5_GET(5), 0xfc93a039, 21)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, a, b, c, d, _PICOHASH_MD5_GET(12), 0x655b59c3, 6)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, d, a, b, c, _PICOHASH_MD5_GET(3), 0x8f0ccc92, 10)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, c, d, a, b, _PICOHASH_MD5_GET(10), 0xffeff47d, 15)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, b, c, d, a, _PICOHASH_MD5_GET(1), 0x85845dd1, 21)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, a, b, c, d, _PICOHASH_MD5_GET(8), 0x6fa87e4f, 6)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, d, a, b, c, _PICOHASH_MD5_GET(15), 0xfe2ce6e0, 10)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, c, d, a, b, _PICOHASH_MD5_GET(6), 0xa3014314, 15)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, b, c, d, a, _PICOHASH_MD5_GET(13), 0x4e0811a1, 21)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, a, b, c, d, _PICOHASH_MD5_GET(4), 0xf7537e82, 6)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, d, a, b, c, _PICOHASH_MD5_GET(11), 0xbd3af235, 10)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, c, d, a, b, _PICOHASH_MD5_GET(2), 0x2ad7d2bb, 15)
+ _PICOHASH_MD5_STEP(_PICOHASH_MD5_I, b, c, d, a, _PICOHASH_MD5_GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+inline void _picohash_md5_init(_picohash_md5_ctx_t *ctx)
+{
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+inline void _picohash_md5_update(_picohash_md5_ctx_t *ctx, const void *data, size_t size)
+{
+ uint_fast32_t saved_lo;
+ unsigned long used, free;
+
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if (used) {
+ free = 64 - used;
+
+ if (size < free) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, free);
+ data = (const unsigned char *)data + free;
+ size -= free;
+ _picohash_md5_body(ctx, ctx->buffer, 64);
+ }
+
+ if (size >= 64) {
+ data = _picohash_md5_body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
+}
+
+inline void _picohash_md5_final(_picohash_md5_ctx_t *ctx, void *_digest)
+{
+ unsigned char *digest = _digest;
+ unsigned long used, free;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ free = 64 - used;
+
+ if (free < 8) {
+ memset(&ctx->buffer[used], 0, free);
+ _picohash_md5_body(ctx, ctx->buffer, 64);
+ used = 0;
+ free = 64;
+ }
+
+ memset(&ctx->buffer[used], 0, free - 8);
+
+ ctx->lo <<= 3;
+ ctx->buffer[56] = ctx->lo;
+ ctx->buffer[57] = ctx->lo >> 8;
+ ctx->buffer[58] = ctx->lo >> 16;
+ ctx->buffer[59] = ctx->lo >> 24;
+ ctx->buffer[60] = ctx->hi;
+ ctx->buffer[61] = ctx->hi >> 8;
+ ctx->buffer[62] = ctx->hi >> 16;
+ ctx->buffer[63] = ctx->hi >> 24;
+
+ _picohash_md5_body(ctx, ctx->buffer, 64);
+
+ digest[0] = ctx->a;
+ digest[1] = ctx->a >> 8;
+ digest[2] = ctx->a >> 16;
+ digest[3] = ctx->a >> 24;
+ digest[4] = ctx->b;
+ digest[5] = ctx->b >> 8;
+ digest[6] = ctx->b >> 16;
+ digest[7] = ctx->b >> 24;
+ digest[8] = ctx->c;
+ digest[9] = ctx->c >> 8;
+ digest[10] = ctx->c >> 16;
+ digest[11] = ctx->c >> 24;
+ digest[12] = ctx->d;
+ digest[13] = ctx->d >> 8;
+ digest[14] = ctx->d >> 16;
+ digest[15] = ctx->d >> 24;
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+#define _PICOHASH_SHA1_K0 0x5a827999
+#define _PICOHASH_SHA1_K20 0x6ed9eba1
+#define _PICOHASH_SHA1_K40 0x8f1bbcdc
+#define _PICOHASH_SHA1_K60 0xca62c1d6
+
+static inline uint32_t _picohash_sha1_rol32(uint32_t number, uint8_t bits)
+{
+ return ((number << bits) | (number >> (32 - bits)));
+}
+
+static inline void _picohash_sha1_hash_block(_picohash_sha1_ctx_t *s)
+{
+ uint8_t i;
+ uint32_t a, b, c, d, e, t;
+
+ a = s->state[0];
+ b = s->state[1];
+ c = s->state[2];
+ d = s->state[3];
+ e = s->state[4];
+ for (i = 0; i < 80; i++) {
+ if (i >= 16) {
+ t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^ s->buffer[(i + 2) & 15] ^ s->buffer[i & 15];
+ s->buffer[i & 15] = _picohash_sha1_rol32(t, 1);
+ }
+ if (i < 20) {
+ t = (d ^ (b & (c ^ d))) + _PICOHASH_SHA1_K0;
+ } else if (i < 40) {
+ t = (b ^ c ^ d) + _PICOHASH_SHA1_K20;
+ } else if (i < 60) {
+ t = ((b & c) | (d & (b | c))) + _PICOHASH_SHA1_K40;
+ } else {
+ t = (b ^ c ^ d) + _PICOHASH_SHA1_K60;
+ }
+ t += _picohash_sha1_rol32(a, 5) + e + s->buffer[i & 15];
+ e = d;
+ d = c;
+ c = _picohash_sha1_rol32(b, 30);
+ b = a;
+ a = t;
+ }
+ s->state[0] += a;
+ s->state[1] += b;
+ s->state[2] += c;
+ s->state[3] += d;
+ s->state[4] += e;
+}
+
+static inline void _picohash_sha1_add_uncounted(_picohash_sha1_ctx_t *s, uint8_t data)
+{
+ uint8_t *const b = (uint8_t *)s->buffer;
+#ifdef _PICOHASH_BIG_ENDIAN
+ b[s->bufferOffset] = data;
+#else
+ b[s->bufferOffset ^ 3] = data;
+#endif
+ s->bufferOffset++;
+ if (s->bufferOffset == PICOHASH_SHA1_BLOCK_LENGTH) {
+ _picohash_sha1_hash_block(s);
+ s->bufferOffset = 0;
+ }
+}
+
+inline void _picohash_sha1_init(_picohash_sha1_ctx_t *s)
+{
+ s->state[0] = 0x67452301;
+ s->state[1] = 0xefcdab89;
+ s->state[2] = 0x98badcfe;
+ s->state[3] = 0x10325476;
+ s->state[4] = 0xc3d2e1f0;
+ s->byteCount = 0;
+ s->bufferOffset = 0;
+}
+
+inline void _picohash_sha1_update(_picohash_sha1_ctx_t *s, const void *_data, size_t len)
+{
+ const uint8_t *data = _data;
+ for (; len != 0; --len) {
+ ++s->byteCount;
+ _picohash_sha1_add_uncounted(s, *data++);
+ }
+}
+
+inline void _picohash_sha1_final(_picohash_sha1_ctx_t *s, void *digest)
+{
+ // Pad with 0x80 followed by 0x00 until the end of the block
+ _picohash_sha1_add_uncounted(s, 0x80);
+ while (s->bufferOffset != 56)
+ _picohash_sha1_add_uncounted(s, 0x00);
+
+ // Append length in the last 8 bytes
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 53); // Shifting to multiply by 8
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 45); // as SHA-1 supports bitstreams as well as
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 37); // byte.
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 29);
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 21);
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 13);
+ _picohash_sha1_add_uncounted(s, s->byteCount >> 5);
+ _picohash_sha1_add_uncounted(s, s->byteCount << 3);
+
+#ifndef SHA_BIG_ENDIAN
+ { // Swap byte order back
+ int i;
+ for (i = 0; i < 5; i++) {
+ s->state[i] = (((s->state[i]) << 24) & 0xff000000) | (((s->state[i]) << 8) & 0x00ff0000) |
+ (((s->state[i]) >> 8) & 0x0000ff00) | (((s->state[i]) >> 24) & 0x000000ff);
+ }
+ }
+#endif
+
+ memcpy(digest, s->state, sizeof(s->state));
+}
+
+#define _picohash_sha256_ch(x, y, z) (z ^ (x & (y ^ z)))
+#define _picohash_sha256_maj(x, y, z) (((x | y) & z) | (x & y))
+#define _picohash_sha256_s(x, y) \
+ (((((uint32_t)(x)&0xFFFFFFFFUL) >> (uint32_t)((y)&31)) | ((uint32_t)(x) << (uint32_t)(32 - ((y)&31)))) & 0xFFFFFFFFUL)
+#define _picohash_sha256_r(x, n) (((x)&0xFFFFFFFFUL) >> (n))
+#define _picohash_sha256_sigma0(x) (_picohash_sha256_s(x, 2) ^ _picohash_sha256_s(x, 13) ^ _picohash_sha256_s(x, 22))
+#define _picohash_sha256_sigma1(x) (_picohash_sha256_s(x, 6) ^ _picohash_sha256_s(x, 11) ^ _picohash_sha256_s(x, 25))
+#define _picohash_sha256_gamma0(x) (_picohash_sha256_s(x, 7) ^ _picohash_sha256_s(x, 18) ^ _picohash_sha256_r(x, 3))
+#define _picohash_sha256_gamma1(x) (_picohash_sha256_s(x, 17) ^ _picohash_sha256_s(x, 19) ^ _picohash_sha256_r(x, 10))
+#define _picohash_sha256_rnd(a, b, c, d, e, f, g, h, i) \
+ t0 = h + _picohash_sha256_sigma1(e) + _picohash_sha256_ch(e, f, g) + K[i] + W[i]; \
+ t1 = _picohash_sha256_sigma0(a) + _picohash_sha256_maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+static inline void _picohash_sha256_compress(_picohash_sha256_ctx_t *ctx, unsigned char *buf)
+{
+ static const uint32_t K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL};
+ uint32_t S[8], W[64], t, t0, t1;
+ int i;
+
+ /* copy state into S */
+ for (i = 0; i < 8; i++)
+ S[i] = ctx->state[i];
+
+ /* copy the state into 512-bits into W[0..15] */
+ for (i = 0; i < 16; i++)
+ W[i] =
+ (uint32_t)buf[4 * i] << 24 | (uint32_t)buf[4 * i + 1] << 16 | (uint32_t)buf[4 * i + 2] << 8 | (uint32_t)buf[4 * i + 3];
+
+ /* fill W[16..63] */
+ for (i = 16; i < 64; i++)
+ W[i] = _picohash_sha256_gamma1(W[i - 2]) + W[i - 7] + _picohash_sha256_gamma0(W[i - 15]) + W[i - 16];
+
+ /* Compress */
+ for (i = 0; i < 64; ++i) {
+ _picohash_sha256_rnd(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
+ t = S[7];
+ S[7] = S[6];
+ S[6] = S[5];
+ S[5] = S[4];
+ S[4] = S[3];
+ S[3] = S[2];
+ S[2] = S[1];
+ S[1] = S[0];
+ S[0] = t;
+ }
+
+ /* feedback */
+ for (i = 0; i < 8; i++)
+ ctx->state[i] = ctx->state[i] + S[i];
+}
+
+static inline void _picohash_sha256_do_final(_picohash_sha256_ctx_t *ctx, void *digest, size_t len)
+{
+ unsigned char *out = digest;
+ size_t i;
+
+ /* increase the length of the message */
+ ctx->length += ctx->curlen * 8;
+
+ /* append the '1' bit */
+ ctx->buf[ctx->curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 56 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (ctx->curlen > 56) {
+ while (ctx->curlen < 64) {
+ ctx->buf[ctx->curlen++] = (unsigned char)0;
+ }
+ _picohash_sha256_compress(ctx, ctx->buf);
+ ctx->curlen = 0;
+ }
+
+ /* pad upto 56 bytes of zeroes */
+ while (ctx->curlen < 56) {
+ ctx->buf[ctx->curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ for (i = 0; i != 8; ++i)
+ ctx->buf[56 + i] = ctx->length >> (56 - 8 * i);
+ _picohash_sha256_compress(ctx, ctx->buf);
+
+ /* copy output */
+ for (i = 0; i != len / 4; ++i) {
+ out[i * 4] = ctx->state[i] >> 24;
+ out[i * 4 + 1] = ctx->state[i] >> 16;
+ out[i * 4 + 2] = ctx->state[i] >> 8;
+ out[i * 4 + 3] = ctx->state[i];
+ }
+}
+
+inline void _picohash_sha256_init(_picohash_sha256_ctx_t *ctx)
+{
+ ctx->curlen = 0;
+ ctx->length = 0;
+ ctx->state[0] = 0x6A09E667UL;
+ ctx->state[1] = 0xBB67AE85UL;
+ ctx->state[2] = 0x3C6EF372UL;
+ ctx->state[3] = 0xA54FF53AUL;
+ ctx->state[4] = 0x510E527FUL;
+ ctx->state[5] = 0x9B05688CUL;
+ ctx->state[6] = 0x1F83D9ABUL;
+ ctx->state[7] = 0x5BE0CD19UL;
+}
+
+inline void _picohash_sha256_update(_picohash_sha256_ctx_t *ctx, const void *data, size_t len)
+{
+ const unsigned char *in = data;
+ size_t n;
+
+ while (len > 0) {
+ if (ctx->curlen == 0 && len >= PICOHASH_SHA256_BLOCK_LENGTH) {
+ _picohash_sha256_compress(ctx, (unsigned char *)in);
+ ctx->length += PICOHASH_SHA256_BLOCK_LENGTH * 8;
+ in += PICOHASH_SHA256_BLOCK_LENGTH;
+ len -= PICOHASH_SHA256_BLOCK_LENGTH;
+ } else {
+ n = PICOHASH_SHA256_BLOCK_LENGTH - ctx->curlen;
+ if (n > len)
+ n = len;
+ memcpy(ctx->buf + ctx->curlen, in, (size_t)n);
+ ctx->curlen += n;
+ in += n;
+ len -= n;
+ if (ctx->curlen == 64) {
+ _picohash_sha256_compress(ctx, ctx->buf);
+ ctx->length += 8 * PICOHASH_SHA256_BLOCK_LENGTH;
+ ctx->curlen = 0;
+ }
+ }
+ }
+}
+
+inline void _picohash_sha256_final(_picohash_sha256_ctx_t *ctx, void *digest)
+{
+ _picohash_sha256_do_final(ctx, digest, PICOHASH_SHA256_DIGEST_LENGTH);
+}
+
+inline void _picohash_sha224_init(_picohash_sha256_ctx_t *ctx)
+{
+ ctx->curlen = 0;
+ ctx->length = 0;
+ ctx->state[0] = 0xc1059ed8UL;
+ ctx->state[1] = 0x367cd507UL;
+ ctx->state[2] = 0x3070dd17UL;
+ ctx->state[3] = 0xf70e5939UL;
+ ctx->state[4] = 0xffc00b31UL;
+ ctx->state[5] = 0x68581511UL;
+ ctx->state[6] = 0x64f98fa7UL;
+ ctx->state[7] = 0xbefa4fa4UL;
+}
+
+inline void _picohash_sha224_final(_picohash_sha256_ctx_t *ctx, void *digest)
+{
+ _picohash_sha256_do_final(ctx, digest, PICOHASH_SHA224_DIGEST_LENGTH);
+}
+
+inline void picohash_init_md5(picohash_ctx_t *ctx)
+{
+ ctx->block_length = PICOHASH_MD5_BLOCK_LENGTH;
+ ctx->digest_length = PICOHASH_MD5_DIGEST_LENGTH;
+ ctx->_reset = (void *)_picohash_md5_init;
+ ctx->_update = (void *)_picohash_md5_update;
+ ctx->_final = (void *)_picohash_md5_final;
+
+ _picohash_md5_init(&ctx->_md5);
+}
+
+inline void picohash_init_sha1(picohash_ctx_t *ctx)
+{
+ ctx->block_length = PICOHASH_SHA1_BLOCK_LENGTH;
+ ctx->digest_length = PICOHASH_SHA1_DIGEST_LENGTH;
+ ctx->_reset = (void *)_picohash_sha1_init;
+ ctx->_update = (void *)_picohash_sha1_update;
+ ctx->_final = (void *)_picohash_sha1_final;
+ _picohash_sha1_init(&ctx->_sha1);
+}
+
+inline void picohash_init_sha224(picohash_ctx_t *ctx)
+{
+ ctx->block_length = PICOHASH_SHA224_BLOCK_LENGTH;
+ ctx->digest_length = PICOHASH_SHA224_DIGEST_LENGTH;
+ ctx->_reset = (void *)_picohash_sha224_init;
+ ctx->_update = (void *)_picohash_sha256_update;
+ ctx->_final = (void *)_picohash_sha224_final;
+ _picohash_sha224_init(&ctx->_sha256);
+}
+
+inline void picohash_init_sha256(picohash_ctx_t *ctx)
+{
+ ctx->block_length = PICOHASH_SHA256_BLOCK_LENGTH;
+ ctx->digest_length = PICOHASH_SHA256_DIGEST_LENGTH;
+ ctx->_reset = (void *)_picohash_sha256_init;
+ ctx->_update = (void *)_picohash_sha256_update;
+ ctx->_final = (void *)_picohash_sha256_final;
+ _picohash_sha256_init(&ctx->_sha256);
+}
+
+inline void picohash_update(picohash_ctx_t *ctx, const void *input, size_t len)
+{
+ ctx->_update(ctx, input, len);
+}
+
+inline void picohash_final(picohash_ctx_t *ctx, void *digest)
+{
+ ctx->_final(ctx, digest);
+}
+
+inline void picohash_reset(picohash_ctx_t *ctx)
+{
+ ctx->_reset(ctx);
+}
+
+static inline void _picohash_hmac_apply_key(picohash_ctx_t *ctx, unsigned char delta)
+{
+ size_t i;
+ for (i = 0; i != ctx->block_length; ++i)
+ ctx->_hmac.key[i] ^= delta;
+ picohash_update(ctx, ctx->_hmac.key, ctx->block_length);
+ for (i = 0; i != ctx->block_length; ++i)
+ ctx->_hmac.key[i] ^= delta;
+}
+
+static void _picohash_hmac_final(picohash_ctx_t *ctx, void *digest)
+{
+ unsigned char inner_digest[PICOHASH_MAX_DIGEST_LENGTH];
+
+ ctx->_hmac.hash_final(ctx, inner_digest);
+
+ ctx->_hmac.hash_reset(ctx);
+ _picohash_hmac_apply_key(ctx, 0x5c);
+ picohash_update(ctx, inner_digest, ctx->digest_length);
+ memset(inner_digest, 0, ctx->digest_length);
+
+ ctx->_hmac.hash_final(ctx, digest);
+}
+
+static inline void _picohash_hmac_reset(picohash_ctx_t *ctx)
+{
+ ctx->_hmac.hash_reset(ctx);
+ _picohash_hmac_apply_key(ctx, 0x36);
+}
+
+inline void picohash_init_hmac(picohash_ctx_t *ctx, void (*initf)(picohash_ctx_t *), const void *key, size_t key_len)
+{
+ initf(ctx);
+
+ memset(ctx->_hmac.key, 0, ctx->block_length);
+ if (key_len > ctx->block_length) {
+ /* hash the key if it is too long */
+ picohash_update(ctx, key, key_len);
+ picohash_final(ctx, ctx->_hmac.key);
+ ctx->_hmac.hash_reset(ctx);
+ } else {
+ memcpy(ctx->_hmac.key, key, key_len);
+ }
+
+ /* replace reset and final function */
+ ctx->_hmac.hash_reset = ctx->_reset;
+ ctx->_hmac.hash_final = ctx->_final;
+ ctx->_reset = (void *)_picohash_hmac_reset;
+ ctx->_final = (void *)_picohash_hmac_final;
+
+ /* start calculating the inner hash */
+ _picohash_hmac_apply_key(ctx, 0x36);
+}
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby-digest/test/digest.rb b/web/server/h2o/libh2o/deps/mruby-digest/test/digest.rb
new file mode 100644
index 00000000..fd13fa43
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-digest/test/digest.rb
@@ -0,0 +1,203 @@
+##
+# Digest Test
+
+if Object.const_defined?(:Digest)
+ assert('Digest') do
+ Digest.class == Module
+ end
+
+ assert('Digest::Base') do
+ Digest::Base.class == Class
+ end
+
+ assert('Digest::Base#new') do
+ e1 = nil
+ begin
+ Digest::Base.new
+ rescue NotImplementedError => e
+ e1 = e
+ end
+ e1.class == NotImplementedError
+ end
+
+ assert('Digest::MD5') do
+ Digest::MD5.class == Class
+ end
+
+ assert('Digest::MD5 superclass') do
+ Digest::MD5.superclass == Digest::Base
+ end
+
+ assert('Digest::MD5.digest') do
+ Digest::MD5.digest('ruby') == "X\xE5=\x13$\xEE\xF6&_\xDB\x97\xB0\x8E\xD9\xAA\xDF"
+ end
+
+ #assert('Digest::MD5.file')
+
+ assert('Digest::MD5.hexdigest') do
+ Digest::MD5.hexdigest('ruby') == "58e53d1324eef6265fdb97b08ed9aadf"
+ end
+
+ assert('Digest::MD5#update') do
+ d = Digest::MD5.new
+ d.update('ruby')
+ d.hexdigest == "58e53d1324eef6265fdb97b08ed9aadf"
+ end
+
+ assert('Digest::MD5#update 2') do
+ d = Digest::MD5.new
+ d.update('ruby')
+ d.update('digest')
+ d.hexdigest == "2ac1b3e3db06239e3244817f281450f1"
+ end
+
+ assert('Digest::MD5#<<') do
+ a = Digest::MD5.new
+ b = Digest::MD5.new
+ a.update('ruby')
+ b << "r" << "u" << "b" << "y"
+ a.hexdigest == b.hexdigest
+ end
+
+ assert('Digest::MD5#== with Digest::XXX') do
+ x1 = Digest::MD5.new.update("ruby")
+ x2 = Digest::MD5.new.update("ruby")
+ x3 = Digest::MD5.new.update("RUBY")
+ (x1 == x2) == true and
+ (x1 == x3) == false
+ end
+
+ assert('Digest::MD5#== with String') do
+ Digest::MD5.new.update("ruby") == "58e53d1324eef6265fdb97b08ed9aadf"
+ end
+
+ assert('Digest::MD5#block_length') do
+ Digest::MD5.new.block_length == 64
+ end
+
+ assert('Digest::MD5#digest') do
+ Digest::MD5.new.update("ruby").digest == "X\xE5=\x13$\xEE\xF6&_\xDB\x97\xB0\x8E\xD9\xAA\xDF"
+ end
+
+ assert('Digest::MD5#digest!') do
+ d = Digest::MD5.new.update("ruby")
+ d.digest!
+ #d.digest! == "\xD4\x1D\x8C\xD9\x8F\x00\xB2\x04\xE9\x80\t\x98\xEC\xF8B~"
+ # XXX: mrbtest dumps core!
+ d.digest! == Digest::MD5.new.digest
+ end
+
+ assert('Digest::MD5#digest_length') do
+ d = Digest::MD5.new
+ n = 16
+ d.digest_length == n and
+ d.length == n and
+ d.size == n
+ end
+
+ #assert('Digest::MD5#file')
+
+ assert('Digest::MD5#hexdigest') do
+ d = Digest::MD5.new.update("ruby")
+ s = "58e53d1324eef6265fdb97b08ed9aadf"
+ d.hexdigest == s and
+ d.to_s == s
+ end
+
+ assert('Digest::MD5#hexdigest!') do
+ d = Digest::MD5.new.update("ruby")
+ d.hexdigest!
+ d.hexdigest! == "d41d8cd98f00b204e9800998ecf8427e"
+ end
+
+ assert('Digest::MD5#reset') do
+ d = Digest::MD5.new.update("ruby")
+ d.reset
+ d.hexdigest! == "d41d8cd98f00b204e9800998ecf8427e"
+ end
+
+ if Digest.const_defined? :RMD160
+ assert('Digest::RMD160#hexdigest') do
+ d = Digest::RMD160.new.update("ruby")
+ s = "29d9b710bc50866fa2399c3061cd02c0c8ffa197"
+ d.hexdigest == s
+ end
+ end
+
+ if Digest.const_defined? :SHA1
+ assert('Digest::SHA1#hexdigest') do
+ d = Digest::SHA1.new.update("ruby")
+ s = "18e40e1401eef67e1ae69efab09afb71f87ffb81"
+ d.hexdigest == s
+ end
+ end
+
+ if Digest.const_defined? :SHA256
+ assert('Digest::SHA256#hexdigest') do
+ d = Digest::SHA256.new.update("ruby")
+ s = "b9138194ffe9e7c8bb6d79d1ed56259553d18d9cb60b66e3ba5aa2e5b078055a"
+ d.hexdigest == s
+ end
+ end
+
+ if Digest.const_defined? :SHA384
+ assert('Digest::SHA384#hexdigest') do
+ d = Digest::SHA384.new.update("ruby")
+ s = "635365ef93ebf2c7a4e40b0b497da727ab8c2914eb9f052e6be40476f95d3daf44786790f5f0e843fab419b43022e069"
+ d.hexdigest == s
+ end
+ end
+
+ if Digest.const_defined? :SHA512
+ assert('Digest::SHA512#hexdigest') do
+ d = Digest::SHA512.new.update("ruby")
+ s = "423408d7723a3d80baefa804bd50b61a89667efec1713386a7b8efe28e5d13968307a908778cad210d7aa2dfe7db9a2aa86895f9fc1eeefcc99814310b207a6b"
+ d.hexdigest == s
+ end
+ end
+
+ assert('Digest::HMAC') do
+ Digest::HMAC.class == Class
+ end
+
+ assert('Digest::HMAC.digest') do
+ Digest::HMAC.digest("data", "hash key", Digest::SHA1) == "\xFD \xECC=\xFD\x97\x0E\xEC!FW\xCF\xB5Gl]\x913f"
+ end
+
+ assert('Digest::HMAC.hexdigest') do
+ Digest::HMAC.hexdigest("data", "hash key", Digest::SHA1) == "fd20ec433dfd970eec214657cfb5476c5d913366"
+ end
+
+ assert('Digest::HMAC#<<') do
+ a = Digest::HMAC.new('hash key', Digest::SHA1)
+ b = Digest::HMAC.new('hash key', Digest::SHA1)
+ a.update('ruby')
+ b << "r" << "u" << "b" << "y"
+ a.hexdigest == b.hexdigest
+ end
+
+ assert('Digest::HMAC#block_length') do
+ d = Digest::HMAC.new("hash key", Digest::SHA1)
+ d.block_length == 64
+ end
+
+ assert('Digest::HMAC#digest_length') do
+ d = Digest::HMAC.new("hash key", Digest::SHA1)
+ d.digest_length == 20
+ end
+
+ # assert('Digest::HMAC#reset')
+
+ assert('Digest::HMAC#update') do
+ d = Digest::HMAC.new("hash key", Digest::SHA1)
+ d.update('data')
+ d.hexdigest == "fd20ec433dfd970eec214657cfb5476c5d913366"
+ end
+
+ assert('Digest::HMAC#update 2') do
+ d = Digest::HMAC.new("hash key", Digest::SHA1)
+ d.update('ruby')
+ d.update('digest')
+ d.hexdigest == "e4be3728777e43deba3aa522a4247ea83b19a1c7"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/.gitignore b/web/server/h2o/libh2o/deps/mruby-dir/.gitignore
new file mode 100644
index 00000000..55ef3162
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/.gitignore
@@ -0,0 +1,5 @@
+gem_*
+gem-*
+mrb-*.a
+src/*.o
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/.travis.yml b/web/server/h2o/libh2o/deps/mruby-dir/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/README.md b/web/server/h2o/libh2o/deps/mruby-dir/README.md
new file mode 100644
index 00000000..d7953036
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/README.md
@@ -0,0 +1,56 @@
+mruby-dir
+=========
+
+Dir class for mruby. Supported methods are:
+
+`.chdir`
+`.delete`
+`.entries`
+`.exist?`
+`.foreach`
+`.getwd`
+`.mkdir`
+`.open`
+`#close`
+`#each`
+`#read`
+`#rewind`
+`#seek`
+`#tell`
+
+
+## License
+
+Copyright (c) 2012 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+- On Windows platforms, you must agree on addional license too:
+
+Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose is hereby granted without fee, provided
+that this copyright and permissions notice appear in all copies and
+derivatives.
+
+This software is supplied "as is" without express or implied warranty.
+
+But that said, if there are any problems please get in touch.
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-dir/mrbgem.rake
new file mode 100644
index 00000000..10864c81
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-dir') do |spec|
+ spec.license = 'MIT and MIT-like license'
+ spec.authors = [ 'Internet Initiative Japan Inc.', 'Kevlin Henney']
+
+ spec.cc.include_paths << "#{build.root}/src"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/mrblib/dir.rb b/web/server/h2o/libh2o/deps/mruby-dir/mrblib/dir.rb
new file mode 100644
index 00000000..065ca1c2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/mrblib/dir.rb
@@ -0,0 +1,64 @@
+class Dir
+ def each(&block)
+ while s = self.read
+ block.call(s)
+ end
+ self
+ end
+
+ alias pos tell
+ alias pos= seek
+
+ def self.entries(path)
+ a = []
+ self.open(path) { |d|
+ while s = d.read
+ a << s
+ end
+ }
+ a
+ end
+
+ def self.foreach(path, &block)
+ if block
+ self.open(path).each { |f| block.call(f) }
+ else
+ self.open(path).each
+ end
+ end
+
+ def self.open(path, &block)
+ if block
+ d = self.new(path)
+ begin
+ block.call(d)
+ ensure
+ d.close
+ end
+ else
+ self.new(path)
+ end
+ end
+
+ def self.chdir(path, &block)
+ my = self # workaround for https://github.com/mruby/mruby/issues/1579
+ if block
+ wd = self.getwd
+ begin
+ self._chdir(path)
+ block.call(path)
+ ensure
+ my._chdir(wd)
+ end
+ else
+ self._chdir(path)
+ end
+ end
+
+ class << self
+ alias exists? exist?
+ alias pwd getwd
+ alias rmdir delete
+ alias unlink delete
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/run_test.rb b/web/server/h2o/libh2o/deps/mruby-dir/run_test.rb
new file mode 100644
index 00000000..d9566a2a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/run_test.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+gemname = File.basename(File.dirname(File.expand_path __FILE__))
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+ build_args = ['all', 'test'] if build_args.nil? or build_args.empty?
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/src/Win/dirent.c b/web/server/h2o/libh2o/deps/mruby-dir/src/Win/dirent.c
new file mode 100644
index 00000000..98728bcf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/src/Win/dirent.c
@@ -0,0 +1,154 @@
+/*
+
+ Implementation of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003 and July 2012.
+ Rights: See end of file.
+
+*/
+
+#include <errno.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
+
+struct dirent
+{
+ char *d_name;
+};
+
+struct DIR
+{
+ handle_type handle; /* -1 for failed rewind */
+ struct _finddata_t info;
+ struct dirent result; /* d_name null iff first time */
+ char *name; /* null-terminated char string */
+};
+
+typedef struct DIR DIR;
+
+DIR *opendir(const char *name)
+{
+ DIR *dir = 0;
+
+ if(name && name[0])
+ {
+ size_t base_length = strlen(name);
+ const char *all = /* search pattern must end with suitable wildcard */
+ strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+ if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
+ (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
+ {
+ strcat(strcpy(dir->name, name), all);
+
+ if((dir->handle =
+ (handle_type) _findfirst(dir->name, &dir->info)) != -1)
+ {
+ dir->result.d_name = 0;
+ }
+ else /* rollback */
+ {
+ free(dir->name);
+ free(dir);
+ dir = 0;
+ }
+ }
+ else /* rollback */
+ {
+ free(dir);
+ dir = 0;
+ errno = ENOMEM;
+ }
+ }
+ else
+ {
+ errno = EINVAL;
+ }
+
+ return dir;
+}
+
+int closedir(DIR *dir)
+{
+ int result = -1;
+
+ if(dir)
+ {
+ if(dir->handle != -1)
+ {
+ result = _findclose(dir->handle);
+ }
+
+ free(dir->name);
+ free(dir);
+ }
+
+ if(result == -1) /* map all errors to EBADF */
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dirent *result = 0;
+
+ if(dir && dir->handle != -1)
+ {
+ if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+ {
+ result = &dir->result;
+ result->d_name = dir->info.name;
+ }
+ }
+ else
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+void rewinddir(DIR *dir)
+{
+ if(dir && dir->handle != -1)
+ {
+ _findclose(dir->handle);
+ dir->handle = (handle_type) _findfirst(dir->name, &dir->info);
+ dir->result.d_name = 0;
+ }
+ else
+ {
+ errno = EBADF;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+
+ Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+*/
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/src/dir.c b/web/server/h2o/libh2o/deps/mruby-dir/src/dir.c
new file mode 100644
index 00000000..0f55ed93
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/src/dir.c
@@ -0,0 +1,281 @@
+/*
+** dir.c - Dir
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include "mruby.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
+#include "mruby/string.h"
+#include "error.h"
+#include <sys/types.h>
+#if defined(_WIN32) || defined(_WIN64)
+ #define MAXPATHLEN 1024
+ #if !defined(PATH_MAX)
+ #define PATH_MAX MAX_PATH
+ #endif
+ #define S_ISDIR(B) ((B)&_S_IFDIR)
+ #include "Win/dirent.c"
+ #include <direct.h>
+ #define rmdir _rmdir
+ #define getcwd _getcwd
+ #define mkdir _mkdir
+ #define chdir _chdir
+#else
+ #include <sys/param.h>
+ #include <dirent.h>
+ #include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+
+/* with/without IO module */
+#ifdef ENABLE_IO
+#include "mruby/ext/io.h"
+#else
+#define E_IO_ERROR E_RUNTIME_ERROR
+#endif
+
+struct mrb_dir {
+ DIR *dir;
+};
+
+void
+mrb_dir_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_dir *mdir = ptr;
+
+ if (mdir->dir) {
+ closedir(mdir->dir);
+ mdir->dir = NULL;
+ }
+ mrb_free(mrb, mdir);
+}
+
+static struct mrb_data_type mrb_dir_type = { "DIR", mrb_dir_free };
+
+mrb_value
+mrb_dir_close(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_dir *mdir;
+ mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
+ if (!mdir) return mrb_nil_value();
+ if (!mdir->dir) {
+ mrb_raise(mrb, E_IO_ERROR, "closed directory");
+ }
+ if (closedir(mdir->dir) == -1) {
+ mrb_sys_fail(mrb, "closedir");
+ }
+ mdir->dir = NULL;
+ return mrb_nil_value();
+}
+
+mrb_value
+mrb_dir_init(mrb_state *mrb, mrb_value self)
+{
+ DIR *dir;
+ struct mrb_dir *mdir;
+ mrb_value path;
+ char *cpath;
+
+ mdir = (struct mrb_dir *)DATA_PTR(self);
+ if (mdir) {
+ mrb_dir_free(mrb, mdir);
+ }
+ DATA_TYPE(self) = &mrb_dir_type;
+ DATA_PTR(self) = NULL;
+
+ mdir = (struct mrb_dir *)mrb_malloc(mrb, sizeof(*mdir));
+ mdir->dir = NULL;
+ DATA_PTR(self) = mdir;
+
+ mrb_get_args(mrb, "S", &path);
+ cpath = mrb_str_to_cstr(mrb, path);
+ if ((dir = opendir(cpath)) == NULL) {
+ mrb_sys_fail(mrb, cpath);
+ }
+ mdir->dir = dir;
+ return self;
+}
+
+mrb_value
+mrb_dir_delete(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value path;
+ char *cpath;
+
+ mrb_get_args(mrb, "S", &path);
+ cpath = mrb_str_to_cstr(mrb, path);
+ if (rmdir(cpath) == -1) {
+ mrb_sys_fail(mrb, cpath);
+ }
+ return mrb_fixnum_value(0);
+}
+
+mrb_value
+mrb_dir_existp(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value path;
+ struct stat sb;
+ char *cpath;
+
+ mrb_get_args(mrb, "S", &path);
+ cpath = mrb_str_to_cstr(mrb, path);
+ if (stat(cpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+ return mrb_true_value();
+ } else {
+ return mrb_false_value();
+ }
+}
+
+mrb_value
+mrb_dir_getwd(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value path;
+
+ path = mrb_str_buf_new(mrb, MAXPATHLEN);
+ if (getcwd(RSTRING_PTR(path), MAXPATHLEN) == NULL) {
+ mrb_sys_fail(mrb, "getcwd(2)");
+ }
+ mrb_str_resize(mrb, path, strlen(RSTRING_PTR(path)));
+ return path;
+}
+
+mrb_value
+mrb_dir_mkdir(mrb_state *mrb, mrb_value klass)
+{
+ mrb_int mode;
+ mrb_value spath;
+ char *path;
+
+ mode = 0777;
+ mrb_get_args(mrb, "S|i", &spath, &mode);
+ path = mrb_str_to_cstr(mrb, spath);
+#ifndef _WIN32
+ if (mkdir(path, mode) == -1) {
+#else
+ if (mkdir(path) == -1) {
+#endif
+ mrb_sys_fail(mrb, path);
+ }
+ return mrb_fixnum_value(0);
+}
+
+mrb_value
+mrb_dir_chdir(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value spath;
+ char *path;
+
+ mrb_get_args(mrb, "S", &spath);
+ path = mrb_str_to_cstr(mrb, spath);
+ if (chdir(path) == -1) {
+ mrb_sys_fail(mrb, path);
+ }
+ return mrb_fixnum_value(0);
+}
+
+mrb_value
+mrb_dir_read(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_dir *mdir;
+ struct dirent *dp;
+
+ mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
+ if (!mdir) return mrb_nil_value();
+ if (!mdir->dir) {
+ mrb_raise(mrb, E_IO_ERROR, "closed directory");
+ }
+ dp = readdir(mdir->dir);
+ if (dp != NULL) {
+ return mrb_str_new_cstr(mrb, dp->d_name);
+ } else {
+ return mrb_nil_value();
+ }
+}
+
+mrb_value
+mrb_dir_rewind(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_dir *mdir;
+
+ mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
+ if (!mdir) return mrb_nil_value();
+ if (!mdir->dir) {
+ mrb_raise(mrb, E_IO_ERROR, "closed directory");
+ }
+ rewinddir(mdir->dir);
+ return self;
+}
+
+mrb_value
+mrb_dir_seek(mrb_state *mrb, mrb_value self)
+{
+ #if defined(_WIN32) || defined(_WIN64) || defined(__android__)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "dirseek() unreliable on Win platforms");
+ return self;
+ #else
+ struct mrb_dir *mdir;
+ mrb_int pos;
+
+ mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
+ if (!mdir) return mrb_nil_value();
+ if (!mdir->dir) {
+ mrb_raise(mrb, E_IO_ERROR, "closed directory");
+ }
+ mrb_get_args(mrb, "i", &pos);
+ seekdir(mdir->dir, (long)pos);
+ return self;
+ #endif
+}
+
+mrb_value
+mrb_dir_tell(mrb_state *mrb, mrb_value self)
+{
+ #if defined(_WIN32) || defined(_WIN64) || defined(__android__)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "dirtell() unreliable on Win platforms");
+ return mrb_fixnum_value(0);
+ #else
+ struct mrb_dir *mdir;
+ mrb_int pos;
+
+ mdir = (struct mrb_dir *)mrb_get_datatype(mrb, self, &mrb_dir_type);
+ if (!mdir) return mrb_nil_value();
+ if (!mdir->dir) {
+ mrb_raise(mrb, E_IO_ERROR, "closed directory");
+ }
+ pos = (mrb_int)telldir(mdir->dir);
+ return mrb_fixnum_value(pos);
+ #endif
+}
+
+void
+mrb_mruby_dir_gem_init(mrb_state *mrb)
+{
+ struct RClass *d;
+
+ d = mrb_define_class(mrb, "Dir", mrb->object_class);
+ MRB_SET_INSTANCE_TT(d, MRB_TT_DATA);
+ mrb_define_class_method(mrb, d, "delete", mrb_dir_delete, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, d, "exist?", mrb_dir_existp, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, d, "getwd", mrb_dir_getwd, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, d, "mkdir", mrb_dir_mkdir, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
+ mrb_define_class_method(mrb, d, "_chdir", mrb_dir_chdir, MRB_ARGS_REQ(1));
+
+ mrb_define_method(mrb, d, "close", mrb_dir_close, MRB_ARGS_NONE());
+ mrb_define_method(mrb, d, "initialize", mrb_dir_init, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, d, "read", mrb_dir_read, MRB_ARGS_NONE());
+ mrb_define_method(mrb, d, "rewind", mrb_dir_rewind, MRB_ARGS_NONE());
+ mrb_define_method(mrb, d, "seek", mrb_dir_seek, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, d, "tell", mrb_dir_tell, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_dir_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/test/dir.rb b/web/server/h2o/libh2o/deps/mruby-dir/test/dir.rb
new file mode 100644
index 00000000..cb1f1e31
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/test/dir.rb
@@ -0,0 +1,128 @@
+assert('Dir') do
+ assert_equal(Class, Dir.class)
+end
+
+assert('DirTest.setup') do
+ DirTest.setup
+end
+
+assert('Dir.chdir') do
+ assert_equal 0, Dir.chdir(DirTest.sandbox)
+end
+
+assert('Dir.entries') do
+ a = Dir.entries(DirTest.sandbox)
+ assert_true a.include? "a"
+ assert_true a.include? "b"
+end
+
+assert('Dir.exist?') do
+ assert_true Dir.exist?(DirTest.sandbox)
+ assert_false Dir.exist?(DirTest.sandbox + "/nosuchdir")
+end
+
+assert('Dir.foreach') do
+ a = []
+ Dir.foreach(DirTest.sandbox) { |s| a << s }
+ assert_true a.include? "a"
+ assert_true a.include? "b"
+end
+
+assert('Dir.getwd') do
+ s = Dir.getwd
+ assert_true s.kind_of? String
+end
+
+assert('Dir.mkdir') do
+ m1 = DirTest.sandbox + "/mkdir1"
+ m2 = DirTest.sandbox + "/mkdir2"
+ assert_equal 0, Dir.mkdir(m1)
+ assert_equal 0, Dir.mkdir(m2, 0765)
+end
+
+assert('Dir.delete') do
+ s = DirTest.sandbox + "/delete"
+ Dir.mkdir(s)
+ assert_true Dir.exist?(s)
+
+ Dir.delete(s)
+ assert_false Dir.exist?(s)
+end
+
+assert('Dir.open') do
+ a = []
+ Dir.open(DirTest.sandbox) { |d|
+ d.each { |s| a << s }
+ }
+ assert_true a.include? "a"
+ assert_true a.include? "b"
+end
+
+assert('Dir#initialize and Dir#close') do
+ d = Dir.new(".")
+ assert_true d.instance_of? Dir
+ assert_nil d.close
+end
+
+assert('Dir#close') do
+ d = Dir.new(".")
+end
+
+assert('Dir#each') do
+ a = []
+ d = Dir.open(DirTest.sandbox)
+ d.each { |s| a << s }
+ d.close
+ assert_true a.include? "a"
+ assert_true a.include? "b"
+end
+
+assert('Dir#read') do
+ a = []
+ d = Dir.open(DirTest.sandbox)
+ while s = d.read
+ a << s
+ end
+ d.close
+ assert_true a.include? "a"
+ assert_true a.include? "b"
+end
+
+assert('Dir#rewind') do
+ d = Dir.open(DirTest.sandbox)
+ while d.read; end
+
+ assert_equal d, d.rewind
+
+ a = []
+ while s = d.read
+ a << s
+ end
+ d.close
+ assert_true a.include? "a"
+ assert_true a.include? "b"
+end
+
+# Note: behaviors of seekdir(3) and telldir(3) are so platform-dependent
+# that we cannot write portable tests here.
+
+assert('Dir#tell') do
+ n = nil
+ Dir.open(DirTest.sandbox) { |d|
+ n = d.tell
+ }
+ assert_true n.is_a? Integer
+end
+
+assert('Dir#seek') do
+ d1 = Dir.open(DirTest.sandbox)
+ d1.read
+ n = d1.tell
+ d1.read
+ d2 = d1.seek(n)
+ assert_equal d1, d2
+end
+
+assert('DirTest.teardown') do
+ DirTest.teardown
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-dir/test/dirtest.c b/web/server/h2o/libh2o/deps/mruby-dir/test/dirtest.c
new file mode 100644
index 00000000..070f23a8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-dir/test/dirtest.c
@@ -0,0 +1,114 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mruby.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+
+
+mrb_value
+mrb_dirtest_setup(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value s;
+ char buf[1024];
+ const char *aname = "a";
+ const char *bname = "b";
+
+ /* save current working directory */
+ if (getcwd(buf, sizeof(buf)) == NULL) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "getcwd() failed");
+ }
+ mrb_cv_set(mrb, klass, mrb_intern_cstr(mrb, "pwd"), mrb_str_new_cstr(mrb, buf));
+
+ /* create sandbox */
+ snprintf(buf, sizeof(buf), "%s/mruby-dir-test.XXXXXX", P_tmpdir);
+ if (mkdtemp(buf) == NULL) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdtemp(%S) failed", mrb_str_new_cstr(mrb, buf));
+ }
+ s = mrb_str_new_cstr(mrb, buf);
+ mrb_cv_set(mrb, klass, mrb_intern_cstr(mrb, "sandbox"), s);
+
+ /* go to sandbox */
+ if (chdir(buf) == -1) {
+ rmdir(buf);
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "chdir(%S) failed", s);
+ }
+
+ /* make some directories in the sandbox */
+ if (mkdir(aname, 0) == -1) {
+ chdir("..");
+ rmdir(buf);
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdir(%S) failed", mrb_str_new_cstr(mrb, aname));
+ }
+ if (mkdir(bname, 0) == -1) {
+ rmdir(aname);
+ chdir("..");
+ rmdir(buf);
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "mkdir(%S) failed", mrb_str_new_cstr(mrb, bname));
+ }
+
+ return mrb_true_value();
+}
+
+mrb_value
+mrb_dirtest_teardown(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value d, sandbox;
+ DIR *dirp;
+ struct dirent *dp;
+ const char *path;
+
+ /* cleanup sandbox */
+ sandbox = mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "sandbox"));
+ path = mrb_str_to_cstr(mrb, sandbox);
+
+ dirp = opendir(path);
+ while ((dp = readdir(dirp)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ continue;
+ if (rmdir(dp->d_name) == -1) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "rmdir(%S) failed", mrb_str_new_cstr(mrb, dp->d_name));
+ }
+ }
+ closedir(dirp);
+
+ /* back to original pwd */
+ d = mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "pwd"));
+ path = mrb_str_to_cstr(mrb, d);
+ if (chdir(path) == -1) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "chdir(%S) failed", d);
+ }
+
+ /* remove sandbox directory */
+ sandbox = mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "sandbox"));
+ path = mrb_str_to_cstr(mrb, sandbox);
+ if (rmdir(path) == -1) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "rmdir(%S) failed", sandbox);
+ }
+
+ return mrb_true_value();
+}
+
+mrb_value
+mrb_dirtest_sandbox(mrb_state *mrb, mrb_value klass)
+{
+ return mrb_cv_get(mrb, klass, mrb_intern_cstr(mrb, "sandbox"));
+}
+
+void
+mrb_mruby_dir_gem_test(mrb_state *mrb)
+{
+ struct RClass *c = mrb_define_module(mrb, "DirTest");
+
+ mrb_define_class_method(mrb, c, "sandbox", mrb_dirtest_sandbox, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, c, "setup", mrb_dirtest_setup, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, c, "teardown", mrb_dirtest_teardown, MRB_ARGS_NONE());
+}
+
diff --git a/web/server/h2o/libh2o/deps/mruby-env/.gitignore b/web/server/h2o/libh2o/deps/mruby-env/.gitignore
new file mode 100644
index 00000000..ceeb05b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/.gitignore
@@ -0,0 +1 @@
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-env/.travis.yml b/web/server/h2o/libh2o/deps/mruby-env/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-env/README.md b/web/server/h2o/libh2o/deps/mruby-env/README.md
new file mode 100644
index 00000000..b6db2248
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/README.md
@@ -0,0 +1,52 @@
+mruby-env
+=========
+
+mruby-env provides "ENV" object, which is a hash-like accessor
+for environment variables.
+
+### Methods
+
+```
+[] []= clear delete has_key? include? inspect key? keys
+member? size store to_a to_hash to_s values
+```
+
+
+### To build:
+
+Prerequisites:
+
+ * mruby
+ * libc
+
+ activate GEMs in *build_config.rb*
+ * conf.gem :github => 'iij/mruby-env'
+ ruby ./minirake
+
+### To run the tests:
+
+ ruby ./minirake test
+
+
+## License
+
+Copyright (c) 2012 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/web/server/h2o/libh2o/deps/mruby-env/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-env/mrbgem.rake
new file mode 100644
index 00000000..03249be2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/mrbgem.rake
@@ -0,0 +1,4 @@
+MRuby::Gem::Specification.new('mruby-env') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Internet Initiative Japan Inc.'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-env/mrblib/env.rb b/web/server/h2o/libh2o/deps/mruby-env/mrblib/env.rb
new file mode 100644
index 00000000..67f9811a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/mrblib/env.rb
@@ -0,0 +1,16 @@
+class << ENV
+ alias include? has_key?
+ alias key? has_key?
+ alias member? has_key?
+
+ def clear
+ self.keys.each { |k| self.delete(k) }
+ self
+ end
+
+ def delete(key)
+ old = self[key]
+ self[key] = nil
+ old
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-env/run_test.rb b/web/server/h2o/libh2o/deps/mruby-env/run_test.rb
new file mode 100644
index 00000000..eefc9143
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/run_test.rb
@@ -0,0 +1,27 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem :core => 'mruby-time'
+ conf.gem :github => 'iij/mruby-io'
+ conf.gem :github => 'iij/mruby-mtest'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-env/src/env.c b/web/server/h2o/libh2o/deps/mruby-env/src/env.c
new file mode 100644
index 00000000..0395e1bc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/src/env.c
@@ -0,0 +1,243 @@
+/*
+** env.c - ENV is a Hash-like accessor for environment variables.
+**
+*/
+
+#include "mruby.h"
+#include "mruby/hash.h"
+#include "mruby/khash.h"
+#include "mruby/class.h"
+#include "mruby/array.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+int
+unsetenv(const char* name)
+{
+ int r;
+ char* p = malloc(strlen(name) + 2);
+ if (!p) return -1;
+ strcpy(p, name);
+ strcat(p, "=");
+ r = _putenv(p);
+ free(p);
+ return r;
+}
+
+int
+setenv(const char* name, const char* value, int overwrite)
+{
+ int r;
+ char* p = malloc(strlen(name) + strlen(value) + 2);
+ if (!p) return -1;
+ strcpy(p, name);
+ strcat(p, "=");
+ strcat(p, value);
+ r = _putenv(p);
+ free(p);
+ return r;
+}
+#define environ _environ
+#else
+extern char **environ;
+#endif
+
+
+mrb_value
+mrb_env_aget(mrb_state *mrb, mrb_value self)
+{
+ mrb_value key;
+ const char *cname, *cvalue;
+
+ mrb_get_args(mrb, "S", &key);
+ cname = mrb_string_value_cstr(mrb, &key);
+ cvalue = getenv(cname);
+ if (cvalue != NULL) {
+ return mrb_str_new_cstr(mrb, cvalue);
+ } else {
+ return mrb_nil_value();
+ }
+}
+
+mrb_value
+mrb_env_has_key(mrb_state *mrb, mrb_value self)
+{
+ mrb_value name;
+ const char *key;
+ mrb_get_args(mrb, "S", &name);
+ key = mrb_str_to_cstr(mrb, name);
+ if (getenv(key) != NULL) {
+ return mrb_true_value();
+ } else {
+ return mrb_false_value();
+ }
+}
+
+mrb_value
+mrb_env_keys(mrb_state *mrb, mrb_value self)
+{
+ int i;
+ mrb_value ary;
+
+ ary = mrb_ary_new(mrb);
+ for (i = 0; environ[i] != NULL; i++) {
+ char *str = strchr(environ[i], '=');
+ if (str != NULL) {
+ int len = str - environ[i];
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, environ[i], len));
+ }
+ }
+
+ return ary;
+}
+
+mrb_value
+mrb_env_values(mrb_state *mrb, mrb_value self)
+{
+ int i;
+ mrb_value ary;
+
+ ary = mrb_ary_new(mrb);
+ for (i = 0; environ[i] != NULL; i++) {
+ char *str = strchr(environ[i], '=');
+ if (str) {
+ int len;
+ str++;
+ len = strlen(str);
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, str, len));
+ }
+ }
+
+ return ary;
+}
+
+static mrb_value
+mrb_env_size(mrb_state *mrb, mrb_value self)
+{
+ int i;
+
+ for (i = 0; environ[i] != NULL; i++)
+ ;
+
+ return mrb_fixnum_value(i);
+}
+
+static mrb_value
+mrb_env_to_hash(mrb_state *mrb, mrb_value self)
+{
+ int i;
+ mrb_value hash;
+
+ hash = mrb_hash_new(mrb);
+ for (i = 0; environ[i] != NULL; i++) {
+ char *str = strchr(environ[i], '=');
+ if (str != NULL) {
+ mrb_value val;
+ int ai = mrb_gc_arena_save(mrb);
+ int len = str - environ[i];
+ mrb_value key = mrb_str_new(mrb, environ[i], len);
+ str++;
+ val = mrb_str_new(mrb, str, strlen(str));
+ mrb_hash_set(mrb, hash, key, val);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ }
+
+ return hash;
+}
+
+static mrb_value
+mrb_env_to_a(mrb_state *mrb, mrb_value self)
+{
+ int i;
+ mrb_value ary;
+
+ ary = mrb_ary_new(mrb);
+ for (i = 0; environ[i] != NULL; i++) {
+ char *str = strchr(environ[i], '=');
+ if (str != NULL) {
+ int ai = mrb_gc_arena_save(mrb);
+ mrb_value elem = mrb_ary_new(mrb);
+ int len = str - environ[i];
+ mrb_ary_push(mrb, elem, mrb_str_new(mrb, environ[i], len));
+ str++;
+ mrb_ary_push(mrb, elem, mrb_str_new(mrb, str, strlen(str)));
+ mrb_ary_push(mrb, ary, elem);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ }
+
+ return ary;
+}
+
+static mrb_value
+mrb_env_inspect(mrb_state *mrb, mrb_value self)
+{
+ mrb_value hash = mrb_env_to_hash(mrb, self);
+ return mrb_funcall(mrb, hash, "inspect", 0);
+}
+
+static mrb_value
+mrb_env_to_s(mrb_state *mrb, mrb_value self)
+{
+ return mrb_str_new_cstr(mrb, "ENV");
+}
+
+static mrb_value
+mrb_env_aset(mrb_state *mrb, mrb_value self)
+{
+ mrb_value name, value;
+ const char *cname, *cvalue;
+
+ mrb_get_args(mrb, "So", &name, &value);
+ cname = mrb_string_value_cstr(mrb, &name);
+
+ if (mrb_nil_p(value)) {
+ if (unsetenv(cname) != 0) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't delete environment variable");
+ }
+ } else {
+ mrb_convert_type(mrb, value, MRB_TT_STRING, "String", "to_str");
+ cvalue = mrb_string_value_cstr(mrb, &value);
+ if (setenv(cname, cvalue, 1) != 0) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't change environment variable");
+ }
+ }
+ return value;
+}
+
+void
+mrb_mruby_env_gem_init(mrb_state *mrb)
+{
+ struct RObject *e;
+
+ e = (struct RObject*) mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
+#if defined(MRUBY_RELEASE_NO) && MRUBY_RELEASE_NO >= 10000
+ mrb_include_module(mrb, (struct RClass*)e, mrb_module_get(mrb, "Enumerable"));
+#else
+ mrb_include_module(mrb, (struct RClass*)e, mrb_class_get(mrb, "Enumerable"));
+#endif
+
+ mrb_define_singleton_method(mrb, e,"[]", mrb_env_aget, MRB_ARGS_REQ(1));
+ mrb_define_singleton_method(mrb, e,"[]=", mrb_env_aset, MRB_ARGS_REQ(2));
+ mrb_define_singleton_method(mrb, e,"has_key?", mrb_env_has_key, MRB_ARGS_REQ(1));
+ mrb_define_singleton_method(mrb, e,"inspect", mrb_env_inspect, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, e,"keys", mrb_env_keys, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, e,"size", mrb_env_size, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, e,"store", mrb_env_aset, MRB_ARGS_REQ(2));
+ mrb_define_singleton_method(mrb, e,"to_a", mrb_env_to_a, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, e,"to_hash", mrb_env_to_hash, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, e,"to_s", mrb_env_to_s, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, e,"values", mrb_env_values, MRB_ARGS_NONE());
+
+ mrb_define_global_const(mrb, "ENV", mrb_obj_value(e));
+}
+
+void
+mrb_mruby_env_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-env/test/env_test.rb b/web/server/h2o/libh2o/deps/mruby-env/test/env_test.rb
new file mode 100644
index 00000000..2aa3dab2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-env/test/env_test.rb
@@ -0,0 +1,121 @@
+##
+# ENV test
+#
+
+if Object.const_defined?(:MTest)
+ class ENVTest < MTest::Unit::TestCase
+ def test_env_class
+ assert_equal(Object, ENV.class)
+ end
+
+ def setup
+ @env_hash = ENV.to_hash
+ ENV.clear
+ end
+
+ def teardown
+ ENV.clear
+ @env_hash.each do |k, v|
+ ENV[k] = v
+ end
+ end
+
+ def set_dummy_env
+ ENV['FOO'] = 'bar'
+ end
+
+ def test_size_empty
+ assert_equal(0, ENV.size)
+ end
+
+ def test_keys_empty
+ assert_empty(ENV.keys)
+ end
+
+ def test_values_empty
+ assert_empty(ENV.values)
+ end
+
+ def test_env_to_s_empty
+ assert_equal("ENV", ENV.to_s)
+ end
+
+ def test_env_inspect_empty
+ assert_equal("{}", ENV.inspect)
+ end
+
+ def test_env_to_hash_empty
+ assert_equal({}, ENV.to_hash)
+ end
+
+ def test_env_get_val
+ set_dummy_env
+ assert_equal('bar', ENV['FOO'])
+ end
+
+ def test_env_keys
+ set_dummy_env
+ assert_equal(['FOO'], ENV.keys)
+ end
+
+ def test_env_values
+ set_dummy_env
+ assert_equal(['bar'], ENV.values)
+ end
+
+ def test_env_to_s
+ set_dummy_env
+ assert_equal("ENV", ENV.to_s)
+ end
+
+ def test_env_has_key
+ set_dummy_env
+ assert_true ENV.has_key?("FOO")
+ assert_false ENV.has_key?("BAR")
+ end
+
+ def test_env_inspect
+ set_dummy_env
+ assert_equal("{\"FOO\"=>\"bar\"}", ENV.inspect)
+ end
+
+ def test_env_delete
+ set_dummy_env
+ old = ENV['FOO']
+ ret = ENV.delete('FOO')
+ assert_equal(0, ENV.size)
+ assert_equal(old, ret)
+ assert_equal(nil, ENV.delete('nosuchenv'))
+ end
+
+ def test_env_subst_nil
+ set_dummy_env
+ ENV['FOO'] = nil
+ assert_equal(0, ENV.size)
+ end
+
+ def test_env_store
+ ENV['a'] = 'b'
+ assert_equal 'b', ENV['a']
+
+ ENV['a'] = 'c'
+ assert_equal 'c', ENV['a']
+
+ ENV['a'] = nil
+ assert_equal nil, ENV['a']
+
+ ENV['b'] = nil
+ assert_equal nil, ENV['b']
+ assert_equal 0, ENV.size
+ end
+ end
+
+ if $ok_test
+ MTest::Unit.new.mrbtest
+ else
+ MTest::Unit.new.run
+ end
+else
+ $asserts << "test skip of mruby-env/test/env_test.rb" if $asserts
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/.gitignore b/web/server/h2o/libh2o/deps/mruby-errno/.gitignore
new file mode 100644
index 00000000..ceeb05b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/.gitignore
@@ -0,0 +1 @@
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/.travis.yml b/web/server/h2o/libh2o/deps/mruby-errno/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/README.md b/web/server/h2o/libh2o/deps/mruby-errno/README.md
new file mode 100644
index 00000000..e3c594cb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/README.md
@@ -0,0 +1,27 @@
+mruby-errno
+===========
+
+Errno module for mruby
+
+
+## License
+
+Copyright (c) 2013 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-errno/mrbgem.rake
new file mode 100644
index 00000000..ba3d60da
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-errno') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Internet Initiative Japan Inc.'
+
+ spec.cc.include_paths << "#{build.root}/src"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/run_test.rb b/web/server/h2o/libh2o/deps/mruby-errno/run_test.rb
new file mode 100644
index 00000000..d9566a2a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/run_test.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+gemname = File.basename(File.dirname(File.expand_path __FILE__))
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+ build_args = ['all', 'test'] if build_args.nil? or build_args.empty?
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/src/errno.c b/web/server/h2o/libh2o/deps/mruby-errno/src/errno.c
new file mode 100644
index 00000000..3617efd4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/src/errno.c
@@ -0,0 +1,175 @@
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
+#include "mruby/hash.h"
+#include "mruby/numeric.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#if MRUBY_RELEASE_NO < 10000
+static struct RClass *
+mrb_module_get(mrb_state *mrb, const char *name)
+{
+ return mrb_class_get(mrb, name);
+}
+#endif
+
+static mrb_value
+mrb_sce_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value c, e2c, m, str;
+ mrb_int n;
+ int argc, no_errno = 0;
+ char buf[20];
+
+ argc = mrb_get_args(mrb, "o|i", &m, &n);
+ if (argc == 1) {
+ if (mrb_type(m) == MRB_TT_FIXNUM) {
+ n = mrb_fixnum(m);
+ m = mrb_nil_value();
+ } else {
+ no_errno = 1;
+ }
+ }
+ if (!no_errno) {
+ e2c = mrb_const_get(mrb, mrb_obj_value(mrb_module_get(mrb, "Errno")), mrb_intern_lit(mrb, "Errno2class"));
+ c = mrb_hash_fetch(mrb, e2c, mrb_fixnum_value(n), mrb_nil_value());
+ if (!mrb_nil_p(c)) {
+ mrb_basic_ptr(self)->c = mrb_class_ptr(c);
+ str = mrb_str_new_cstr(mrb, strerror(n));
+ } else {
+ mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "errno"), mrb_fixnum_value(n));
+ str = mrb_str_new_cstr(mrb, "Unknown error: ");
+ snprintf(buf, sizeof(buf), "%d", (int)n);
+ mrb_str_cat2(mrb, str, buf);
+ }
+ } else {
+ str = mrb_str_new_cstr(mrb, "unknown error");
+ }
+ if (!mrb_nil_p(m)) {
+ mrb_str_cat2(mrb, str, " - ");
+ mrb_str_append(mrb, str, m);
+ }
+ mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "mesg"), str);
+ return self;
+}
+
+static mrb_value
+mrb_sce_errno(mrb_state *mrb, mrb_value self)
+{
+ struct RClass *c;
+ mrb_sym sym;
+
+ c = mrb_class(mrb, self);
+ sym = mrb_intern_lit(mrb, "Errno");
+#if MRUBY_RELEASE_NO < 10000
+ if (mrb_const_defined_at(mrb, c, sym)) {
+#else
+ if (mrb_const_defined_at(mrb, mrb_obj_value(c), sym)) {
+#endif
+ return mrb_const_get(mrb, mrb_obj_value(c), sym);
+ } else {
+ sym = mrb_intern_lit(mrb, "errno");
+ return mrb_attr_get(mrb, self, sym);
+ }
+}
+
+static mrb_value
+mrb_sce_to_s(mrb_state *mrb, mrb_value self)
+{
+ return mrb_attr_get(mrb, self, mrb_intern_lit(mrb, "mesg"));
+}
+
+static mrb_value
+mrb_sce_sys_fail(mrb_state *mrb, mrb_value cls)
+{
+ struct RClass *cl, *sce;
+ mrb_value e, msg;
+ mrb_int no;
+ int argc;
+ char name[8];
+
+ sce = mrb_class_get(mrb, "SystemCallError");
+ argc = mrb_get_args(mrb, "i|S", &no, &msg);
+ if (argc == 1) {
+ e = mrb_funcall(mrb, mrb_obj_value(sce), "new", 1, mrb_fixnum_value(no));
+ } else {
+ e = mrb_funcall(mrb, mrb_obj_value(sce), "new", 2, msg, mrb_fixnum_value(no));
+ }
+ if (mrb_obj_class(mrb, e) == sce) {
+ snprintf(name, sizeof(name), "E%03ld", (long)no);
+ cl = mrb_define_class_under(mrb, mrb_module_get(mrb, "Errno"), name, sce);
+ mrb_define_const(mrb, cl, "Errno", mrb_fixnum_value(no));
+ mrb_basic_ptr(e)->c = cl;
+ }
+ mrb_exc_raise(mrb, e);
+ return mrb_nil_value(); /* NOTREACHED */
+}
+
+static mrb_value
+mrb_exxx_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value m, no, str;
+
+ no = mrb_const_get(mrb, mrb_obj_value(mrb_class(mrb, self)), mrb_intern_lit(mrb, "Errno"));
+ str = mrb_str_new_cstr(mrb, strerror(mrb_fixnum(no)));
+
+ m = mrb_nil_value();
+ mrb_get_args(mrb, "|S", &m);
+ if (!mrb_nil_p(m)) {
+ mrb_str_cat2(mrb, str, " - ");
+ mrb_str_append(mrb, str, m);
+ }
+ mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "mesg"), str);
+ return self;
+}
+
+void
+mrb_mruby_errno_gem_init(mrb_state *mrb)
+{
+ struct RClass *e, *eno, *sce, *ste;
+ mrb_value h, noerror;
+
+ ste = mrb_class_get(mrb, "StandardError");
+
+ sce = mrb_define_class(mrb, "SystemCallError", ste);
+ mrb_define_class_method(mrb, sce, "_sys_fail", mrb_sce_sys_fail, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, sce, "errno", mrb_sce_errno, MRB_ARGS_NONE());
+ mrb_define_method(mrb, sce, "to_s", mrb_sce_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, sce, "initialize", mrb_sce_init, MRB_ARGS_ARG(1, 1));
+
+ eno = mrb_define_module(mrb, "Errno");
+ h = mrb_hash_new(mrb);
+ mrb_define_const(mrb, eno, "Errno2class", h);
+
+ e = mrb_define_class_under(mrb, eno, "NOERROR", sce);
+ mrb_define_const(mrb, e, "Errno", mrb_fixnum_value(0));
+ mrb_define_method(mrb, e, "initialize", mrb_exxx_init, MRB_ARGS_OPT(1));
+ //mrb_define_method(mrb, e, "===", mrb_exxx_cmp, MRB_ARGS_REQ(1));
+ noerror = mrb_obj_value(e);
+
+#define itsdefined(SYM) \
+ do { \
+ int ai = mrb_gc_arena_save(mrb); \
+ e = mrb_define_class_under(mrb, eno, #SYM, sce); \
+ mrb_define_const(mrb, e, "Errno", mrb_fixnum_value(SYM)); \
+ mrb_define_method(mrb, e, "initialize", mrb_exxx_init, MRB_ARGS_OPT(1)); \
+ mrb_hash_set(mrb, h, mrb_fixnum_value(SYM), mrb_obj_value(e)); \
+ mrb_gc_arena_restore(mrb, ai); \
+ } while (0)
+
+#define itsnotdefined(SYM) \
+ do { \
+ mrb_define_const(mrb, eno, #SYM, noerror); \
+ } while (0)
+
+#include "known_errors_def.cstub"
+}
+
+void
+mrb_mruby_errno_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/src/gen.rb b/web/server/h2o/libh2o/deps/mruby-errno/src/gen.rb
new file mode 100755
index 00000000..12e6b302
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/src/gen.rb
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname($0))
+
+e = File.open("known_errors_e2c.cstub", "w")
+d = File.open("known_errors_def.cstub", "w")
+
+IO.readlines("known_errors.def").each { |name|
+ next if name =~ /^#/
+ name.strip!
+
+ e.write <<CODE
+#ifdef #{name}
+ { #{name}, NULL, },
+#endif
+CODE
+
+ d.write <<CODE
+#ifdef #{name}
+ itsdefined(#{name});
+#else
+ itsnotdefined(#{name});
+#endif
+CODE
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors.def b/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors.def
new file mode 100644
index 00000000..3cebe90a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors.def
@@ -0,0 +1,145 @@
+EPERM
+ENOENT
+ESRCH
+EINTR
+EIO
+ENXIO
+E2BIG
+ENOEXEC
+EBADF
+ECHILD
+EAGAIN
+ENOMEM
+EACCES
+EFAULT
+ENOTBLK
+EBUSY
+EEXIST
+EXDEV
+ENODEV
+ENOTDIR
+EISDIR
+EINVAL
+ENFILE
+EMFILE
+ENOTTY
+ETXTBSY
+EFBIG
+ENOSPC
+ESPIPE
+EROFS
+EMLINK
+EPIPE
+EDOM
+ERANGE
+EDEADLK
+ENAMETOOLONG
+ENOLCK
+ENOSYS
+ENOTEMPTY
+ELOOP
+EWOULDBLOCK
+ENOMSG
+EIDRM
+ECHRNG
+EL2NSYNC
+EL3HLT
+EL3RST
+ELNRNG
+EUNATCH
+ENOCSI
+EL2HLT
+EBADE
+EBADR
+EXFULL
+ENOANO
+EBADRQC
+EBADSLT
+EDEADLOCK
+EBFONT
+ENOSTR
+ENODATA
+ETIME
+ENOSR
+ENONET
+ENOPKG
+EREMOTE
+ENOLINK
+EADV
+ESRMNT
+ECOMM
+EPROTO
+EMULTIHOP
+EDOTDOT
+EBADMSG
+EOVERFLOW
+ENOTUNIQ
+EBADFD
+EREMCHG
+ELIBACC
+ELIBBAD
+ELIBSCN
+ELIBMAX
+ELIBEXEC
+EILSEQ
+ERESTART
+ESTRPIPE
+EUSERS
+ENOTSOCK
+EDESTADDRREQ
+EMSGSIZE
+EPROTOTYPE
+ENOPROTOOPT
+EPROTONOSUPPORT
+ESOCKTNOSUPPORT
+EOPNOTSUPP
+EPFNOSUPPORT
+EAFNOSUPPORT
+EADDRINUSE
+EADDRNOTAVAIL
+ENETDOWN
+ENETUNREACH
+ENETRESET
+ECONNABORTED
+ECONNRESET
+ENOBUFS
+EISCONN
+ENOTCONN
+ESHUTDOWN
+ETOOMANYREFS
+ETIMEDOUT
+ECONNREFUSED
+EHOSTDOWN
+EHOSTUNREACH
+EALREADY
+EINPROGRESS
+ESTALE
+EUCLEAN
+ENOTNAM
+ENAVAIL
+EISNAM
+EREMOTEIO
+EDQUOT
+ECANCELED
+EKEYEXPIRED
+EKEYREJECTED
+EKEYREVOKED
+EMEDIUMTYPE
+ENOKEY
+ENOMEDIUM
+ENOTRECOVERABLE
+EOWNERDEAD
+ERFKILL
+EAUTH
+EBADRPC
+EDOOFUS
+EFTYPE
+ENEEDAUTH
+ENOATTR
+ENOTSUP
+EPROCLIM
+EPROCUNAVAIL
+EPROGMISMATCH
+EPROGUNAVAIL
+ERPCMISMATCH
+EIPSEC
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_def.cstub b/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_def.cstub
new file mode 100644
index 00000000..83d8670b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_def.cstub
@@ -0,0 +1,725 @@
+#ifdef EPERM
+ itsdefined(EPERM);
+#else
+ itsnotdefined(EPERM);
+#endif
+#ifdef ENOENT
+ itsdefined(ENOENT);
+#else
+ itsnotdefined(ENOENT);
+#endif
+#ifdef ESRCH
+ itsdefined(ESRCH);
+#else
+ itsnotdefined(ESRCH);
+#endif
+#ifdef EINTR
+ itsdefined(EINTR);
+#else
+ itsnotdefined(EINTR);
+#endif
+#ifdef EIO
+ itsdefined(EIO);
+#else
+ itsnotdefined(EIO);
+#endif
+#ifdef ENXIO
+ itsdefined(ENXIO);
+#else
+ itsnotdefined(ENXIO);
+#endif
+#ifdef E2BIG
+ itsdefined(E2BIG);
+#else
+ itsnotdefined(E2BIG);
+#endif
+#ifdef ENOEXEC
+ itsdefined(ENOEXEC);
+#else
+ itsnotdefined(ENOEXEC);
+#endif
+#ifdef EBADF
+ itsdefined(EBADF);
+#else
+ itsnotdefined(EBADF);
+#endif
+#ifdef ECHILD
+ itsdefined(ECHILD);
+#else
+ itsnotdefined(ECHILD);
+#endif
+#ifdef EAGAIN
+ itsdefined(EAGAIN);
+#else
+ itsnotdefined(EAGAIN);
+#endif
+#ifdef ENOMEM
+ itsdefined(ENOMEM);
+#else
+ itsnotdefined(ENOMEM);
+#endif
+#ifdef EACCES
+ itsdefined(EACCES);
+#else
+ itsnotdefined(EACCES);
+#endif
+#ifdef EFAULT
+ itsdefined(EFAULT);
+#else
+ itsnotdefined(EFAULT);
+#endif
+#ifdef ENOTBLK
+ itsdefined(ENOTBLK);
+#else
+ itsnotdefined(ENOTBLK);
+#endif
+#ifdef EBUSY
+ itsdefined(EBUSY);
+#else
+ itsnotdefined(EBUSY);
+#endif
+#ifdef EEXIST
+ itsdefined(EEXIST);
+#else
+ itsnotdefined(EEXIST);
+#endif
+#ifdef EXDEV
+ itsdefined(EXDEV);
+#else
+ itsnotdefined(EXDEV);
+#endif
+#ifdef ENODEV
+ itsdefined(ENODEV);
+#else
+ itsnotdefined(ENODEV);
+#endif
+#ifdef ENOTDIR
+ itsdefined(ENOTDIR);
+#else
+ itsnotdefined(ENOTDIR);
+#endif
+#ifdef EISDIR
+ itsdefined(EISDIR);
+#else
+ itsnotdefined(EISDIR);
+#endif
+#ifdef EINVAL
+ itsdefined(EINVAL);
+#else
+ itsnotdefined(EINVAL);
+#endif
+#ifdef ENFILE
+ itsdefined(ENFILE);
+#else
+ itsnotdefined(ENFILE);
+#endif
+#ifdef EMFILE
+ itsdefined(EMFILE);
+#else
+ itsnotdefined(EMFILE);
+#endif
+#ifdef ENOTTY
+ itsdefined(ENOTTY);
+#else
+ itsnotdefined(ENOTTY);
+#endif
+#ifdef ETXTBSY
+ itsdefined(ETXTBSY);
+#else
+ itsnotdefined(ETXTBSY);
+#endif
+#ifdef EFBIG
+ itsdefined(EFBIG);
+#else
+ itsnotdefined(EFBIG);
+#endif
+#ifdef ENOSPC
+ itsdefined(ENOSPC);
+#else
+ itsnotdefined(ENOSPC);
+#endif
+#ifdef ESPIPE
+ itsdefined(ESPIPE);
+#else
+ itsnotdefined(ESPIPE);
+#endif
+#ifdef EROFS
+ itsdefined(EROFS);
+#else
+ itsnotdefined(EROFS);
+#endif
+#ifdef EMLINK
+ itsdefined(EMLINK);
+#else
+ itsnotdefined(EMLINK);
+#endif
+#ifdef EPIPE
+ itsdefined(EPIPE);
+#else
+ itsnotdefined(EPIPE);
+#endif
+#ifdef EDOM
+ itsdefined(EDOM);
+#else
+ itsnotdefined(EDOM);
+#endif
+#ifdef ERANGE
+ itsdefined(ERANGE);
+#else
+ itsnotdefined(ERANGE);
+#endif
+#ifdef EDEADLK
+ itsdefined(EDEADLK);
+#else
+ itsnotdefined(EDEADLK);
+#endif
+#ifdef ENAMETOOLONG
+ itsdefined(ENAMETOOLONG);
+#else
+ itsnotdefined(ENAMETOOLONG);
+#endif
+#ifdef ENOLCK
+ itsdefined(ENOLCK);
+#else
+ itsnotdefined(ENOLCK);
+#endif
+#ifdef ENOSYS
+ itsdefined(ENOSYS);
+#else
+ itsnotdefined(ENOSYS);
+#endif
+#ifdef ENOTEMPTY
+ itsdefined(ENOTEMPTY);
+#else
+ itsnotdefined(ENOTEMPTY);
+#endif
+#ifdef ELOOP
+ itsdefined(ELOOP);
+#else
+ itsnotdefined(ELOOP);
+#endif
+#ifdef EWOULDBLOCK
+ itsdefined(EWOULDBLOCK);
+#else
+ itsnotdefined(EWOULDBLOCK);
+#endif
+#ifdef ENOMSG
+ itsdefined(ENOMSG);
+#else
+ itsnotdefined(ENOMSG);
+#endif
+#ifdef EIDRM
+ itsdefined(EIDRM);
+#else
+ itsnotdefined(EIDRM);
+#endif
+#ifdef ECHRNG
+ itsdefined(ECHRNG);
+#else
+ itsnotdefined(ECHRNG);
+#endif
+#ifdef EL2NSYNC
+ itsdefined(EL2NSYNC);
+#else
+ itsnotdefined(EL2NSYNC);
+#endif
+#ifdef EL3HLT
+ itsdefined(EL3HLT);
+#else
+ itsnotdefined(EL3HLT);
+#endif
+#ifdef EL3RST
+ itsdefined(EL3RST);
+#else
+ itsnotdefined(EL3RST);
+#endif
+#ifdef ELNRNG
+ itsdefined(ELNRNG);
+#else
+ itsnotdefined(ELNRNG);
+#endif
+#ifdef EUNATCH
+ itsdefined(EUNATCH);
+#else
+ itsnotdefined(EUNATCH);
+#endif
+#ifdef ENOCSI
+ itsdefined(ENOCSI);
+#else
+ itsnotdefined(ENOCSI);
+#endif
+#ifdef EL2HLT
+ itsdefined(EL2HLT);
+#else
+ itsnotdefined(EL2HLT);
+#endif
+#ifdef EBADE
+ itsdefined(EBADE);
+#else
+ itsnotdefined(EBADE);
+#endif
+#ifdef EBADR
+ itsdefined(EBADR);
+#else
+ itsnotdefined(EBADR);
+#endif
+#ifdef EXFULL
+ itsdefined(EXFULL);
+#else
+ itsnotdefined(EXFULL);
+#endif
+#ifdef ENOANO
+ itsdefined(ENOANO);
+#else
+ itsnotdefined(ENOANO);
+#endif
+#ifdef EBADRQC
+ itsdefined(EBADRQC);
+#else
+ itsnotdefined(EBADRQC);
+#endif
+#ifdef EBADSLT
+ itsdefined(EBADSLT);
+#else
+ itsnotdefined(EBADSLT);
+#endif
+#ifdef EDEADLOCK
+ itsdefined(EDEADLOCK);
+#else
+ itsnotdefined(EDEADLOCK);
+#endif
+#ifdef EBFONT
+ itsdefined(EBFONT);
+#else
+ itsnotdefined(EBFONT);
+#endif
+#ifdef ENOSTR
+ itsdefined(ENOSTR);
+#else
+ itsnotdefined(ENOSTR);
+#endif
+#ifdef ENODATA
+ itsdefined(ENODATA);
+#else
+ itsnotdefined(ENODATA);
+#endif
+#ifdef ETIME
+ itsdefined(ETIME);
+#else
+ itsnotdefined(ETIME);
+#endif
+#ifdef ENOSR
+ itsdefined(ENOSR);
+#else
+ itsnotdefined(ENOSR);
+#endif
+#ifdef ENONET
+ itsdefined(ENONET);
+#else
+ itsnotdefined(ENONET);
+#endif
+#ifdef ENOPKG
+ itsdefined(ENOPKG);
+#else
+ itsnotdefined(ENOPKG);
+#endif
+#ifdef EREMOTE
+ itsdefined(EREMOTE);
+#else
+ itsnotdefined(EREMOTE);
+#endif
+#ifdef ENOLINK
+ itsdefined(ENOLINK);
+#else
+ itsnotdefined(ENOLINK);
+#endif
+#ifdef EADV
+ itsdefined(EADV);
+#else
+ itsnotdefined(EADV);
+#endif
+#ifdef ESRMNT
+ itsdefined(ESRMNT);
+#else
+ itsnotdefined(ESRMNT);
+#endif
+#ifdef ECOMM
+ itsdefined(ECOMM);
+#else
+ itsnotdefined(ECOMM);
+#endif
+#ifdef EPROTO
+ itsdefined(EPROTO);
+#else
+ itsnotdefined(EPROTO);
+#endif
+#ifdef EMULTIHOP
+ itsdefined(EMULTIHOP);
+#else
+ itsnotdefined(EMULTIHOP);
+#endif
+#ifdef EDOTDOT
+ itsdefined(EDOTDOT);
+#else
+ itsnotdefined(EDOTDOT);
+#endif
+#ifdef EBADMSG
+ itsdefined(EBADMSG);
+#else
+ itsnotdefined(EBADMSG);
+#endif
+#ifdef EOVERFLOW
+ itsdefined(EOVERFLOW);
+#else
+ itsnotdefined(EOVERFLOW);
+#endif
+#ifdef ENOTUNIQ
+ itsdefined(ENOTUNIQ);
+#else
+ itsnotdefined(ENOTUNIQ);
+#endif
+#ifdef EBADFD
+ itsdefined(EBADFD);
+#else
+ itsnotdefined(EBADFD);
+#endif
+#ifdef EREMCHG
+ itsdefined(EREMCHG);
+#else
+ itsnotdefined(EREMCHG);
+#endif
+#ifdef ELIBACC
+ itsdefined(ELIBACC);
+#else
+ itsnotdefined(ELIBACC);
+#endif
+#ifdef ELIBBAD
+ itsdefined(ELIBBAD);
+#else
+ itsnotdefined(ELIBBAD);
+#endif
+#ifdef ELIBSCN
+ itsdefined(ELIBSCN);
+#else
+ itsnotdefined(ELIBSCN);
+#endif
+#ifdef ELIBMAX
+ itsdefined(ELIBMAX);
+#else
+ itsnotdefined(ELIBMAX);
+#endif
+#ifdef ELIBEXEC
+ itsdefined(ELIBEXEC);
+#else
+ itsnotdefined(ELIBEXEC);
+#endif
+#ifdef EILSEQ
+ itsdefined(EILSEQ);
+#else
+ itsnotdefined(EILSEQ);
+#endif
+#ifdef ERESTART
+ itsdefined(ERESTART);
+#else
+ itsnotdefined(ERESTART);
+#endif
+#ifdef ESTRPIPE
+ itsdefined(ESTRPIPE);
+#else
+ itsnotdefined(ESTRPIPE);
+#endif
+#ifdef EUSERS
+ itsdefined(EUSERS);
+#else
+ itsnotdefined(EUSERS);
+#endif
+#ifdef ENOTSOCK
+ itsdefined(ENOTSOCK);
+#else
+ itsnotdefined(ENOTSOCK);
+#endif
+#ifdef EDESTADDRREQ
+ itsdefined(EDESTADDRREQ);
+#else
+ itsnotdefined(EDESTADDRREQ);
+#endif
+#ifdef EMSGSIZE
+ itsdefined(EMSGSIZE);
+#else
+ itsnotdefined(EMSGSIZE);
+#endif
+#ifdef EPROTOTYPE
+ itsdefined(EPROTOTYPE);
+#else
+ itsnotdefined(EPROTOTYPE);
+#endif
+#ifdef ENOPROTOOPT
+ itsdefined(ENOPROTOOPT);
+#else
+ itsnotdefined(ENOPROTOOPT);
+#endif
+#ifdef EPROTONOSUPPORT
+ itsdefined(EPROTONOSUPPORT);
+#else
+ itsnotdefined(EPROTONOSUPPORT);
+#endif
+#ifdef ESOCKTNOSUPPORT
+ itsdefined(ESOCKTNOSUPPORT);
+#else
+ itsnotdefined(ESOCKTNOSUPPORT);
+#endif
+#ifdef EOPNOTSUPP
+ itsdefined(EOPNOTSUPP);
+#else
+ itsnotdefined(EOPNOTSUPP);
+#endif
+#ifdef EPFNOSUPPORT
+ itsdefined(EPFNOSUPPORT);
+#else
+ itsnotdefined(EPFNOSUPPORT);
+#endif
+#ifdef EAFNOSUPPORT
+ itsdefined(EAFNOSUPPORT);
+#else
+ itsnotdefined(EAFNOSUPPORT);
+#endif
+#ifdef EADDRINUSE
+ itsdefined(EADDRINUSE);
+#else
+ itsnotdefined(EADDRINUSE);
+#endif
+#ifdef EADDRNOTAVAIL
+ itsdefined(EADDRNOTAVAIL);
+#else
+ itsnotdefined(EADDRNOTAVAIL);
+#endif
+#ifdef ENETDOWN
+ itsdefined(ENETDOWN);
+#else
+ itsnotdefined(ENETDOWN);
+#endif
+#ifdef ENETUNREACH
+ itsdefined(ENETUNREACH);
+#else
+ itsnotdefined(ENETUNREACH);
+#endif
+#ifdef ENETRESET
+ itsdefined(ENETRESET);
+#else
+ itsnotdefined(ENETRESET);
+#endif
+#ifdef ECONNABORTED
+ itsdefined(ECONNABORTED);
+#else
+ itsnotdefined(ECONNABORTED);
+#endif
+#ifdef ECONNRESET
+ itsdefined(ECONNRESET);
+#else
+ itsnotdefined(ECONNRESET);
+#endif
+#ifdef ENOBUFS
+ itsdefined(ENOBUFS);
+#else
+ itsnotdefined(ENOBUFS);
+#endif
+#ifdef EISCONN
+ itsdefined(EISCONN);
+#else
+ itsnotdefined(EISCONN);
+#endif
+#ifdef ENOTCONN
+ itsdefined(ENOTCONN);
+#else
+ itsnotdefined(ENOTCONN);
+#endif
+#ifdef ESHUTDOWN
+ itsdefined(ESHUTDOWN);
+#else
+ itsnotdefined(ESHUTDOWN);
+#endif
+#ifdef ETOOMANYREFS
+ itsdefined(ETOOMANYREFS);
+#else
+ itsnotdefined(ETOOMANYREFS);
+#endif
+#ifdef ETIMEDOUT
+ itsdefined(ETIMEDOUT);
+#else
+ itsnotdefined(ETIMEDOUT);
+#endif
+#ifdef ECONNREFUSED
+ itsdefined(ECONNREFUSED);
+#else
+ itsnotdefined(ECONNREFUSED);
+#endif
+#ifdef EHOSTDOWN
+ itsdefined(EHOSTDOWN);
+#else
+ itsnotdefined(EHOSTDOWN);
+#endif
+#ifdef EHOSTUNREACH
+ itsdefined(EHOSTUNREACH);
+#else
+ itsnotdefined(EHOSTUNREACH);
+#endif
+#ifdef EALREADY
+ itsdefined(EALREADY);
+#else
+ itsnotdefined(EALREADY);
+#endif
+#ifdef EINPROGRESS
+ itsdefined(EINPROGRESS);
+#else
+ itsnotdefined(EINPROGRESS);
+#endif
+#ifdef ESTALE
+ itsdefined(ESTALE);
+#else
+ itsnotdefined(ESTALE);
+#endif
+#ifdef EUCLEAN
+ itsdefined(EUCLEAN);
+#else
+ itsnotdefined(EUCLEAN);
+#endif
+#ifdef ENOTNAM
+ itsdefined(ENOTNAM);
+#else
+ itsnotdefined(ENOTNAM);
+#endif
+#ifdef ENAVAIL
+ itsdefined(ENAVAIL);
+#else
+ itsnotdefined(ENAVAIL);
+#endif
+#ifdef EISNAM
+ itsdefined(EISNAM);
+#else
+ itsnotdefined(EISNAM);
+#endif
+#ifdef EREMOTEIO
+ itsdefined(EREMOTEIO);
+#else
+ itsnotdefined(EREMOTEIO);
+#endif
+#ifdef EDQUOT
+ itsdefined(EDQUOT);
+#else
+ itsnotdefined(EDQUOT);
+#endif
+#ifdef ECANCELED
+ itsdefined(ECANCELED);
+#else
+ itsnotdefined(ECANCELED);
+#endif
+#ifdef EKEYEXPIRED
+ itsdefined(EKEYEXPIRED);
+#else
+ itsnotdefined(EKEYEXPIRED);
+#endif
+#ifdef EKEYREJECTED
+ itsdefined(EKEYREJECTED);
+#else
+ itsnotdefined(EKEYREJECTED);
+#endif
+#ifdef EKEYREVOKED
+ itsdefined(EKEYREVOKED);
+#else
+ itsnotdefined(EKEYREVOKED);
+#endif
+#ifdef EMEDIUMTYPE
+ itsdefined(EMEDIUMTYPE);
+#else
+ itsnotdefined(EMEDIUMTYPE);
+#endif
+#ifdef ENOKEY
+ itsdefined(ENOKEY);
+#else
+ itsnotdefined(ENOKEY);
+#endif
+#ifdef ENOMEDIUM
+ itsdefined(ENOMEDIUM);
+#else
+ itsnotdefined(ENOMEDIUM);
+#endif
+#ifdef ENOTRECOVERABLE
+ itsdefined(ENOTRECOVERABLE);
+#else
+ itsnotdefined(ENOTRECOVERABLE);
+#endif
+#ifdef EOWNERDEAD
+ itsdefined(EOWNERDEAD);
+#else
+ itsnotdefined(EOWNERDEAD);
+#endif
+#ifdef ERFKILL
+ itsdefined(ERFKILL);
+#else
+ itsnotdefined(ERFKILL);
+#endif
+#ifdef EAUTH
+ itsdefined(EAUTH);
+#else
+ itsnotdefined(EAUTH);
+#endif
+#ifdef EBADRPC
+ itsdefined(EBADRPC);
+#else
+ itsnotdefined(EBADRPC);
+#endif
+#ifdef EDOOFUS
+ itsdefined(EDOOFUS);
+#else
+ itsnotdefined(EDOOFUS);
+#endif
+#ifdef EFTYPE
+ itsdefined(EFTYPE);
+#else
+ itsnotdefined(EFTYPE);
+#endif
+#ifdef ENEEDAUTH
+ itsdefined(ENEEDAUTH);
+#else
+ itsnotdefined(ENEEDAUTH);
+#endif
+#ifdef ENOATTR
+ itsdefined(ENOATTR);
+#else
+ itsnotdefined(ENOATTR);
+#endif
+#ifdef ENOTSUP
+ itsdefined(ENOTSUP);
+#else
+ itsnotdefined(ENOTSUP);
+#endif
+#ifdef EPROCLIM
+ itsdefined(EPROCLIM);
+#else
+ itsnotdefined(EPROCLIM);
+#endif
+#ifdef EPROCUNAVAIL
+ itsdefined(EPROCUNAVAIL);
+#else
+ itsnotdefined(EPROCUNAVAIL);
+#endif
+#ifdef EPROGMISMATCH
+ itsdefined(EPROGMISMATCH);
+#else
+ itsnotdefined(EPROGMISMATCH);
+#endif
+#ifdef EPROGUNAVAIL
+ itsdefined(EPROGUNAVAIL);
+#else
+ itsnotdefined(EPROGUNAVAIL);
+#endif
+#ifdef ERPCMISMATCH
+ itsdefined(ERPCMISMATCH);
+#else
+ itsnotdefined(ERPCMISMATCH);
+#endif
+#ifdef EIPSEC
+ itsdefined(EIPSEC);
+#else
+ itsnotdefined(EIPSEC);
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_e2c.cstub b/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_e2c.cstub
new file mode 100644
index 00000000..f203c336
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/src/known_errors_e2c.cstub
@@ -0,0 +1,435 @@
+#ifdef EPERM
+ { EPERM, NULL, },
+#endif
+#ifdef ENOENT
+ { ENOENT, NULL, },
+#endif
+#ifdef ESRCH
+ { ESRCH, NULL, },
+#endif
+#ifdef EINTR
+ { EINTR, NULL, },
+#endif
+#ifdef EIO
+ { EIO, NULL, },
+#endif
+#ifdef ENXIO
+ { ENXIO, NULL, },
+#endif
+#ifdef E2BIG
+ { E2BIG, NULL, },
+#endif
+#ifdef ENOEXEC
+ { ENOEXEC, NULL, },
+#endif
+#ifdef EBADF
+ { EBADF, NULL, },
+#endif
+#ifdef ECHILD
+ { ECHILD, NULL, },
+#endif
+#ifdef EAGAIN
+ { EAGAIN, NULL, },
+#endif
+#ifdef ENOMEM
+ { ENOMEM, NULL, },
+#endif
+#ifdef EACCES
+ { EACCES, NULL, },
+#endif
+#ifdef EFAULT
+ { EFAULT, NULL, },
+#endif
+#ifdef ENOTBLK
+ { ENOTBLK, NULL, },
+#endif
+#ifdef EBUSY
+ { EBUSY, NULL, },
+#endif
+#ifdef EEXIST
+ { EEXIST, NULL, },
+#endif
+#ifdef EXDEV
+ { EXDEV, NULL, },
+#endif
+#ifdef ENODEV
+ { ENODEV, NULL, },
+#endif
+#ifdef ENOTDIR
+ { ENOTDIR, NULL, },
+#endif
+#ifdef EISDIR
+ { EISDIR, NULL, },
+#endif
+#ifdef EINVAL
+ { EINVAL, NULL, },
+#endif
+#ifdef ENFILE
+ { ENFILE, NULL, },
+#endif
+#ifdef EMFILE
+ { EMFILE, NULL, },
+#endif
+#ifdef ENOTTY
+ { ENOTTY, NULL, },
+#endif
+#ifdef ETXTBSY
+ { ETXTBSY, NULL, },
+#endif
+#ifdef EFBIG
+ { EFBIG, NULL, },
+#endif
+#ifdef ENOSPC
+ { ENOSPC, NULL, },
+#endif
+#ifdef ESPIPE
+ { ESPIPE, NULL, },
+#endif
+#ifdef EROFS
+ { EROFS, NULL, },
+#endif
+#ifdef EMLINK
+ { EMLINK, NULL, },
+#endif
+#ifdef EPIPE
+ { EPIPE, NULL, },
+#endif
+#ifdef EDOM
+ { EDOM, NULL, },
+#endif
+#ifdef ERANGE
+ { ERANGE, NULL, },
+#endif
+#ifdef EDEADLK
+ { EDEADLK, NULL, },
+#endif
+#ifdef ENAMETOOLONG
+ { ENAMETOOLONG, NULL, },
+#endif
+#ifdef ENOLCK
+ { ENOLCK, NULL, },
+#endif
+#ifdef ENOSYS
+ { ENOSYS, NULL, },
+#endif
+#ifdef ENOTEMPTY
+ { ENOTEMPTY, NULL, },
+#endif
+#ifdef ELOOP
+ { ELOOP, NULL, },
+#endif
+#ifdef EWOULDBLOCK
+ { EWOULDBLOCK, NULL, },
+#endif
+#ifdef ENOMSG
+ { ENOMSG, NULL, },
+#endif
+#ifdef EIDRM
+ { EIDRM, NULL, },
+#endif
+#ifdef ECHRNG
+ { ECHRNG, NULL, },
+#endif
+#ifdef EL2NSYNC
+ { EL2NSYNC, NULL, },
+#endif
+#ifdef EL3HLT
+ { EL3HLT, NULL, },
+#endif
+#ifdef EL3RST
+ { EL3RST, NULL, },
+#endif
+#ifdef ELNRNG
+ { ELNRNG, NULL, },
+#endif
+#ifdef EUNATCH
+ { EUNATCH, NULL, },
+#endif
+#ifdef ENOCSI
+ { ENOCSI, NULL, },
+#endif
+#ifdef EL2HLT
+ { EL2HLT, NULL, },
+#endif
+#ifdef EBADE
+ { EBADE, NULL, },
+#endif
+#ifdef EBADR
+ { EBADR, NULL, },
+#endif
+#ifdef EXFULL
+ { EXFULL, NULL, },
+#endif
+#ifdef ENOANO
+ { ENOANO, NULL, },
+#endif
+#ifdef EBADRQC
+ { EBADRQC, NULL, },
+#endif
+#ifdef EBADSLT
+ { EBADSLT, NULL, },
+#endif
+#ifdef EDEADLOCK
+ { EDEADLOCK, NULL, },
+#endif
+#ifdef EBFONT
+ { EBFONT, NULL, },
+#endif
+#ifdef ENOSTR
+ { ENOSTR, NULL, },
+#endif
+#ifdef ENODATA
+ { ENODATA, NULL, },
+#endif
+#ifdef ETIME
+ { ETIME, NULL, },
+#endif
+#ifdef ENOSR
+ { ENOSR, NULL, },
+#endif
+#ifdef ENONET
+ { ENONET, NULL, },
+#endif
+#ifdef ENOPKG
+ { ENOPKG, NULL, },
+#endif
+#ifdef EREMOTE
+ { EREMOTE, NULL, },
+#endif
+#ifdef ENOLINK
+ { ENOLINK, NULL, },
+#endif
+#ifdef EADV
+ { EADV, NULL, },
+#endif
+#ifdef ESRMNT
+ { ESRMNT, NULL, },
+#endif
+#ifdef ECOMM
+ { ECOMM, NULL, },
+#endif
+#ifdef EPROTO
+ { EPROTO, NULL, },
+#endif
+#ifdef EMULTIHOP
+ { EMULTIHOP, NULL, },
+#endif
+#ifdef EDOTDOT
+ { EDOTDOT, NULL, },
+#endif
+#ifdef EBADMSG
+ { EBADMSG, NULL, },
+#endif
+#ifdef EOVERFLOW
+ { EOVERFLOW, NULL, },
+#endif
+#ifdef ENOTUNIQ
+ { ENOTUNIQ, NULL, },
+#endif
+#ifdef EBADFD
+ { EBADFD, NULL, },
+#endif
+#ifdef EREMCHG
+ { EREMCHG, NULL, },
+#endif
+#ifdef ELIBACC
+ { ELIBACC, NULL, },
+#endif
+#ifdef ELIBBAD
+ { ELIBBAD, NULL, },
+#endif
+#ifdef ELIBSCN
+ { ELIBSCN, NULL, },
+#endif
+#ifdef ELIBMAX
+ { ELIBMAX, NULL, },
+#endif
+#ifdef ELIBEXEC
+ { ELIBEXEC, NULL, },
+#endif
+#ifdef EILSEQ
+ { EILSEQ, NULL, },
+#endif
+#ifdef ERESTART
+ { ERESTART, NULL, },
+#endif
+#ifdef ESTRPIPE
+ { ESTRPIPE, NULL, },
+#endif
+#ifdef EUSERS
+ { EUSERS, NULL, },
+#endif
+#ifdef ENOTSOCK
+ { ENOTSOCK, NULL, },
+#endif
+#ifdef EDESTADDRREQ
+ { EDESTADDRREQ, NULL, },
+#endif
+#ifdef EMSGSIZE
+ { EMSGSIZE, NULL, },
+#endif
+#ifdef EPROTOTYPE
+ { EPROTOTYPE, NULL, },
+#endif
+#ifdef ENOPROTOOPT
+ { ENOPROTOOPT, NULL, },
+#endif
+#ifdef EPROTONOSUPPORT
+ { EPROTONOSUPPORT, NULL, },
+#endif
+#ifdef ESOCKTNOSUPPORT
+ { ESOCKTNOSUPPORT, NULL, },
+#endif
+#ifdef EOPNOTSUPP
+ { EOPNOTSUPP, NULL, },
+#endif
+#ifdef EPFNOSUPPORT
+ { EPFNOSUPPORT, NULL, },
+#endif
+#ifdef EAFNOSUPPORT
+ { EAFNOSUPPORT, NULL, },
+#endif
+#ifdef EADDRINUSE
+ { EADDRINUSE, NULL, },
+#endif
+#ifdef EADDRNOTAVAIL
+ { EADDRNOTAVAIL, NULL, },
+#endif
+#ifdef ENETDOWN
+ { ENETDOWN, NULL, },
+#endif
+#ifdef ENETUNREACH
+ { ENETUNREACH, NULL, },
+#endif
+#ifdef ENETRESET
+ { ENETRESET, NULL, },
+#endif
+#ifdef ECONNABORTED
+ { ECONNABORTED, NULL, },
+#endif
+#ifdef ECONNRESET
+ { ECONNRESET, NULL, },
+#endif
+#ifdef ENOBUFS
+ { ENOBUFS, NULL, },
+#endif
+#ifdef EISCONN
+ { EISCONN, NULL, },
+#endif
+#ifdef ENOTCONN
+ { ENOTCONN, NULL, },
+#endif
+#ifdef ESHUTDOWN
+ { ESHUTDOWN, NULL, },
+#endif
+#ifdef ETOOMANYREFS
+ { ETOOMANYREFS, NULL, },
+#endif
+#ifdef ETIMEDOUT
+ { ETIMEDOUT, NULL, },
+#endif
+#ifdef ECONNREFUSED
+ { ECONNREFUSED, NULL, },
+#endif
+#ifdef EHOSTDOWN
+ { EHOSTDOWN, NULL, },
+#endif
+#ifdef EHOSTUNREACH
+ { EHOSTUNREACH, NULL, },
+#endif
+#ifdef EALREADY
+ { EALREADY, NULL, },
+#endif
+#ifdef EINPROGRESS
+ { EINPROGRESS, NULL, },
+#endif
+#ifdef ESTALE
+ { ESTALE, NULL, },
+#endif
+#ifdef EUCLEAN
+ { EUCLEAN, NULL, },
+#endif
+#ifdef ENOTNAM
+ { ENOTNAM, NULL, },
+#endif
+#ifdef ENAVAIL
+ { ENAVAIL, NULL, },
+#endif
+#ifdef EISNAM
+ { EISNAM, NULL, },
+#endif
+#ifdef EREMOTEIO
+ { EREMOTEIO, NULL, },
+#endif
+#ifdef EDQUOT
+ { EDQUOT, NULL, },
+#endif
+#ifdef ECANCELED
+ { ECANCELED, NULL, },
+#endif
+#ifdef EKEYEXPIRED
+ { EKEYEXPIRED, NULL, },
+#endif
+#ifdef EKEYREJECTED
+ { EKEYREJECTED, NULL, },
+#endif
+#ifdef EKEYREVOKED
+ { EKEYREVOKED, NULL, },
+#endif
+#ifdef EMEDIUMTYPE
+ { EMEDIUMTYPE, NULL, },
+#endif
+#ifdef ENOKEY
+ { ENOKEY, NULL, },
+#endif
+#ifdef ENOMEDIUM
+ { ENOMEDIUM, NULL, },
+#endif
+#ifdef ENOTRECOVERABLE
+ { ENOTRECOVERABLE, NULL, },
+#endif
+#ifdef EOWNERDEAD
+ { EOWNERDEAD, NULL, },
+#endif
+#ifdef ERFKILL
+ { ERFKILL, NULL, },
+#endif
+#ifdef EAUTH
+ { EAUTH, NULL, },
+#endif
+#ifdef EBADRPC
+ { EBADRPC, NULL, },
+#endif
+#ifdef EDOOFUS
+ { EDOOFUS, NULL, },
+#endif
+#ifdef EFTYPE
+ { EFTYPE, NULL, },
+#endif
+#ifdef ENEEDAUTH
+ { ENEEDAUTH, NULL, },
+#endif
+#ifdef ENOATTR
+ { ENOATTR, NULL, },
+#endif
+#ifdef ENOTSUP
+ { ENOTSUP, NULL, },
+#endif
+#ifdef EPROCLIM
+ { EPROCLIM, NULL, },
+#endif
+#ifdef EPROCUNAVAIL
+ { EPROCUNAVAIL, NULL, },
+#endif
+#ifdef EPROGMISMATCH
+ { EPROGMISMATCH, NULL, },
+#endif
+#ifdef EPROGUNAVAIL
+ { EPROGUNAVAIL, NULL, },
+#endif
+#ifdef ERPCMISMATCH
+ { ERPCMISMATCH, NULL, },
+#endif
+#ifdef EIPSEC
+ { EIPSEC, NULL, },
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby-errno/test/errno.rb b/web/server/h2o/libh2o/deps/mruby-errno/test/errno.rb
new file mode 100644
index 00000000..79031156
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-errno/test/errno.rb
@@ -0,0 +1,60 @@
+assert('Errno') do
+ Errno.class == Module
+end
+
+assert('SystemCallError') do
+ SystemCallError.class == Class
+end
+
+assert('SystemCallError superclass') do
+ SystemCallError.superclass == StandardError
+end
+
+assert('SystemCallError#initialize') do
+ SystemCallError.new("a").message == "unknown error - a" and
+ SystemCallError.new("a", 12345).message == "Unknown error: 12345 - a" and
+ SystemCallError.new(12345).message == "Unknown error: 12345"
+end
+
+assert('SystemCallError#errno') do
+ assert_equal 1, SystemCallError.new("a", 1).errno
+ assert_equal 1, SystemCallError.new(1).errno
+ assert_equal 12345, SystemCallError.new("a", 12345).errno
+ assert_equal 23456, SystemCallError.new(23456).errno
+end
+
+assert('SystemCallError#inspect') do
+ SystemCallError.new("a").inspect == "SystemCallError: unknown error - a"
+ end
+
+assert('Errno::NOERROR') do
+ Errno::NOERROR.class == Class
+end
+
+# Is there any platform does not have EPERM?
+assert('Errno::EPERM') do
+ Errno::EPERM.class == Class
+end
+
+assert('Errno::EPERM superclass') do
+ Errno::EPERM.superclass == SystemCallError
+end
+
+assert('Errno::EPERM::Errno') do
+ Errno::EPERM::Errno.is_a? Fixnum
+end
+
+assert('Errno::EPERM#message') do
+ msg = Errno::EPERM.new.message
+ Errno::EPERM.new("a").message == "#{msg} - a"
+end
+
+assert('Errno::EPERM#inspect 1') do
+ msg = Errno::EPERM.new.message
+ Errno::EPERM.new.inspect == "Errno::EPERM: #{msg}"
+end
+
+assert('Errno::EPERM#inspect 2') do
+ msg = Errno::EPERM.new.message
+ Errno::EPERM.new("a").inspect == "Errno::EPERM: #{msg} - a"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/.gitignore b/web/server/h2o/libh2o/deps/mruby-file-stat/.gitignore
new file mode 100644
index 00000000..415be354
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/.gitignore
@@ -0,0 +1,5 @@
+*.o
+autom4te.cache/
+*.log
+config.status
+config.h
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/.travis.yml b/web/server/h2o/libh2o/deps/mruby-file-stat/.travis.yml
new file mode 100644
index 00000000..e630dcb1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/.travis.yml
@@ -0,0 +1,15 @@
+language: c
+compiler:
+ - gcc
+ - clang
+before_install:
+ - sudo apt-get -qq update
+install:
+ - sudo apt-get -qq install rake bison git gperf
+before_script:
+ - cd ../
+ - git clone https://github.com/mruby/mruby.git
+ - cd mruby
+ - cp -fp ../mruby-file-stat/.travis_build_config.rb build_config.rb
+script:
+ - ruby minirake all test
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/.travis_build_config.rb b/web/server/h2o/libh2o/deps/mruby-file-stat/.travis_build_config.rb
new file mode 100644
index 00000000..623303eb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/.travis_build_config.rb
@@ -0,0 +1,7 @@
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+ conf.enable_test
+
+ conf.gem '../mruby-file-stat'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/README.md b/web/server/h2o/libh2o/deps/mruby-file-stat/README.md
new file mode 100644
index 00000000..ebf7cec3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/README.md
@@ -0,0 +1,82 @@
+# mruby-file-stat
+
+[![Build Status](https://travis-ci.org/ksss/mruby-file-stat.svg?branch=master)](https://travis-ci.org/ksss/mruby-file-stat)
+[![Build status](https://ci.appveyor.com/api/projects/status/04am84uda2cj49n3/branch/master?svg=true)](https://ci.appveyor.com/project/ksss/mruby-file-stat/branch/master)
+
+**File::Stat** class in mruby
+
+```ruby
+stat = File::Stat.new('filename') # or File.stat('filename')
+stat.dev #=> device id
+stat.dev_major #=> device major id
+stat.dev_minor #=> device minor id
+stat.ino #=> i-node number
+stat.mode #=> permission value (st_mode)
+stat.nlink #=> hard link count
+stat.uid #=> user id
+stat.gid #=> group id
+stat.rdev #=> device type
+stat.rdev_major #=> rdev major id
+stat.rdev_minor #=> rdev minor id
+stat.atime #=> last access time
+stat.mtime #=> last modify time
+stat.ctime #=> last change attribute time
+stat.birthtime #=> file created time
+stat.size #=> file size(byte)
+stat.blksize #=> file I/O block size
+stat.blocks #=> attached block num
+stat.grpowned #=> same gid?
+stat.<=> #=> comparate mtime (-1,0,1 or nil)
+stat.size?
+stat.zero?
+stat.symlink?
+stat.file?
+stat.directory?
+stat.chardev?
+stat.blockdev?
+stat.pipe?
+stat.socket?
+stat.owned?
+stat.owned_real?
+stat.readable?
+stat.readable_real?
+stat.writable?
+stat.writable_real?
+stat.executable?
+stat.executable_real?
+stat.world_readable?
+stat.world_writable?
+stat.setuid?
+stat.setgid?
+stat.sticky?
+stat.ftype #=> socket, link, file, blockSpecial, directory, characterSpecial, fifo or unknown
+```
+
+This library is wrap of struct stat.
+
+## Installation
+
+### use github repository
+
+Write in /mruby/build_config.rb
+
+```ruby
+MRuby::Build.new do |conf|
+ # by mgem
+ conf.gem :mgem => 'mruby-file-stat'
+ # by github
+ conf.gem :github => 'ksss/mruby-file-stat', :branch => 'master'
+end
+```
+
+## Homepage
+
+https://github.com/ksss/mruby-file-stat
+
+## License
+
+See [https://github.com/ruby/ruby/blob/trunk/file.c](https://github.com/ruby/ruby/blob/trunk/file.c)
+
+## Doc
+
+[http://ruby-doc.org/core-2.1.5/File/Stat.html](http://ruby-doc.org/core-2.1.5/File/Stat.html)
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/appveyor.yml b/web/server/h2o/libh2o/deps/mruby-file-stat/appveyor.yml
new file mode 100644
index 00000000..f47afa99
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/appveyor.yml
@@ -0,0 +1,19 @@
+---
+version: "#{build}"
+environment:
+ MRUBY_CONFIG: "C:/projects/mruby-file-stat/.travis_build_config.rb"
+ matrix:
+ - Compiler: mingw
+
+install:
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
+ - set PATH=C:\MinGW\bin;C:\MinGW\msys\1.0\bin;%PATH%
+ - ruby --version
+ - gem --version
+ - gcc --version
+ - gem install rake --force
+ - cd ..
+ - git clone --depth 1 https://github.com/mruby/mruby.git
+ - cd mruby
+build_script:
+ - ruby minirake all test --trace --verbose
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/config.h.in b/web/server/h2o/libh2o/deps/mruby-file-stat/config.h.in
new file mode 100644
index 00000000..27cc7e6f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/config.h.in
@@ -0,0 +1,19 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if your system has a working `getgroups' function. */
+#undef HAVE_GETGROUPS
+
+/* Define to 1 if you have the `lstat' function. */
+#undef HAVE_LSTAT
+
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLOCKS
+
+/* Define to 1 if `st_rdev' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_RDEV
+
+/* Define to 1 if `st_birthtimespec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/configure b/web/server/h2o/libh2o/deps/mruby-file-stat/configure
new file mode 100755
index 00000000..517c66c4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/configure
@@ -0,0 +1,4320 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="src/file-stat.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_rdev" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_birthtimespec" "ac_cv_member_struct_stat_st_birthtimespec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_birthtimespec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC 1
+_ACEOF
+
+
+fi
+
+
+for ac_func in getgroups
+do :
+ ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups"
+if test "x$ac_cv_func_getgroups" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETGROUPS 1
+_ACEOF
+
+fi
+done
+
+for ac_func in lstat
+do :
+ ac_fn_c_check_func "$LINENO" "lstat" "ac_cv_func_lstat"
+if test "x$ac_cv_func_lstat" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LSTAT 1
+_ACEOF
+
+fi
+done
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/configure.ac b/web/server/h2o/libh2o/deps/mruby-file-stat/configure.ac
new file mode 100644
index 00000000..ce6be3fa
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/configure.ac
@@ -0,0 +1,20 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT()
+
+AC_PROG_CC
+
+AC_CONFIG_SRCDIR([src/file-stat.c])
+AC_CONFIG_HEADERS([config.h])
+
+AC_CHECK_MEMBERS([struct stat.st_blksize])
+AC_CHECK_MEMBERS([struct stat.st_blocks])
+AC_CHECK_MEMBERS([struct stat.st_rdev])
+AC_CHECK_MEMBERS([struct stat.st_birthtimespec])
+
+AC_CHECK_FUNCS(getgroups)
+AC_CHECK_FUNCS(lstat)
+
+AC_OUTPUT
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-file-stat/mrbgem.rake
new file mode 100644
index 00000000..ff7d076b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/mrbgem.rake
@@ -0,0 +1,32 @@
+MRuby::Gem::Specification.new('mruby-file-stat') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'ksss <co000ri@gmail.com>'
+ spec.add_dependency('mruby-time')
+
+ env = {
+ 'CC' => "#{build.cc.command} #{build.cc.flags.join(' ')}",
+ 'CXX' => "#{build.cxx.command} #{build.cxx.flags.join(' ')}",
+ 'LD' => "#{build.linker.command} #{build.linker.flags.join(' ')}",
+ 'AR' => build.archiver.command
+ }
+ config = "#{build_dir}/config.h"
+
+ file config do
+ FileUtils.mkdir_p build_dir, :verbose => true
+ Dir.chdir build_dir do
+ if ENV['OS'] == 'Windows_NT'
+ _pp 'on Windows', dir
+ FileUtils.touch "#{build_dir}/config.h", :verbose => true
+ else
+ _pp './configure', dir
+ system env, "#{dir}/configure"
+ end
+ end
+ end
+ file "#{dir}/src/file-stat.c" => config
+ task :clean do
+ FileUtils.rm_f config, :verbose => true
+ end
+
+ cc.include_paths << build_dir
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/ext.rb b/web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/ext.rb
new file mode 100644
index 00000000..1fda1869
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/ext.rb
@@ -0,0 +1,5 @@
+class File
+ def self.stat(fname)
+ File::Stat.new(fname)
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/file-stat.rb b/web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/file-stat.rb
new file mode 100644
index 00000000..23ded179
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/mrblib/file-stat.rb
@@ -0,0 +1,52 @@
+class File
+ class Stat
+ include Comparable
+
+ def <=>(other)
+ if other.kind_of?(self.class)
+ self.mtime <=> other.mtime
+ else
+ nil
+ end
+ end
+
+ def inspect
+ _dev = dev
+ _dev = "0x#{_dev.to_s(16)}" if _dev.kind_of?(Fixnum)
+ _mode = mode
+ _mode = "0#{_mode.to_s(8)}" if _mode.kind_of?(Fixnum)
+ _rdev = rdev
+ _rdev = "0x#{_rdev.to_s(16)}" if _rdev.kind_of?(Fixnum)
+
+ stats = {
+ 'dev' => _dev,
+ 'ino' => ino,
+ 'mode' => _mode,
+ 'nlink' => nlink,
+ 'uid' => uid,
+ 'gid' => gid,
+ 'rdev' => _rdev,
+ 'size' => size,
+ 'blksize' => blksize,
+ 'blocks' => blocks,
+ 'atime' => atime,
+ 'mtime' => mtime,
+ 'ctime' => ctime,
+ }
+ if respond_to? :birthtime
+ stats['birthtime'] = birthtime
+ end
+
+ "#<#{self.class.to_s} #{stats.map{|k, v| "#{k}=#{v}"}.join(', ')}>"
+ end
+
+ def size?
+ s = size
+ s == 0 ? nil : s
+ end
+
+ def zero?
+ size == 0
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/src/file-stat.c b/web/server/h2o/libh2o/deps/mruby-file-stat/src/file-stat.c
new file mode 100644
index 00000000..f36ed197
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/src/file-stat.c
@@ -0,0 +1,873 @@
+/**
+ * original is https://github.com/ruby/ruby/blob/trunk/file.c
+ */
+
+#include "mruby.h"
+#include "mruby/string.h"
+#include "mruby/data.h"
+#include "mruby/error.h"
+#include "mruby/class.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+
+#if !defined S_IXUSR && !defined __MINGW32__
+# define S_IXUSR 0100
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0010
+#endif
+#ifndef S_IXOTH
+# define S_IXOTH 0001
+#endif
+
+#else
+#include <unistd.h>
+#endif
+
+#ifndef S_IRUGO
+# define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH)
+#endif
+
+#ifndef S_IWUGO
+# define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH)
+#endif
+
+#ifndef S_IXUGO
+# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
+#endif
+
+#ifndef S_ISLNK
+# ifdef _S_ISLNK
+# define S_ISLNK(m) _S_ISLNK(m)
+# else
+# ifdef _S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
+# else
+# ifdef S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# endif
+# endif
+# endif
+#endif
+
+#ifdef S_IFIFO
+# ifndef S_ISFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# endif
+#endif
+
+#ifndef S_ISSOCK
+# ifdef _S_ISSOCK
+# define S_ISSOCK(m) _S_ISSOCK(m)
+# else
+# ifdef _S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
+# else
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# endif
+# endif
+# endif
+#endif
+
+#ifndef S_ISBLK
+# ifdef S_IFBLK
+# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+# else
+# define S_ISBLK(m) (0) /* anytime false */
+# endif
+#endif
+
+#ifndef S_ISCHR
+# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+
+#ifndef S_ISREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+#include "config.h"
+
+#define STAT(p,s) stat(p,s)
+#ifdef HAVE_LSTAT
+# define LSTAT(p,s) lstat(p,s)
+#else
+# define LSTAT(p,s) stat(p,s)
+#endif
+#define MRB_MAX_GROUPS (65536)
+
+#if defined(_WIN32) || defined(_WIN64)
+typedef unsigned int uid_t;
+typedef unsigned int gid_t;
+uid_t
+getuid(void)
+{
+ return 0;
+}
+uid_t
+geteuid(void)
+{
+ return 0;
+}
+gid_t
+getgid(void)
+{
+ return 0;
+}
+gid_t
+getegid(void)
+{
+ return 0;
+}
+#endif
+#define GETGROUPS_T gid_t
+
+#if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
+# define USE_GETEUID 1
+#endif
+
+#ifdef __native_client__
+# undef USE_GETEUID
+#endif
+
+struct mrb_data_type mrb_stat_type = { "File::Stat", mrb_free };
+
+static struct stat *
+mrb_stat_alloc(mrb_state *mrb)
+{
+ return (struct stat *)mrb_malloc(mrb, sizeof(struct stat));
+}
+
+static mrb_value
+file_s_lstat(mrb_state *mrb, mrb_value klass)
+{
+ struct RClass *file_class;
+ struct RClass *stat_class;
+ struct stat st, *ptr;
+ mrb_value fname, tmp;
+ char *path;
+
+ mrb_get_args(mrb, "o", &fname);
+
+ tmp = mrb_check_convert_type(mrb, fname, MRB_TT_STRING, "String", "to_path");
+ if (mrb_nil_p(tmp)) {
+ tmp = mrb_convert_type(mrb, fname, MRB_TT_STRING, "String", "to_str");
+ }
+ path = mrb_str_to_cstr(mrb, tmp);
+ if (LSTAT(path, &st) == -1) {
+ mrb_sys_fail(mrb, path);
+ }
+
+ file_class = mrb_class_ptr(klass);
+ stat_class = mrb_class_get_under(mrb, file_class, "Stat");
+ ptr = mrb_stat_alloc(mrb);
+ *ptr = st;
+
+ return mrb_obj_value(Data_Wrap_Struct(mrb, stat_class, &mrb_stat_type, ptr));
+}
+
+static mrb_value
+stat_initialize(mrb_state *mrb, mrb_value self)
+{
+ struct stat st, *ptr;
+ mrb_value fname, tmp;
+ char *path;
+
+ mrb_get_args(mrb, "o", &fname);
+
+ tmp = mrb_check_convert_type(mrb, fname, MRB_TT_STRING, "String", "to_path");
+ if (mrb_nil_p(tmp)) {
+ tmp = mrb_convert_type(mrb, fname, MRB_TT_STRING, "String", "to_str");
+ }
+ path = mrb_str_to_cstr(mrb, tmp);
+ if (STAT(path, &st) == -1) {
+ mrb_sys_fail(mrb, path);
+ }
+
+ ptr = (struct stat *)DATA_PTR(self);
+ if (ptr) {
+ mrb_free(mrb, ptr);
+ }
+
+ ptr = mrb_stat_alloc(mrb);
+ *ptr = st;
+
+ DATA_TYPE(self) = &mrb_stat_type;
+ DATA_PTR(self) = ptr;
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+stat_initialize_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_value orig;
+
+ mrb_get_args(mrb, "o", &orig);
+
+ if (mrb_obj_equal(mrb, copy, orig)) return copy;
+
+ if (!mrb_obj_is_instance_of(mrb, orig, mrb_obj_class(mrb, copy))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+
+ if (DATA_PTR(copy)) {
+ mrb_free(mrb, DATA_PTR(copy));
+ DATA_PTR(copy) = 0;
+ }
+
+ if (DATA_PTR(orig)) {
+ DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct stat));
+ DATA_TYPE(copy) = &mrb_stat_type;
+ *(struct stat *)DATA_PTR(copy) = *(struct stat *)DATA_PTR(orig);
+ }
+ return copy;
+}
+
+static struct stat *
+get_stat(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st;
+
+ st = (struct stat *)mrb_data_get_ptr(mrb, self, &mrb_stat_type);
+ if (!st) mrb_raise(mrb, E_TYPE_ERROR, "uninitialized File::Stat");
+ return st;
+}
+
+static mrb_value
+mrb_ll2num(mrb_state *mrb, long long t)
+{
+ if (MRB_INT_MIN <= t && t <= MRB_INT_MAX) {
+ return mrb_fixnum_value((mrb_int)t);
+ } else {
+ return mrb_float_value(mrb, (mrb_float)t);
+ }
+}
+
+static mrb_value
+io_stat(mrb_state *mrb, mrb_value self)
+{
+ struct RClass *file_class;
+ struct RClass *stat_class;
+ struct stat st, *ptr;
+ mrb_value fileno;
+
+ if (mrb_respond_to(mrb, self, mrb_intern_lit(mrb, "fileno"))) {
+ fileno = mrb_funcall(mrb, self, "fileno", 0);
+ }
+ else {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "`fileno' is not implemented");
+ }
+
+ if (fstat(mrb_fixnum(fileno), &st) == -1) {
+ mrb_sys_fail(mrb, "fstat");
+ }
+
+ file_class = mrb_class_get(mrb, "File");
+ stat_class = mrb_class_get_under(mrb, file_class, "Stat");
+ ptr = mrb_stat_alloc(mrb);
+ *ptr = st;
+
+ return mrb_obj_value(Data_Wrap_Struct(mrb, stat_class, &mrb_stat_type, ptr));
+}
+
+static mrb_value
+stat_dev(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(get_stat(mrb, self)->st_dev);
+}
+
+static mrb_value
+stat_dev_major(mrb_state *mrb, mrb_value self)
+{
+#if defined(major)
+ return mrb_fixnum_value(major(get_stat(mrb, self)->st_dev));
+#else
+ return mrb_nil_value(); // NotImplemented
+#endif
+}
+
+static mrb_value
+stat_dev_minor(mrb_state *mrb, mrb_value self)
+{
+#if defined(minor)
+ return mrb_fixnum_value(minor(get_stat(mrb, self)->st_dev));
+#else
+ return mrb_nil_value(); // NotImplemented
+#endif
+}
+
+static mrb_value
+stat_ino(mrb_state *mrb, mrb_value self)
+{
+ return mrb_ll2num(mrb, get_stat(mrb, self)->st_ino);
+}
+
+static mrb_value
+stat_mode(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(get_stat(mrb, self)->st_mode);
+}
+
+static mrb_value
+stat_nlink(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(get_stat(mrb, self)->st_nlink);
+}
+
+static mrb_value
+stat_uid(mrb_state *mrb, mrb_value self)
+{
+ return mrb_ll2num(mrb, get_stat(mrb, self)->st_uid);
+}
+
+static mrb_value
+stat_gid(mrb_state *mrb, mrb_value self)
+{
+ return mrb_ll2num(mrb, get_stat(mrb, self)->st_gid);
+}
+
+static mrb_value
+stat_rdev(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(get_stat(mrb, self)->st_rdev);
+}
+
+static mrb_value
+stat_rdev_major(mrb_state *mrb, mrb_value self)
+{
+#if defined(major)
+ return mrb_fixnum_value(major(get_stat(mrb, self)->st_rdev));
+#else
+ return mrb_nil_value(); // NotImplemented
+#endif
+}
+
+static mrb_value
+stat_rdev_minor(mrb_state *mrb, mrb_value self)
+{
+#if defined(minor)
+ return mrb_fixnum_value(minor(get_stat(mrb, self)->st_rdev));
+#else
+ return mrb_nil_value(); // NotImplemented
+#endif
+}
+
+static mrb_value
+time_at_with_sec(mrb_state *mrb, long long sec)
+{
+ return mrb_funcall(mrb, mrb_obj_value(mrb_class_get(mrb, "Time")), "at", 1, mrb_ll2num(mrb, sec));
+}
+
+static mrb_value
+stat_atime(mrb_state *mrb, mrb_value self)
+{
+ return time_at_with_sec(mrb, get_stat(mrb, self)->st_atime);
+}
+
+static mrb_value
+stat_mtime(mrb_state *mrb, mrb_value self)
+{
+ return time_at_with_sec(mrb, get_stat(mrb, self)->st_mtime);
+}
+
+static mrb_value
+stat_ctime(mrb_state *mrb, mrb_value self)
+{
+ return time_at_with_sec(mrb, get_stat(mrb, self)->st_ctime);
+}
+
+#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
+static mrb_value
+stat_birthtime(mrb_state *mrb, mrb_value self)
+{
+ return time_at_with_sec(mrb, get_stat(mrb, self)->st_birthtimespec.tv_sec);
+}
+# define HAVE_METHOD_BIRTHTIME 1
+#elif defined(_WIN32)
+# define stat_birthtime stat_ctime
+# define HAVE_METHOD_BIRTHTIME 1
+#endif
+
+static mrb_value
+stat_size(mrb_state *mrb, mrb_value self)
+{
+ return mrb_ll2num(mrb, get_stat(mrb, self)->st_size);
+}
+
+static mrb_value
+stat_blksize(mrb_state *mrb, mrb_value self)
+{
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+ return mrb_fixnum_value(get_stat(mrb, self)->st_blksize);
+#else
+ return mrb_nil_value();
+#endif
+}
+
+static mrb_value
+stat_blocks(mrb_state *mrb, mrb_value self)
+{
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+ return mrb_ll2num(mrb, get_stat(mrb, self)->st_blocks);
+#else
+ return mrb_nil_value();
+#endif
+}
+
+static int
+mrb_group_member(mrb_state *mrb, GETGROUPS_T gid)
+{
+#if defined(_WIN32) || !defined(HAVE_GETGROUPS)
+ return FALSE;
+#else
+ int rv = FALSE;
+ int groups = 16;
+ GETGROUPS_T *gary = NULL;
+ int anum = -1;
+
+ if (getgid() == gid || getegid() == gid)
+ return TRUE;
+
+ /*
+ * On Mac OS X (Mountain Lion), NGROUPS is 16. But libc and kernel
+ * accept more larger value.
+ * So we don't trunk NGROUPS anymore.
+ */
+ while (groups <= MRB_MAX_GROUPS) {
+ gary = (GETGROUPS_T*)mrb_malloc(mrb, sizeof(GETGROUPS_T) * (unsigned int)groups);
+ anum = getgroups(groups, gary);
+ if (anum != -1 && anum != groups)
+ break;
+ groups *= 2;
+ if (gary) {
+ mrb_free(mrb, gary);
+ gary = 0;
+ }
+ }
+ if (anum == -1)
+ return FALSE;
+
+ while (--anum >= 0) {
+ if (gary[anum] == gid) {
+ rv = TRUE;
+ break;
+ }
+ }
+
+ if (gary) {
+ mrb_free(mrb, gary);
+ }
+ return rv;
+#endif
+}
+
+static mrb_value
+stat_grpowned_p(mrb_state *mrb, mrb_value self)
+{
+#ifndef _WIN32
+ if (mrb_group_member(mrb, get_stat(mrb, self)->st_gid)) return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_readable_p(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st;
+#ifdef USE_GETEUID
+ if (geteuid() == 0)
+ return mrb_true_value();
+#endif
+ st = get_stat(mrb, self);
+#ifdef S_IRUSR
+ if (st->st_uid == geteuid())
+ return st->st_mode & S_IRUSR ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IRGRP
+ if (mrb_group_member(mrb, st->st_gid))
+ return st->st_mode & S_IRGRP ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IROTH
+ if (!(st->st_mode & S_IROTH))
+ return mrb_false_value();
+#endif
+ return mrb_true_value();
+}
+
+static mrb_value
+stat_readable_real_p(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st;
+
+#ifdef USE_GETEUID
+ if (getuid() == 0)
+ return mrb_true_value();
+#endif
+ st = get_stat(mrb, self);
+#ifdef S_IRUSR
+ if (st->st_uid == getuid())
+ return st->st_mode & S_IRUSR ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IRGRP
+ if (mrb_group_member(mrb, st->st_gid))
+ return st->st_mode & S_IRGRP ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IROTH
+ if (!(st->st_mode & S_IROTH)) return mrb_false_value();
+#endif
+ return mrb_true_value();
+}
+
+static mrb_value
+stat_world_readable_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_IROTH
+ struct stat *st = get_stat(mrb, self);
+ if ((st->st_mode & (S_IROTH)) == S_IROTH) {
+ return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ }
+ else {
+ return mrb_nil_value();
+ }
+#else
+ return mrb_nil_value();
+#endif
+}
+
+
+static mrb_value
+stat_writable_p(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st;
+
+#ifdef USE_GETEUID
+ if (geteuid() == 0)
+ return mrb_true_value();
+#endif
+ st = get_stat(mrb, self);
+#ifdef S_IWUSR
+ if (st->st_uid == geteuid())
+ return st->st_mode & S_IWUSR ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IWGRP
+ if (mrb_group_member(mrb, st->st_gid))
+ return st->st_mode & S_IWGRP ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IWOTH
+ if (!(st->st_mode & S_IWOTH))
+ return mrb_false_value();
+#endif
+ return mrb_true_value();
+}
+
+static mrb_value
+stat_writable_real_p(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st;
+
+#ifdef USE_GETEUID
+ if (getuid() == 0)
+ return mrb_true_value();
+#endif
+ st = get_stat(mrb, self);
+#ifdef S_IWUSR
+ if (st->st_uid == getuid())
+ return st->st_mode & S_IWUSR ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IWGRP
+ if (mrb_group_member(mrb, st->st_gid))
+ return st->st_mode & S_IWGRP ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IWOTH
+ if (!(st->st_mode & S_IWOTH)) return mrb_false_value();
+#endif
+ return mrb_true_value();
+}
+
+static mrb_value
+stat_world_writable_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_IROTH
+ struct stat *st = get_stat(mrb, self);
+ if ((st->st_mode & (S_IROTH)) == S_IROTH) {
+ return mrb_fixnum_value(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ }
+ else {
+ return mrb_nil_value();
+ }
+#else
+ return mrb_nil_value();
+#endif
+}
+
+static mrb_value
+stat_executable_p(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st = get_stat(mrb, self);
+
+#ifdef USE_GETEUID
+ if (geteuid() == 0) {
+ return st->st_mode & S_IXUGO ? mrb_true_value() : mrb_false_value();
+}
+#endif
+#ifdef S_IXUSR
+ if (st->st_uid == geteuid())
+ return st->st_mode & S_IXUSR ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IXGRP
+ if (mrb_group_member(mrb, st->st_gid))
+ return st->st_mode & S_IXGRP ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IXOTH
+ if (!(st->st_mode & S_IXOTH))
+ return mrb_false_value();
+#endif
+ return mrb_true_value();
+}
+
+static mrb_value
+stat_executable_real_p(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st = get_stat(mrb, self);
+
+#ifdef USE_GETEUID
+ if (getuid() == 0)
+ return st->st_mode & S_IXUGO ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IXUSR
+ if (st->st_uid == getuid())
+ return st->st_mode & S_IXUSR ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IXGRP
+ if (mrb_group_member(mrb, st->st_gid))
+ return st->st_mode & S_IXGRP ? mrb_true_value() : mrb_false_value();
+#endif
+#ifdef S_IXOTH
+ if (!(st->st_mode & S_IXOTH)) return mrb_false_value();
+#endif
+ return mrb_true_value();
+}
+
+static mrb_value
+stat_symlink_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISLNK
+ if (S_ISLNK(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_file_p(mrb_state *mrb, mrb_value self)
+{
+ if (S_ISREG(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_directory_p(mrb_state *mrb, mrb_value self)
+{
+ if (S_ISDIR(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_chardev_p(mrb_state *mrb, mrb_value self)
+{
+ if (S_ISCHR(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_blockdev_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISBLK
+ if (S_ISBLK(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_pipe_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISFIFO
+ if (S_ISFIFO(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_socket_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISSOCK
+ if (S_ISSOCK(get_stat(mrb, self)->st_mode))
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_setuid_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISUID
+ if (get_stat(mrb, self)->st_mode & S_ISUID)
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_setgid_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISGID
+ if (get_stat(mrb, self)->st_mode & S_ISGID)
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_sticky_p(mrb_state *mrb, mrb_value self)
+{
+#ifdef S_ISVTX
+ if (get_stat(mrb, self)->st_mode & S_ISVTX)
+ return mrb_true_value();
+#endif
+ return mrb_false_value();
+}
+
+static mrb_value
+stat_ftype(mrb_state *mrb, mrb_value self)
+{
+ struct stat *st = get_stat(mrb, self);
+ const char *t;
+
+ if (S_ISREG(st->st_mode)) {
+ t = "file";
+ }
+ else if (S_ISDIR(st->st_mode)) {
+ t = "directory";
+ }
+ else if (S_ISCHR(st->st_mode)) {
+ t = "characterSpecial";
+ }
+#ifdef S_ISBLK
+ else if (S_ISBLK(st->st_mode)) {
+ t = "blockSpecial";
+ }
+#endif
+#ifdef S_ISFIFO
+ else if (S_ISFIFO(st->st_mode)) {
+ t = "fifo";
+ }
+#endif
+#ifdef S_ISLNK
+ else if (S_ISLNK(st->st_mode)) {
+ t = "link";
+ }
+#endif
+#ifdef S_ISSOCK
+ else if (S_ISSOCK(st->st_mode)) {
+ t = "socket";
+ }
+#endif
+ else {
+ t = "unknown";
+ }
+ return mrb_str_new_static(mrb, t, (size_t)strlen(t));
+}
+
+static mrb_value
+stat_owned_p(mrb_state *mrb, mrb_value self)
+{
+ return get_stat(mrb, self)->st_uid == geteuid() ? mrb_true_value() : mrb_false_value();
+}
+
+static mrb_value
+stat_owned_real_p(mrb_state *mrb, mrb_value self)
+{
+ return get_stat(mrb, self)->st_uid == getuid() ? mrb_true_value() : mrb_false_value();
+}
+
+void
+mrb_mruby_file_stat_gem_init(mrb_state* mrb)
+{
+ struct RClass *io = mrb_define_class(mrb, "IO", mrb->object_class);
+ struct RClass *file = mrb_define_class(mrb, "File", io);
+ struct RClass *stat = mrb_define_class_under(mrb, file, "Stat", mrb->object_class);
+
+ MRB_SET_INSTANCE_TT(stat, MRB_TT_DATA);
+
+ mrb_define_method(mrb, io, "stat", io_stat, MRB_ARGS_NONE());
+
+ mrb_define_class_method(mrb, file, "lstat", file_s_lstat, MRB_ARGS_REQ(1));
+
+ mrb_define_method(mrb, stat, "initialize", stat_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, stat, "initialize_copy", stat_initialize_copy, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, stat, "dev", stat_dev, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "dev_major", stat_dev_major, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "dev_minor", stat_dev_minor, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "ino", stat_ino, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "mode", stat_mode, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "nlink", stat_nlink, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "uid", stat_uid, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "gid", stat_gid, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "rdev", stat_rdev, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "rdev_major", stat_rdev_major, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "rdev_minor", stat_rdev_minor, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "atime", stat_atime, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "mtime", stat_mtime, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "ctime", stat_ctime, MRB_ARGS_NONE());
+#ifdef HAVE_METHOD_BIRTHTIME
+ mrb_define_method(mrb, stat, "birthtime", stat_birthtime, MRB_ARGS_NONE());
+#endif
+ mrb_define_method(mrb, stat, "size", stat_size, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "blksize", stat_blksize, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "blocks", stat_blocks, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "grpowned?", stat_grpowned_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "readable?", stat_readable_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "readable_real?", stat_readable_real_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "world_readable?", stat_world_readable_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "writable?", stat_writable_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "writable_real?", stat_writable_real_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "world_writable?", stat_world_writable_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "executable?", stat_executable_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "executable_real?", stat_executable_real_p, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, stat, "symlink?", stat_symlink_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "file?", stat_file_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "directory?", stat_directory_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "chardev?", stat_chardev_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "blockdev?", stat_blockdev_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "pipe?", stat_pipe_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "socket?", stat_socket_p, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, stat, "setuid?", stat_setuid_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "setgid?", stat_setgid_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "sticky?", stat_sticky_p, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, stat, "ftype", stat_ftype, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, stat, "owned?", stat_owned_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, stat, "owned_real?", stat_owned_real_p, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_file_stat_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/test/executable b/web/server/h2o/libh2o/deps/mruby-file-stat/test/executable
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/test/executable
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.c b/web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.c
new file mode 100644
index 00000000..4e596648
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.c
@@ -0,0 +1,30 @@
+#include <mruby.h>
+#include <stdlib.h>
+
+static mrb_value
+test_system(mrb_state *mrb, mrb_value klass)
+{
+ char *cmd = NULL;
+ mrb_get_args(mrb, "z", &cmd);
+ system(cmd);
+ return mrb_nil_value();
+}
+
+static mrb_value
+test_win_p(mrb_state *mrb, mrb_value klass)
+{
+#if defined(_WIN32)
+ return mrb_true_value();
+#else
+ return mrb_false_value();
+#endif
+}
+
+void mrb_mruby_file_stat_gem_test(mrb_state *mrb)
+{
+ struct RClass *t;
+
+ t = mrb_define_class(mrb, "FileStatTest", mrb->object_class);
+ mrb_define_module_function(mrb, t, "system", test_system, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, t, "win?", test_win_p, MRB_ARGS_NONE());
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.rb b/web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.rb
new file mode 100644
index 00000000..63906d01
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/test/file-stat.rb
@@ -0,0 +1,369 @@
+class FileStatTest
+ class << self
+ def chmod(mode, path)
+ system("chmod #{mode} #{path}")
+ yield
+ ensure
+ system("chmod 644 #{path}")
+ end
+ end
+end
+
+assert 'File::Stat.new' do
+ assert_kind_of File::Stat, File::Stat.new('README.md')
+ assert_raise(RuntimeError){ File::Stat.new('unknown.file') }
+end
+
+assert 'File.stat' do
+ assert_kind_of File::Stat, File.stat('README.md')
+end
+
+assert 'File.lstat' do
+ assert_kind_of File::Stat, File.lstat('README.md')
+end
+
+assert 'File::Stat#initialize_copy' do
+ orig = File::Stat.new('README.md')
+ copy = orig.dup
+ assert_equal orig.inspect, copy.inspect
+end
+
+assert 'File::Stat#<=>' do
+ stat1 = File::Stat.new('README.md')
+ stat2 = File::Stat.new('README.md')
+ assert_equal 0, stat1.<=>(stat2)
+ assert_equal nil, stat1.<=>(1)
+ assert_raise(ArgumentError) { stat1 < 1 }
+end
+
+assert 'File::Stat#dev' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Fixnum, stat.dev
+end
+
+assert 'File::Stat#dev_major' do
+ stat = File::Stat.new('README.md')
+ if stat.dev_major
+ assert_equal Fixnum, stat.dev_major.class
+ else
+ assert_nil stat.dev_major ## not supported
+ end
+end
+
+assert 'File::Stat#dev_minor' do
+ stat = File::Stat.new('README.md')
+ if stat.dev_minor
+ assert_equal Fixnum, stat.dev_minor.class
+ else
+ assert_nil stat.dev_minor ## not supported
+ end
+end
+
+assert 'File::Stat#ino' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Numeric, stat.ino
+end
+
+assert 'File::Stat#mode' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Fixnum, stat.mode
+end
+
+assert 'File::Stat#nlink' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Fixnum, stat.nlink
+end
+
+assert 'File::Stat#uid' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Numeric, stat.uid
+end
+
+assert 'File::Stat#gid' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Numeric, stat.gid
+end
+
+assert 'File::Stat#rdev' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Fixnum, stat.rdev
+end
+
+assert 'File::Stat#rdev_major' do
+ stat = File::Stat.new('README.md')
+ if stat.rdev_major
+ assert_equal Fixnum, stat.rdev_major.class
+ else
+ assert_nil stat.rdev_major ## not supported
+ end
+end
+
+assert 'File::Stat#rdev_minor' do
+ stat = File::Stat.new('README.md')
+ if stat.rdev_minor
+ assert_equal Fixnum, stat.rdev_minor.class
+ else
+ assert_nil stat.rdev_minor ## not supported
+ end
+end
+
+assert 'File::Stat#blocks' do
+ stat = File::Stat.new('README.md')
+ blocks = stat.blocks
+ skip "This system not support `struct stat.st_blocks`" if blocks.nil?
+
+ assert_kind_of Integer, blocks
+end
+
+assert 'File::Stat#atime' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Time, stat.atime
+end
+
+assert 'File::Stat#mtime' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Time, stat.mtime
+end
+
+assert 'File::Stat#ctime' do
+ stat = File::Stat.new('README.md')
+ assert_kind_of Time, stat.ctime
+end
+
+assert 'File::Stat#birthtime' do
+ stat = File::Stat.new('README.md')
+ begin
+ assert_kind_of Time, stat.birthtime
+ rescue NameError
+ skip 'This system not support `struct stat.birthtimespec`'
+ end
+end
+
+assert 'File::Stat#size' do
+ stat = File::Stat.new('README.md')
+ assert_true 0 < stat.size
+end
+
+assert 'File::Stat#blksize' do
+ stat = File::Stat.new('README.md')
+ blksize = stat.blksize
+ skip "This system not support `struct stat.st_blksize`" if blksize.nil?
+
+ assert_kind_of Integer, blksize
+end
+
+assert 'File::Stat#inspect' do
+ stat = File::Stat.new('README.md')
+ %w(dev ino mode nlink uid gid size blksize blocks atime mtime ctime).all? do |name|
+ assert_include stat.inspect, name
+ end
+end
+
+assert 'File::Stat#ftype' do
+ stat = File::Stat.new('README.md')
+ assert_equal "file", stat.ftype
+
+ stat = File::Stat.new('bin')
+ assert_equal "directory", stat.ftype
+end
+
+assert 'File::Stat#directory?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.directory?
+
+ stat = File::Stat.new('bin')
+ assert_true stat.directory?
+end
+
+assert 'File::Stat#readable?' do
+ skip "when windows" if FileStatTest.win?
+
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("+r-w-x", "#{dir}/test/readable") do
+ assert_true File::Stat.new("#{dir}/test/readable").readable?
+ end
+ FileStatTest.chmod("-r+w-x", "#{dir}/test/writable") do
+ assert_false File::Stat.new("#{dir}/test/writable").readable?
+ end
+ FileStatTest.chmod("-r-w+x", "#{dir}/test/executable") do
+ assert_false File::Stat.new("#{dir}/test/executable").readable?
+ end
+end
+
+assert 'File::Stat#readable_real?' do
+ skip "when windows" if FileStatTest.win?
+
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("+r-w-x", "#{dir}/test/readable") do
+ assert_true File::Stat.new("#{dir}/test/readable").readable_real?
+ end
+ FileStatTest.chmod("-r+w-x", "#{dir}/test/writable") do
+ assert_false File::Stat.new("#{dir}/test/writable").readable_real?
+ end
+ FileStatTest.chmod("-r-w+x", "#{dir}/test/executable") do
+ assert_false File::Stat.new("#{dir}/test/executable").readable_real?
+ end
+end
+
+assert 'File::Stat#world_readable?' do
+ skip "when windows" if FileStatTest.win?
+
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.system("chmod 0400 #{dir}/test/readable")
+ assert_equal nil, File::Stat.new("#{dir}/test/readable").world_readable?
+ FileStatTest.system("chmod 0444 #{dir}/test/readable")
+ assert_equal 0444, File::Stat.new("#{dir}/test/readable").world_readable?
+end
+
+assert 'File::Stat#writable?' do
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("+r-w-x", "#{dir}/test/readable") do
+ assert_false File::Stat.new("#{dir}/test/readable").writable?
+ end
+ FileStatTest.chmod("-r+w-x", "#{dir}/test/writable") do
+ assert_true File::Stat.new("#{dir}/test/writable").writable?
+ end
+ FileStatTest.chmod("-r-w+x", "#{dir}/test/executable") do
+ assert_false File::Stat.new("#{dir}/test/executable").writable?
+ end
+end
+
+assert 'File::Stat#writable_real?' do
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("+r-w-x", "#{dir}/test/readable") do
+ assert_false File::Stat.new("#{dir}/test/readable").writable_real?
+ end
+ FileStatTest.chmod("-r+w-x", "#{dir}/test/writable") do
+ assert_true File::Stat.new("#{dir}/test/writable").writable_real?
+ end
+ FileStatTest.chmod("-r-w+x", "#{dir}/test/executable") do
+ assert_false File::Stat.new("#{dir}/test/executable").writable_real?
+ end
+end
+
+assert 'File::Stat#world_writable?' do
+ skip "when windows" if FileStatTest.win?
+
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("0600", "#{dir}/test/writable") do
+ assert_equal nil, File::Stat.new("#{dir}/test/writable").world_writable?
+ end
+ FileStatTest.chmod("0666", "#{dir}/test/writable") do
+ assert_equal 0666, File::Stat.new("#{dir}/test/writable").world_writable?
+ end
+end
+
+assert 'File::Stat#executable?' do
+ skip "when windows" if FileStatTest.win?
+
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("+r-w-x", "#{dir}/test/readable") do
+ assert_false File::Stat.new("#{dir}/test/readable").executable?
+ end
+ FileStatTest.chmod("-r+w-x", "#{dir}/test/writable") do
+ assert_false File::Stat.new("#{dir}/test/writable").executable?
+ end
+ FileStatTest.chmod("-r-w+x", "#{dir}/test/executable") do
+ assert_true File::Stat.new("#{dir}/test/executable").executable?
+ end
+end
+
+assert 'File::Stat#executable_real?' do
+ skip "when windows" if FileStatTest.win?
+
+ dir = __FILE__[0..-18] # 18 = /test/file-stat.rb
+ FileStatTest.chmod("+r-w-x", "#{dir}/test/readable") do
+ assert_false File::Stat.new("#{dir}/test/readable").executable_real?
+ end
+ FileStatTest.chmod("-r+w-x", "#{dir}/test/writable") do
+ assert_false File::Stat.new("#{dir}/test/writable").executable_real?
+ end
+ FileStatTest.chmod("-r-w+x", "#{dir}/test/executable") do
+ assert_true File::Stat.new("#{dir}/test/executable").executable_real?
+ end
+end
+
+assert 'File::Stat#file?' do
+ stat = File::Stat.new('README.md')
+ assert_true stat.file?
+
+ stat = File::Stat.new('bin')
+ assert_false stat.file?
+end
+
+assert 'File::Stat#zero?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.zero?
+end
+
+assert 'File::Stat#size?' do
+ stat = File::Stat.new('README.md')
+ assert_true 0 < stat.size?
+end
+
+assert 'File::Stat#owned?' do
+ stat = File::Stat.new('README.md')
+ assert_true stat.owned?
+end
+
+assert 'File::Stat#owned_real?' do
+ stat = File::Stat.new('README.md')
+ assert_true stat.owned_real?
+end
+
+assert 'File::Stat#grpowned?' do
+ is_unix = File::Stat.new('/dev/tty') rescue false
+ if is_unix
+ stat = File::Stat.new('README.md')
+ assert_true stat.grpowned?
+ else
+ skip "is not supported"
+ end
+end
+
+assert 'File::Stat#pipe?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.pipe?
+end
+
+assert 'File::Stat#symlink?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.symlink?
+end
+
+assert 'File::Stat#socket?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.socket?
+end
+
+assert 'File::Stat#blockdev?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.blockdev?
+end
+
+assert 'File::Stat#chardev?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.chardev?
+
+ begin
+ stat = File::Stat.new('/dev/tty')
+ assert_true stat.chardev?
+ rescue RuntimeError
+ skip '/dev/tty is not found'
+ end
+end
+
+assert 'File::Stat#setuid?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.setuid?
+end
+
+assert 'File::Stat#setgid?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.setgid?
+end
+
+assert 'File::Stat#sticky?' do
+ stat = File::Stat.new('README.md')
+ assert_false stat.sticky?
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/test/io.rb b/web/server/h2o/libh2o/deps/mruby-file-stat/test/io.rb
new file mode 100644
index 00000000..47e63089
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/test/io.rb
@@ -0,0 +1,7 @@
+assert 'IO#stat' do
+ # You can use IO#stat if implemented to IO#fileno
+ # mruby-file-stat is just not implemented this.
+ assert_raise(NotImplementedError) do
+ IO.new(1).stat
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/test/readable b/web/server/h2o/libh2o/deps/mruby-file-stat/test/readable
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/test/readable
diff --git a/web/server/h2o/libh2o/deps/mruby-file-stat/test/writable b/web/server/h2o/libh2o/deps/mruby-file-stat/test/writable
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-file-stat/test/writable
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/.gitignore b/web/server/h2o/libh2o/deps/mruby-iijson/.gitignore
new file mode 100644
index 00000000..ceeb05b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/.gitignore
@@ -0,0 +1 @@
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/.travis.yml b/web/server/h2o/libh2o/deps/mruby-iijson/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/README.md b/web/server/h2o/libh2o/deps/mruby-iijson/README.md
new file mode 100644
index 00000000..bbbfeba6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/README.md
@@ -0,0 +1,87 @@
+# mruby-iijson
+[![Build Status](https://travis-ci.org/iij/mruby-iijson.svg?branch=master)](https://travis-ci.org/iij/mruby-iijson)
+
+"mruby-iijson" is JSON module for mruby.
+
+
+## Implemented Methods:
+ - [JSON.dump](http://docs.ruby-lang.org/en/2.2.0/JSON.html#method-i-dump)
+ - [JSON.generate](http://docs.ruby-lang.org/en/2.2.0/JSON.html#method-i-generate)
+ - [JSON.load](http://docs.ruby-lang.org/en/2.2.0/JSON.html#method-i-load)
+ - [JSON.parse](http://docs.ruby-lang.org/en/2.2.0/JSON.html#method-i-parse)
+ - `Array#to_json`, `Fixnum#to_json`, `Float#to_json`, `Hash#to_json`, `String#to_json`, ...
+
+## Example:
+
+```Ruby
+str = '{
+ "Image": {
+ "Width": 800,
+ "Height": 600,
+ "Title": "View from 15th Floor",
+ "Thumbnail": {
+ "Url": "http://www.example.com/image/481989943",
+ "Height": 125,
+ "Width": "100"
+ },
+ "IDs": [116, 943, 234, 38793]
+ }
+}'
+p JSON.parse(str)
+
+h = {
+ :precision => "zip",
+ :Latitude => 37.7668,
+ :Longitude => -122.3959,
+ :Address => "",
+ :City => "SAN FRANCISCO",
+ :State => "CA",
+ :Zip => "94107",
+ :Country => "US"
+}
+p h.to_json
+puts JSON.generate(h, {:pretty_print => true, :indent_with => 2})
+```
+
+```
+{"Image"=>{"Width"=>800, "Height"=>600, "Title"=>"View from 15th Floor", "Thumbnail"=>{"Url"=>"http://www.example.com/image/481989943", "Height"=>125, "Width"=>"100"}, "IDs"=>[116, 943, 234, 38793]}}
+"{\"precision\":\"zip\",\"Latitude\":37.766800000000003,\"Longitude\":-122.3959,\"Address\":\"\",\"City\":\"SAN FRANCISCO\",\"State\":\"CA\",\"Zip\":\"94107\",\"Country\":\"US\"}"
+{
+ "precision": "zip",
+ "Latitude": 37.766800000000003,
+ "Longitude": -122.3959,
+ "Address": "",
+ "City": "SAN FRANCISCO",
+ "State": "CA",
+ "Zip": "94107",
+ "Country": "US"
+}
+```
+
+
+## Caveats
+
+ - JSON.generate won't return if input Array/Hash has circular reference.
+
+
+## License
+
+Copyright (c) 2014 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-iijson/mrbgem.rake
new file mode 100644
index 00000000..fef1c3dd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-iijson') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'Internet Initiative Japan Inc.'
+
+ spec.add_dependency "mruby-sprintf", :core => "mruby-sprintf"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/mrblib/json.rb b/web/server/h2o/libh2o/deps/mruby-iijson/mrblib/json.rb
new file mode 100755
index 00000000..87b5a6bd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/mrblib/json.rb
@@ -0,0 +1,129 @@
+module JSON
+ def self.dump(object, io=nil, limit=nil)
+ state = {}
+ state[:max_nesting] = limit if limit
+ begin
+ js = JSON.generate(object, nil, state)
+ rescue JSON::NestingError
+ raise ArgumentError, "exceeded depth limit"
+ end
+ if io
+ io.write js
+ io
+ else
+ js
+ end
+ end
+
+ def self.generate(obj, options=nil, state=nil)
+ options = (options || {}).to_hash unless options.is_a? Hash
+ options[:pretty_print] ||= false
+ options[:indent_with] ||= 2
+ state = (state || {}).to_hash unless state.is_a? Hash
+ state[:max_nesting] ||= 100
+ state[:nesting] = 0
+ self.generate0(obj, options, state)
+ end
+
+ def self.generate0(obj, options, state)
+ if state[:nesting] >= state[:max_nesting]
+ raise JSON::NestingError, "nesting of #{state[:nesting]} is too deep"
+ end
+
+ pretty = options[:pretty_print]
+
+ if pretty
+ indent = options[:indent_with].class == Fixnum ? " " * options[:indent_with] : options[:indent_with]
+ else
+ indent = ""
+ end
+
+ nl = pretty ? "\n" : ""
+
+ if obj == false
+ return "false"
+
+ elsif obj == nil
+ return "null"
+
+ elsif obj == true
+ return "true"
+
+ elsif obj.is_a? Hash
+ members = []
+ state[:nesting] += 1
+ obj.each { |k, v|
+ members << JSON.generate0(k, options, state) + ":" + (pretty ? " " : "") + JSON.generate0(v, options, state)
+ }
+ if pretty
+ members.map! { |k| (indent * state[:nesting]) + "#{k}" }.join("_")
+ end
+ state[:nesting] -= 1
+ return "{" + nl + members.join("," + nl) + nl + (indent * state[:nesting]) + "}"
+
+ elsif obj.is_a? Array
+ state[:nesting] += 1
+ members = obj.map { |v| JSON.generate0(v, options, state) }
+ if pretty
+ members.map! { |k| (indent * state[:nesting]) + "#{k}" }.join("_")
+ end
+ state[:nesting] -= 1
+ return "[" + nl + members.join("," + nl) + nl + (indent * state[:nesting]) + "]"
+
+ elsif obj.is_a? Fixnum
+ return obj.to_s
+
+ elsif obj.is_a? Float
+ if obj.infinite? or obj.nan?
+ raise GeneratorError, "#{obj.to_s} not allowed in JSON"
+ end
+ sprintf "%.17g", obj
+
+ else
+ a = []
+ obj.to_s.each_char { |ch|
+ a << if ch < "\x20"
+ case ch
+ when "\x08"
+ "\\b"
+ when "\x0c"
+ "\\f"
+ when "\x0a"
+ "\\n"
+ when "\x0d"
+ "\\r"
+ when "\x09"
+ "\\t"
+ else
+ raise GeneratorError, "cannot convert #{ch.inspect} to JSON"
+ end
+ elsif ch == '"'
+ '\\"'
+ elsif ch == '\\'
+ "\\\\"
+ else
+ ch
+ end
+ }
+ return '"' + a.join + '"'
+ end
+ end
+
+ def self.load(source) # TODO: proc, options
+ source = source.read unless source.is_a? String
+ JSON.parse source
+ end
+
+ class JSONError < StandardError; end
+ class GeneratorError < JSONError; end
+ class ParserError < JSONError; end
+ class NestingError < ParserError; end
+end
+
+unless Float.method_defined? :nan?
+ class Float
+ def nan?
+ not (self == self)
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/mrblib/to_json.rb b/web/server/h2o/libh2o/deps/mruby-iijson/mrblib/to_json.rb
new file mode 100644
index 00000000..ee97ac2c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/mrblib/to_json.rb
@@ -0,0 +1,47 @@
+class Array
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class FalseClass
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class Fixnum
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class Float
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class Hash
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class NilClass
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class String
+ def to_json
+ JSON.generate(self)
+ end
+end
+
+class TrueClass
+ def to_json
+ JSON.generate(self)
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/run_test.rb b/web/server/h2o/libh2o/deps/mruby-iijson/run_test.rb
new file mode 100644
index 00000000..dece5070
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/run_test.rb
@@ -0,0 +1,23 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/src/json.c b/web/server/h2o/libh2o/deps/mruby-iijson/src/json.c
new file mode 100644
index 00000000..6836e090
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/src/json.c
@@ -0,0 +1,641 @@
+#include <ctype.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/hash.h"
+#include "mruby/string.h"
+#include "mruby/value.h"
+
+#define E_JSON_PARSER_ERROR (mrb_class_get_under(mrb, mrb_module_get(mrb, "JSON"), "ParserError"))
+
+#define JSON_EOF -1
+
+#define DEFAULT_MAX_NESTING 100
+
+struct json_parser {
+ mrb_state *mrb;
+ mrb_value src;
+ unsigned int cursor;
+ unsigned int lineno;
+ int nesting;
+
+ int max_nesting;
+};
+
+static void json_check_nesting(struct json_parser *);
+static int json_delimiter_p(char ch);
+static int json_getc(struct json_parser *);
+static void json_skip_ws(struct json_parser *);
+static void json_ungetc(struct json_parser *);
+static int json_unicode2utf8(uint32_t, char *);
+static int json_whitespace_p(char ch);
+
+static int json_parse_array(struct json_parser *, mrb_value *);
+static int json_parse_object(struct json_parser *, mrb_value *);
+static int json_parse_number2(struct json_parser *, int, mrb_value *, mrb_int, int);
+static int json_parse_string(struct json_parser *, mrb_value *);
+static int json_parse_value(struct json_parser *, mrb_value *);
+
+#if MRUBY_RELEASE_NO < 10000
+static struct RClass *
+mrb_module_get(mrb_state *mrb, const char *name)
+{
+ return mrb_class_get(mrb, name);
+}
+#endif
+#if !defined(MRB_PRId)
+#if defined(MRB_INT64)
+# define MRB_PRId PRId64
+#elif defined(MRB_INT16)
+# define MRB_PRId PRId16
+#else
+# define MRB_PRId PRId32
+#endif
+#endif /* !defined(MRB_PRId) */
+
+static void
+json_check_nesting(struct json_parser *parser)
+{
+ mrb_state *mrb = parser->mrb;
+
+ if (parser->max_nesting != -1) {
+ if (parser->nesting >= parser->max_nesting) {
+ // +1 for compatibility with CRuby
+ mrb_raisef(mrb, E_JSON_PARSER_ERROR, "nesting of %S is too deep", mrb_fixnum_value(parser->nesting+1));
+ }
+ }
+}
+
+static int
+json_delimiter_p(char ch)
+{
+ return (json_whitespace_p(ch) || ch == ',' || ch == ']' || ch == '}');
+}
+
+static int
+json_getc(struct json_parser *parser)
+{
+ if (parser->cursor < RSTRING_LEN(parser->src)) {
+ unsigned char ch = RSTRING_PTR(parser->src)[parser->cursor];
+ parser->cursor++;
+ return ch;
+ } else {
+ return JSON_EOF;
+ }
+}
+
+static int
+json_parse_readstring(struct json_parser *parser, const char *str)
+{
+ size_t len;
+ int ch;
+
+ len = strlen(str);
+ if (parser->cursor + len > RSTRING_LEN(parser->src))
+ return 0;
+ if (memcmp(str, RSTRING_PTR(parser->src) + parser->cursor, len) != 0)
+ return -1;
+ parser->cursor += len;
+ if (parser->cursor == RSTRING_LEN(parser->src))
+ return 1;
+ ch = RSTRING_PTR(parser->src)[parser->cursor];
+ if (!json_delimiter_p(ch))
+ return -1;
+ return 1;
+}
+
+static void
+json_skip_ws(struct json_parser *parser)
+{
+ int ch;
+
+ do {
+ ch = json_getc(parser);
+ if (ch == 0x0a)
+ parser->lineno++;
+ } while (json_whitespace_p(ch));
+ if (ch != JSON_EOF) {
+ json_ungetc(parser);
+ }
+}
+
+static void
+json_ungetc(struct json_parser *parser)
+{
+ if (parser->cursor > 0)
+ parser->cursor--;
+}
+
+static int
+json_unicode2utf8(uint32_t unicode, char *cp)
+{
+ int n = 0;
+ if (unicode < 0x80) {
+ cp[n++] = unicode;
+ } else if (unicode < 0x800) {
+ cp[n++] = 0xc0 + (unicode >> 6);
+ cp[n++] = 0x80 + (unicode & 0x3f);
+ } else if (unicode < 0x10000) {
+ cp[n++] = 0xe0 + (unicode >> 12);
+ cp[n++] = 0x80 + ((unicode >> 6) & 0x3f);
+ cp[n++] = 0x80 + (unicode & 0x3f);
+ } else {
+ cp[n++] = 0xf0 + (unicode >> 18);
+ cp[n++] = 0x80 + ((unicode >> 12) & 0x3f);
+ cp[n++] = 0x80 + ((unicode >> 6) & 0x3f);
+ cp[n++] = 0x80 + (unicode & 0x3f);
+ }
+ return n;
+}
+
+static int
+json_whitespace_p(char ch)
+{
+ return (ch == 0x20 || ch == 0x09 || ch == 0x0a || ch == 0x0d);
+}
+
+static int
+json_parse_array(struct json_parser *parser, mrb_value *result)
+{
+ mrb_state *mrb = parser->mrb;
+ mrb_value ary, v;
+ int ch;
+
+ json_check_nesting(parser);
+
+ ary = mrb_ary_new(mrb);
+
+ json_skip_ws(parser);
+ ch = json_getc(parser);
+ if (ch == ']') { /* easy case */
+ *result = ary;
+ return 1;
+ }
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "JSON_EOF in array(1)");
+ }
+ json_ungetc(parser);
+
+ while (1) {
+ parser->nesting++;
+ if (json_parse_value(parser, &v) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "error in array");
+ }
+ parser->nesting--;
+
+ mrb_ary_push(mrb, ary, v);
+
+ json_skip_ws(parser);
+ ch = json_getc(parser);
+ if (ch == ']') {
+ break;
+ }
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "JSON_EOF in array(2)");
+ }
+ if (ch != ',') {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "not ',' in array");
+ }
+ }
+ *result = ary;
+ return 1;
+}
+
+static int
+json_parse_object(struct json_parser *parser, mrb_value *result)
+{
+ mrb_state *mrb = parser->mrb;
+ mrb_value h, k, v;
+ int ch;
+
+ json_check_nesting(parser);
+
+ h = mrb_hash_new(mrb);
+
+ json_skip_ws(parser);
+ ch = json_getc(parser);
+ if (ch == '}') { /* easy case */
+ *result = h;
+ return 1;
+ }
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in object(1)");
+ }
+ json_ungetc(parser);
+
+ while (1) {
+ parser->nesting++;
+ if (json_parse_value(parser, &k) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "error in object key");
+ }
+ parser->nesting--;
+ if (! mrb_string_p(k)) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "key is not a string");
+ }
+
+ json_skip_ws(parser);
+
+ ch = json_getc(parser);
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in object(2)");
+ }
+ if (ch != ':') {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "no ':' in object");
+ }
+
+ parser->nesting++;
+ if (json_parse_value(parser, &v) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "error in object value");
+ }
+ parser->nesting--;
+
+ mrb_hash_set(mrb, h, k, v);
+
+ json_skip_ws(parser);
+ ch = json_getc(parser);
+ if (ch == '}') {
+ break;
+ }
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in object(3)");
+ }
+ if (ch != ',') {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "no ',' in object");
+ }
+ }
+ *result = h;
+ return 1;
+}
+
+static int
+json_parse_number(struct json_parser *parser, int ch, mrb_value *result)
+{
+ mrb_state *mrb = parser->mrb;
+ mrb_int num;
+ int d, sign;
+
+ if (ch == '-') {
+ sign = -1;
+ ch = json_getc(parser);
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "no character following minus");
+ }
+ if (!isdigit(ch)) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "character following minus is not a digit");
+ }
+ } else {
+ sign = 1;
+ }
+ num = (ch - '0') * sign;
+ while (1) {
+ ch = json_getc(parser);
+ if (ch == JSON_EOF) {
+ break;
+ }
+ if (isdigit(ch)) {
+ if (num == 0) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "leading zeros are not allowed");
+ }
+ d = (ch - '0') * sign;
+ if (num < MRB_INT_MIN / 10 ||
+ (num == MRB_INT_MIN / 10 && d < MRB_INT_MIN - num * 10) ||
+ num > MRB_INT_MAX / 10 ||
+ (num == MRB_INT_MAX / 10 && d > MRB_INT_MAX - num * 10)) {
+ return json_parse_number2(parser, ch, result, num, sign);
+ }
+ num = num * 10 + d;
+ } else if (ch == '.' || ch == 'e' || ch == 'E') {
+ return json_parse_number2(parser, ch, result, num, sign);
+ } else if (json_delimiter_p(ch)) {
+ json_ungetc(parser);
+ break;
+ } else {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid number");
+ }
+ }
+ *result = mrb_fixnum_value(num);
+ return 1;
+}
+
+static int
+json_parse_number2(struct json_parser *parser, int ch, mrb_value *result, mrb_int num, int sign)
+{
+ mrb_state *mrb = parser->mrb;
+ double d;
+ int i, state;
+ char buf[64];
+
+ /*
+ * "-"? ("0" | [1-9] digit* ) ("." digit+ )? ([eE][-+] digit+)?
+ * state: 000000 111 222222 33334444 555555
+ */
+ i = snprintf(buf, sizeof(buf), "%s%"MRB_PRId"%c",
+ (num == 0 && sign < 0) ? "-" : "",
+ num, ch);
+
+ if (isdigit(ch))
+ state = 0;
+ else if (ch == '.')
+ state = 1;
+ else /* (ch == 'e' || ch == 'E') */
+ state = 3;
+
+ while (1) {
+ ch = json_getc(parser);
+ if (ch == JSON_EOF)
+ break;
+ switch (state) {
+ case 0:
+ if (isdigit(ch))
+ ; /* read more digits */
+ else if (ch == '.')
+ state = 1;
+ else if (ch == 'e' || ch == 'E')
+ state = 3;
+ else if (json_delimiter_p(ch)) {
+ json_ungetc(parser);
+ state = -1;
+ } else
+ goto formaterr;
+ break;
+ case 1:
+ if (!isdigit(ch))
+ goto formaterr;
+ state = 2;
+ break;
+ case 2:
+ if (isdigit(ch))
+ ; /* read more digits */
+ else if (ch == 'e' || ch == 'E')
+ state = 3;
+ else if (json_delimiter_p(ch)) {
+ json_ungetc(parser);
+ state = -1;
+ } else
+ goto formaterr;
+ break;
+ case 3:
+ if (ch == '-' || ch == '+')
+ state = 4;
+ else if (isdigit(ch))
+ state = 5;
+ else
+ goto formaterr;
+ break;
+ case 4:
+ if (!isdigit(ch))
+ goto formaterr;
+ state = 5;
+ break;
+ case 5:
+ default:
+ if (isdigit(ch))
+ ; /* read more digits */
+ else {
+ json_ungetc(parser);
+ state = -1;
+ }
+ break;
+ }
+ if (state == -1)
+ break;
+ if (i == sizeof(buf) - 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "floating point number too long");
+ }
+ buf[i++] = ch;
+ }
+ buf[i] = '\0';
+ sscanf(buf, "%lf", &d);
+ *result = mrb_float_value(mrb, d);
+ return 1;
+
+formaterr:
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "floating point number error");
+ return -1;
+}
+
+static int
+json_parse_string(struct json_parser *parser, mrb_value *result)
+{
+ mrb_state *mrb = parser->mrb;
+ mrb_value str;
+ uint32_t unicode;
+ uint16_t utf16;
+ int ch, i, n;
+ char *cp;
+
+ str = mrb_str_buf_new(mrb, 30);
+ cp = RSTRING_PTR(str);
+ n = 0;
+ unicode = 0;
+
+ while (1) {
+ ch = json_getc(parser);
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF in string");
+ }
+
+ if (ch == '"') {
+ break;
+ } else if (ch == '\\') {
+ ch = json_getc(parser);
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "EOF following escape char");
+ }
+ switch (ch) {
+ case '"':
+ case '\\':
+ case '/':
+ break;
+ case 'b':
+ ch = 0x08;
+ break;
+ case 'f':
+ ch = 0x0c;
+ break;
+ case 'n':
+ ch = 0x0a;
+ break;
+ case 'r':
+ ch = 0x0d;
+ break;
+ case 't':
+ ch = 0x09;
+ break;
+ case 'u':
+ utf16 = 0;
+ for (i = 0; i < 4; i++) {
+ ch = json_getc(parser);
+ if (ch == JSON_EOF) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid unicode escape");
+ }
+ if (ch >= '0' && ch <= '9') {
+ ch -= '0';
+ } else if (ch >= 'A' && ch <= 'F') {
+ ch = (ch - 'A') + 10;
+ } else if (ch >= 'a' && ch <= 'f') {
+ ch = (ch - 'a') + 10;
+ } else {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid unicode character");
+ }
+ utf16 *= 16;
+ utf16 += ch;
+ }
+
+ if (n + 8 >= RSTRING_CAPA(str)) {
+ mrb_str_resize(mrb, str, RSTRING_CAPA(str)*2);
+ cp = RSTRING_PTR(str);
+ }
+
+ if ((utf16 & 0xf800) == 0xd800) {
+ if ((utf16 & 0xfc00) == 0xd800) {
+ /* high surrogate */
+ unicode = utf16;
+ continue;
+ } else {
+ /* low surrogate */
+ if (unicode > 0) {
+ unicode = ((unicode & 0x03ff) + 0x040) << 10;
+ unicode += utf16 & 0x03ff;
+ } else {
+ /* error: low surrogate comes first... */
+ }
+ }
+ } else {
+ if (unicode > 0) {
+ /* error: high surrogate not followed by low surrogate */
+ n += json_unicode2utf8(unicode, &cp[n]);
+ }
+ unicode = utf16;
+ }
+
+ n += json_unicode2utf8(unicode, &cp[n]);
+ unicode = 0;
+ continue;
+ default:
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid escape char");
+ break;
+ }
+ } else if (ch < 0x20) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "invalid char");
+ }
+
+ if (n + 1 == RSTRING_CAPA(str)) {
+ mrb_str_resize(mrb, str, RSTRING_CAPA(str)*2);
+ cp = RSTRING_PTR(str);
+ }
+ cp[n++] = ch;
+ }
+ cp[n] = '\0';
+ mrb_str_resize(mrb, str, n);
+ *result = str;
+ return 1;
+}
+
+static int
+json_parse_value(struct json_parser *parser, mrb_value *result)
+{
+ mrb_state *mrb = parser->mrb;
+ int ch;
+
+ do {
+ ch = json_getc(parser);
+ if (ch == JSON_EOF)
+ return 0;
+ } while (json_whitespace_p(ch));
+
+ switch (ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '-':
+ if (json_parse_number(parser, ch, result) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "number...?");
+ }
+ break;
+
+ case '"':
+ if (json_parse_string(parser, result) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "string...?");
+ }
+ break;
+
+ case '[':
+ if (json_parse_array(parser, result) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "array...?");
+ }
+ break;
+
+ case '{':
+ if (json_parse_object(parser, result) != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "object...?");
+ }
+ break;
+
+ case 'f':
+ if (json_parse_readstring(parser, "alse") != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected f");
+ }
+ *result = mrb_false_value();
+ break;
+
+ case 'n':
+ if (json_parse_readstring(parser, "ull") != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected n");
+ }
+ *result = mrb_nil_value();
+ break;
+
+ case 't':
+ if (json_parse_readstring(parser, "rue") != 1) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected t");
+ }
+ *result = mrb_true_value();
+ break;
+
+ default:
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "unexpected character");
+ }
+
+ return 1;
+}
+
+static mrb_value
+mrb_json_parse(mrb_state *mrb, mrb_value mod)
+{
+ struct json_parser parser;
+ mrb_value obj, options, source;
+
+ mrb_get_args(mrb, "S|H", &source, &options);
+
+ parser.mrb = mrb;
+ parser.src = source;
+ parser.cursor = 0;
+ parser.lineno = 0;
+ parser.nesting = 0;
+ parser.max_nesting = DEFAULT_MAX_NESTING;
+
+ if (json_parse_value(&parser, &obj) == 0) {
+ mrb_raise(mrb, E_JSON_PARSER_ERROR, "no JSON value");
+ }
+
+ // if we have extra characters:
+ // unexpected token at '3' (JSON::ParserError)
+
+ return obj;
+}
+
+void
+mrb_mruby_iijson_gem_init(mrb_state *mrb)
+{
+ struct RClass *m;
+
+ m = mrb_define_module(mrb, "JSON");
+ mrb_define_module_function(mrb, m, "parse", mrb_json_parse, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
+}
+
+void
+mrb_mruby_iijson_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/test/json.rb b/web/server/h2o/libh2o/deps/mruby-iijson/test/json.rb
new file mode 100644
index 00000000..5b1e759c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/test/json.rb
@@ -0,0 +1,145 @@
+assert('JSON.dump') do
+ class JsonTestIo
+ def initialize
+ @buf = ""
+ end
+ def write(str)
+ @buf += str
+ end
+ attr_reader :buf
+ end
+ assert_equal "[1]", JSON.dump([1])
+
+ jio = JsonTestIo.new
+ JSON.dump(["abc"], jio)
+ assert_equal '["abc"]', jio.buf
+
+ assert_raise(ArgumentError) do
+ JSON.dump({:a => {:b => {} } }, nil, 2)
+ end
+ JSON.dump({:a=>{:b=>{}}}, nil, 3) # should not raise
+end
+
+assert('JSON.generate: false') do
+ assert_equal "false", JSON.generate(false)
+end
+
+assert('JSON.generate: null') do
+ assert_equal "null", JSON.generate(nil)
+end
+
+assert('JSON.generate: true') do
+ assert_equal "true", JSON.generate(true)
+end
+
+assert('JSON.generate: object') do
+ assert_equal '{"key":"value"}', JSON.generate({ "key" => "value" })
+ assert_equal '{"ten":10}', JSON.generate({ :ten => 10 })
+end
+
+assert('JSON.generate: array') do
+ assert_equal '[null,1,"two"]', JSON.generate([ nil, 1, "two"])
+end
+
+assert('JSON.generate: number (Fixnum)') do
+ str = JSON.generate [1]
+ assert_equal "[1]", str
+end
+
+assert('JSON.generate: number (Float)') do
+ str = JSON.generate [134.625]
+ assert_equal "[134.625]", str
+end
+
+assert('JSON.generate: string') do
+ assert_equal "\"abc\"", JSON.generate("abc")
+ assert_equal "\"\\\"\\\\/\\b\\f\\n\\r\\t\"",
+ JSON.generate("\x22\x5c\x2f\x08\x0c\x0a\x0d\x09")
+end
+
+assert('JSON.load') do
+ assert_equal [1,2,3], JSON.load("[1,2,3]")
+
+ class JsonTestReader
+ def read
+ '{"abc":123}'
+ end
+ end
+ assert_equal({"abc"=>123}, JSON.load(JsonTestReader.new))
+end
+
+assert('JSON.parse: text from RFC4726') do
+ str = '{
+ "Image": {
+ "Width": 800,
+ "Height": 600,
+ "Title": "View from 15th Floor",
+ "Thumbnail": {
+ "Url": "http://www.example.com/image/481989943",
+ "Height": 125,
+ "Width": "100"
+ },
+ "IDs": [116, 943, 234, 38793]
+ }
+ }'
+ hash = {
+ "Image" => {
+ "Width" => 800,
+ "Height" => 600,
+ "Title" => "View from 15th Floor",
+ "Thumbnail" => {
+ "Url" => "http://www.example.com/image/481989943",
+ "Height" => 125,
+ "Width" => "100"
+ },
+ "IDs" => [116, 943, 234, 38793]
+ }
+ }
+ assert_equal hash, JSON.parse(str)
+
+ # We cannot compare `str` with `JSON.generate(hash)` because Hash entries
+ # will be in a random order.
+ assert_equal hash, JSON.parse(JSON.generate(hash))
+end
+
+assert('JSON::ParserError') do
+ assert_raise(JSON::ParserError) do
+ JSON.parse "[xxx]"
+ end
+end
+
+assert('JSON.parse: empty string is not a valid JSON text') do
+ assert_raise(JSON::ParserError) do
+ JSON.parse ""
+ end
+end
+
+assert('JSON.parse: parsing numbers around MRB_INT_MIN/MRB_INT_MAX') do
+ int_min = TestJSON::MRB_INT_MIN
+ int_max = TestJSON::MRB_INT_MAX
+
+ assert_kind_of Fixnum, JSON.load(int_min.to_s)
+ assert_equal int_min, JSON.load(int_min.to_s)
+
+ assert_kind_of Fixnum, JSON.load(int_max.to_s)
+ assert_equal int_max, JSON.load(int_max.to_s)
+
+ assert_kind_of Float, JSON.load((int_min-1).to_s)
+ assert_float (int_min-1)/int_min, JSON.load((int_min-1).to_s)/int_min
+
+ assert_kind_of Float, JSON.load((int_max+1).to_s)
+ assert_float (int_max+1)/int_max, JSON.load((int_max+1).to_s)/int_max
+end
+
+assert('#to_json') do
+ assert_equal 'false', false.to_json
+ assert_equal 'null', nil.to_json
+ assert_equal 'true', true.to_json
+ assert_equal '1', 1.to_json
+ assert_equal '3.125', 3.125.to_json
+ assert_equal '"str"', "str".to_json
+ assert_equal '["one",2]', [ "one", 2 ].to_json
+ assert_equal '{"a":1}', { "a" => 1 }.to_json
+ assert_equal TestJSON::MRB_INT_MIN.to_s, TestJSON::MRB_INT_MIN.to_json
+ assert_equal TestJSON::MRB_INT_MAX.to_s, TestJSON::MRB_INT_MAX.to_json
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-iijson/test/testjson.c b/web/server/h2o/libh2o/deps/mruby-iijson/test/testjson.c
new file mode 100644
index 00000000..f254e8bb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-iijson/test/testjson.c
@@ -0,0 +1,11 @@
+#include "mruby.h"
+#include "mruby/value.h"
+#include "mruby/variable.h"
+
+void
+mrb_mruby_iijson_gem_test(mrb_state* mrb)
+{
+ struct RClass *c = mrb_define_module(mrb, "TestJSON");
+ mrb_const_set(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, "MRB_INT_MIN"), mrb_fixnum_value(MRB_INT_MIN));
+ mrb_const_set(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, "MRB_INT_MAX"), mrb_fixnum_value(MRB_INT_MAX));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/.travis.yml b/web/server/h2o/libh2o/deps/mruby-input-stream/.travis.yml
new file mode 100644
index 00000000..fc81cada
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/.travis.yml
@@ -0,0 +1,6 @@
+sudo: false
+script:
+ - export MRUBY_CONFIG="$TRAVIS_BUILD_DIR/build_config_sample.rb"
+ - git clone --depth 1 "https://github.com/mruby/mruby.git"
+ - cd mruby
+ - ./minirake test
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/LICENSE b/web/server/h2o/libh2o/deps/mruby-input-stream/LICENSE
new file mode 100644
index 00000000..6e817bb5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Masayoshi Takahashi
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/README.md b/web/server/h2o/libh2o/deps/mruby-input-stream/README.md
new file mode 100644
index 00000000..a9efe87f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/README.md
@@ -0,0 +1,28 @@
+# mruby-input-stream
+
+[![Build Status](https://travis-ci.org/takahashim/mruby-input-stream.svg?branch=master)](https://travis-ci.org/takahashim/mruby-input-stream)
+
+Input Stream class for Rack.
+
+
+## Install
+
+add conf.gem to `build_config.rb`:
+
+ MRuby::Build.new do |conf|
+
+ # ... (snip) ...
+
+ conf.gem :github => 'takahashim/mruby-input-stream'
+ end
+
+## License
+
+MIT
+
+## Author
+
+Masayoshi Takahashi
+
+
+
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/Rakefile b/web/server/h2o/libh2o/deps/mruby-input-stream/Rakefile
new file mode 100644
index 00000000..0c0c78ea
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/Rakefile
@@ -0,0 +1,28 @@
+MRUBY_CONFIG=File.expand_path(ENV["MRUBY_CONFIG"] || "./build_config_sample.rb")
+RAKE="ruby ./minirake"
+
+file :mruby do
+ sh "git clone --depth 1 git://github.com/mruby/mruby.git"
+end
+
+task :default => :test
+
+desc "test this mrbgem"
+task :test => :mruby do
+ sh "cd mruby && MRUBY_CONFIG=#{MRUBY_CONFIG} #{RAKE} test"
+end
+
+desc "build mruby with this mrbgem"
+task :build => :mruby do
+ sh "cd mruby && MRUBY_CONFIG=#{MRUBY_CONFIG} #{RAKE} all"
+end
+
+desc "cleanup"
+task :clean do
+ sh "cd mruby && rake deep_clean" if File.exist?("mruby")
+end
+
+desc "cleanup including temporary files"
+task :realclean do
+ sh "rm -rf mruby"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/build_config_sample.rb b/web/server/h2o/libh2o/deps/mruby-input-stream/build_config_sample.rb
new file mode 100644
index 00000000..9d2321d9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/build_config_sample.rb
@@ -0,0 +1,17 @@
+MRuby::Build.new do |conf|
+ toolchain :gcc
+
+ conf.gembox 'default'
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
+
+MRuby::Build.new('test') do |conf|
+ toolchain :gcc
+
+ enable_debug
+ conf.enable_bintest
+ conf.enable_test
+
+ conf.gembox 'default'
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-input-stream/mrbgem.rake
new file mode 100644
index 00000000..082a128a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-input-stream') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Masayoshi Takahashi'
+ spec.summary = 'InputStream class for Rack'
+ spec.version = '1.0.0'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/mrblib/input_stream.rb b/web/server/h2o/libh2o/deps/mruby-input-stream/mrblib/input_stream.rb
new file mode 100644
index 00000000..d452f7ff
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/mrblib/input_stream.rb
@@ -0,0 +1,16 @@
+class InputStream
+ include Enumerable
+
+ #
+ # from String#each
+ def each(&block)
+ self.rewind
+ while pos = self.byteindex(0x0a)
+ block.call(self.read(pos+1))
+ end
+ rest = self.read()
+ if rest
+ block.call(rest)
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c b/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c
new file mode 100644
index 00000000..a5f90b98
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c
@@ -0,0 +1,278 @@
+#include <string.h>
+#include "mruby.h"
+#include "mruby/value.h"
+#include "mruby/data.h"
+#include "mruby/string.h"
+#include "mruby_input_stream.h"
+
+typedef struct mrb_input_stream_t {
+ const char *base;
+ mrb_int len;
+ mrb_int pos;
+ mrb_input_stream_free_callback free_cb;
+ void *free_cb_data;
+} mrb_input_stream_t;
+
+static mrb_input_stream_t*
+mrb_input_stream_create(mrb_state *mrb, const char *base, mrb_int len, mrb_input_stream_free_callback cb, void *cb_data);
+
+static void
+mrb_mruby_input_stream_free(mrb_state *mrb, void *ptr);
+
+static mrb_int
+seek_char(mrb_input_stream_t *stream, const char chr);
+
+const static struct mrb_data_type mrb_input_stream_type = {
+ "InputStream",
+ mrb_mruby_input_stream_free,
+};
+
+static void
+assert_is_open(mrb_state *mrb, mrb_input_stream_t *stream)
+{
+ if (stream->len < 0) {
+ struct RClass *klass = mrb_class_get(mrb, "IOError");
+ if (klass == NULL)
+ klass = E_RUNTIME_ERROR;
+ mrb_raise(mrb, klass, "stream closed");
+ }
+}
+
+static mrb_value
+mrb_input_stream_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+ mrb_int len;
+ char *ptr;
+ mrb_input_stream_t *stream;
+ mrb_int n = mrb_get_args(mrb, "|S", &str);
+ if (n > 1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(n));
+ }
+
+ if (n == 1) {
+ len = RSTRING_LEN(str);
+ ptr = RSTRING_PTR(str);
+ stream = mrb_input_stream_create(mrb, ptr, len, NULL, NULL);
+ } else {
+ stream = mrb_input_stream_create(mrb, NULL, 0, NULL, NULL);
+ }
+
+ DATA_TYPE(self) = &mrb_input_stream_type;
+ DATA_PTR(self) = stream;
+ return self;
+}
+
+static void
+default_free_cb(mrb_state *mrb, const char *base, mrb_int len, void *cb_data)
+{
+ if (base != NULL)
+ mrb_free(mrb, (void *)base);
+}
+
+static void
+mrb_mruby_input_stream_free(mrb_state *mrb, void *ptr)
+{
+ mrb_input_stream_t *stream = (mrb_input_stream_t *)ptr;
+ if (stream->free_cb != NULL)
+ stream->free_cb(mrb, stream->base, stream->len, stream->free_cb_data);
+ mrb_free(mrb, stream);
+}
+
+static void setup_stream(mrb_state *mrb, mrb_input_stream_t *stream, const char *base, mrb_int len, mrb_int pos, mrb_input_stream_free_callback free_cb, void *free_cb_data)
+{
+ if (free_cb == NULL) {
+ if (len > 0) {
+ char *dst_base = (char *)mrb_malloc(mrb, sizeof(char)*len);
+ memcpy(dst_base, base, len);
+ stream->base = dst_base;
+ stream->len = len;
+ } else {
+ stream->base = NULL;
+ stream->len = len;
+ }
+ stream->free_cb = default_free_cb;
+ stream->free_cb_data = NULL;
+ } else {
+ stream->base = base;
+ stream->len = len;
+ stream->free_cb = free_cb;
+ stream->free_cb_data = free_cb_data;
+ }
+
+ stream->pos = pos;
+}
+
+mrb_input_stream_t*
+mrb_input_stream_create(mrb_state *mrb, const char *base, mrb_int len, mrb_input_stream_free_callback free_cb, void *free_cb_data)
+{
+ mrb_input_stream_t *stream = (mrb_input_stream_t *)mrb_malloc(mrb, sizeof(mrb_input_stream_t));
+
+ setup_stream(mrb, stream, base, len, 0, free_cb, free_cb_data);
+ return stream;
+}
+
+mrb_value
+mrb_input_stream_value(mrb_state *mrb, const char *base, mrb_int len)
+{
+ mrb_input_stream_t *stream = mrb_input_stream_create(mrb, base, len, NULL, NULL);
+ struct RClass *c = mrb_class_get(mrb, "InputStream");
+ struct RData *d = mrb_data_object_alloc(mrb, c, stream, &mrb_input_stream_type);
+
+ return mrb_obj_value(d);
+}
+
+void
+mrb_input_stream_get_data(mrb_state *mrb, mrb_value self, const char **base, mrb_int *len, mrb_int *pos, mrb_input_stream_free_callback *free_cb, void **free_cb_data)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+
+ if (base != NULL)
+ *base = stream->base;
+ if (len != NULL)
+ *len = stream->len;
+ if (pos != NULL)
+ *pos = stream->pos;
+ if (free_cb != NULL)
+ *free_cb = stream->free_cb;
+ if (free_cb_data != NULL)
+ *free_cb_data = stream->free_cb_data;
+}
+
+void
+mrb_input_stream_set_data(mrb_state *mrb, mrb_value self, const char *base, mrb_int len, mrb_int pos, mrb_input_stream_free_callback free_cb, void *free_cb_data)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+
+ if (stream->free_cb != NULL)
+ stream->free_cb(mrb, stream->base, stream->len, stream->free_cb_data);
+ setup_stream(mrb, stream, base, len, pos, free_cb, free_cb_data);
+}
+
+static mrb_value
+mrb_input_stream_gets(mrb_state *mrb, mrb_value self)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ mrb_int pos, len;
+
+ assert_is_open(mrb, stream);
+
+ pos = stream->pos;
+ len = seek_char(stream, '\n');
+ if (len < 0) {
+ return mrb_nil_value();
+ }
+ if (stream->pos + len < stream->len) {
+ len++;
+ }
+ stream->pos += len;
+ return mrb_str_new(mrb, (stream->base + pos), len);
+}
+
+static mrb_int
+seek_char(mrb_input_stream_t *stream, char chr){
+ const char *base = stream->base;
+ size_t len = stream->len;
+ mrb_int pos = stream->pos;
+ const char *end = base + len;
+ const char *start = base + pos;
+ const char *s = start;
+
+ if (pos >= len) {
+ return -1;
+ }
+
+ while (s < end) {
+ if (*s == chr) {
+ break;
+ }
+ s++;
+ }
+ return (s - start);
+}
+
+static mrb_value
+mrb_input_stream_read(mrb_state *mrb, mrb_value self)
+{
+ mrb_int len;
+ mrb_value buf;
+ mrb_int n = mrb_get_args(mrb, "|iS", &len, &buf), pos;
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ const char *start;
+
+ assert_is_open(mrb, stream);
+
+ pos = stream->pos;
+ start = stream->base + pos;
+
+ if (pos >= stream->len) {
+ return mrb_nil_value();
+ }
+ if (n == 0) {
+ stream->pos = stream->len;
+ return mrb_str_new(mrb, start, stream->len - pos);
+ } else {
+ mrb_int newpos = pos + len;
+ if (newpos > stream->len) {
+ newpos = stream->len;
+ }
+ stream->pos = newpos;
+ if (n == 1) {
+ return mrb_str_new(mrb, start, newpos - pos);
+ } else {
+ return mrb_str_cat(mrb, buf, start, newpos - pos);
+ }
+ }
+}
+
+static mrb_value
+mrb_input_stream_rewind(mrb_state *mrb, mrb_value self)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ assert_is_open(mrb, stream);
+ stream->pos = 0;
+ return self;
+}
+
+
+static mrb_value
+mrb_input_stream_byteindex(mrb_state *mrb, mrb_value self)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ mrb_int chr, n, len;
+
+ assert_is_open(mrb, stream);
+
+ n = mrb_get_args(mrb, "i", &chr);
+ if (n != 1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(n));
+ }
+ if (chr < 0 || chr > 255) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "index should be a byte (0 - 255)");
+ }
+
+ len = seek_char(stream, chr);
+ if (len < 0) {
+ return mrb_nil_value();
+ }
+
+ return mrb_fixnum_value(len);
+}
+
+
+void
+mrb_mruby_input_stream_gem_init(mrb_state* mrb)
+{
+ struct RClass * c = mrb_define_class(mrb, "InputStream", mrb->object_class);
+
+ mrb_define_method(mrb, c, "gets", mrb_input_stream_gets, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "read", mrb_input_stream_read, MRB_ARGS_ANY());
+ mrb_define_method(mrb, c, "initialize", mrb_input_stream_init, MRB_ARGS_BLOCK());
+ mrb_define_method(mrb, c, "rewind", mrb_input_stream_rewind, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "byteindex", mrb_input_stream_byteindex, MRB_ARGS_ANY());
+}
+
+void
+mrb_mruby_input_stream_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.h b/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.h
new file mode 100644
index 00000000..39150ad6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.h
@@ -0,0 +1,19 @@
+/*
+ * input_stream.h
+ *
+ */
+#ifndef mruby_input_stream_h
+#define mruby_input_stream_h
+
+typedef void (*mrb_input_stream_free_callback)(mrb_state *mrb, const char *base, mrb_int len, void *cb_data);
+
+mrb_value
+mrb_input_stream_value(mrb_state *mrb, const char *base, mrb_int len);
+
+void
+mrb_input_stream_get_data(mrb_state *mrb, mrb_value self, const char **base, mrb_int *len, mrb_int *pos, mrb_input_stream_free_callback *free_cb, void **free_cb_data);
+
+void
+mrb_input_stream_set_data(mrb_state *mrb, mrb_value self, const char *base, mrb_int len, mrb_int pos, mrb_input_stream_free_callback free_cb, void *free_cb_data);
+
+#endif /* input_stream_h */
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/test/input_stream.rb b/web/server/h2o/libh2o/deps/mruby-input-stream/test/input_stream.rb
new file mode 100644
index 00000000..8201786b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/test/input_stream.rb
@@ -0,0 +1,111 @@
+assert('InputStream.new()') do
+ vec = InputStream.new
+ assert_equal InputStream, vec.class
+end
+
+assert('InputStream.new("foo")') do
+ vec = InputStream.new("foo")
+ assert_equal InputStream, vec.class
+end
+
+assert('InputStream#read') do
+ vec = InputStream.new("foo")
+ assert_equal "foo", vec.read
+end
+
+assert('InputStream#read(2)') do
+ vec = InputStream.new("abcdef")
+ assert_equal "ab", vec.read(2)
+ assert_equal "cde", vec.read(3)
+ assert_equal "f", vec.read(4)
+ assert_equal nil, vec.read(5)
+end
+
+assert('InputStream#read(2, "")') do
+ vec = InputStream.new("abcdef")
+ s1 = ""
+ assert_equal "ab", vec.read(2, s1)
+ assert_equal "ab", s1
+ assert_equal "abcde", vec.read(3, s1)
+ assert_equal "abcde", s1
+ assert_equal "abcdef", vec.read(4, s1)
+ assert_equal "abcdef", s1
+ assert_equal nil, vec.read(5, s1)
+ assert_equal "abcdef", s1
+end
+
+assert('InputStream#read(10)') do
+ vec = InputStream.new("abc")
+ assert_equal "abc", vec.read(10)
+ assert_equal nil, vec.read(10)
+end
+
+assert('InputStream#read ""') do
+ vec = InputStream.new("")
+ assert_equal nil, vec.read(2)
+ assert_equal nil, vec.read(0)
+ assert_equal nil, vec.read(2)
+end
+
+assert('InputStream#read(0)') do
+ vec = InputStream.new("foo")
+ assert_equal "", vec.read(0)
+ assert_equal "", vec.read(0)
+ assert_equal "f", vec.read(1)
+end
+
+
+assert('InputStream#gets') do
+ vec = InputStream.new("foo")
+ assert_equal "foo", vec.gets
+ assert_equal nil, vec.gets
+end
+
+assert('InputStream#gets ""') do
+ vec = InputStream.new("")
+ assert_equal nil, vec.gets
+end
+
+assert('InputStream#gets long') do
+ vec = InputStream.new("foo\nbar\nbuz\n")
+ assert_equal "foo\n", vec.gets
+ assert_equal "bar\n", vec.gets
+ assert_equal "buz\n", vec.gets
+ assert_equal nil, vec.gets
+end
+
+assert('InputStream#gets NN') do
+ vec = InputStream.new("\n\nbuz")
+ assert_equal "\n", vec.gets
+ assert_equal "\n", vec.gets
+ assert_equal "buz", vec.gets
+ assert_equal nil, vec.gets
+end
+
+assert('InputStream#each') do
+ vec = InputStream.new("foo\nbar\nbuz\nzzz")
+ buf = []
+ vec.each do |line|
+ buf << line
+ end
+ assert_equal ["foo\n", "bar\n", "buz\n", "zzz"], buf
+end
+
+assert('InputStream#each ""') do
+ vec = InputStream.new("")
+ buf = []
+ vec.each do |line|
+ buf << line
+ end
+ assert_equal [], buf
+end
+
+assert('InputStream#rewind') do
+ vec = InputStream.new("abcdef")
+ assert_equal "ab", vec.read(2)
+ assert_equal "cde", vec.read(3)
+ vec.rewind
+ assert_equal "abcd", vec.read(4)
+ assert_equal "ef", vec.read(5)
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby-io/.gitignore b/web/server/h2o/libh2o/deps/mruby-io/.gitignore
new file mode 100644
index 00000000..ceeb05b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/.gitignore
@@ -0,0 +1 @@
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-io/.travis.yml b/web/server/h2o/libh2o/deps/mruby-io/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-io/README.md b/web/server/h2o/libh2o/deps/mruby-io/README.md
new file mode 100644
index 00000000..d7fa6945
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/README.md
@@ -0,0 +1,185 @@
+mruby-io
+========
+
+IO, File module for mruby
+
+
+## Implemented methods
+
+### IO
+ - http://doc.ruby-lang.org/ja/1.9.3/class/IO.html
+
+| method | mruby-io | memo |
+| ------------------------- | -------- | ---- |
+| IO.binread | | |
+| IO.binwrite | | |
+| IO.copy_stream | | |
+| IO.new, IO.for_fd, IO.open | o | |
+| IO.foreach | | |
+| IO.pipe | | |
+| IO.popen | o | |
+| IO.read | o | |
+| IO.readlines | | |
+| IO.select | o | |
+| IO.sysopen | o | |
+| IO.try_convert | | |
+| IO.write | | |
+| IO#<< | | |
+| IO#advise | | |
+| IO#autoclose= | | |
+| IO#autoclose? | | |
+| IO#binmode | | |
+| IO#binmode? | | |
+| IO#bytes | | obsolete |
+| IO#chars | | obsolete |
+| IO#clone, IO#dup | | |
+| IO#close | o | |
+| IO#close_on_exec= | o | |
+| IO#close_on_exec? | o | |
+| IO#close_read | | |
+| IO#close_write | | |
+| IO#closed? | o | |
+| IO#codepoints | | obsolete |
+| IO#each_byte | o | |
+| IO#each_char | o | |
+| IO#each_codepoint | | |
+| IO#each_line | o | |
+| IO#eof, IO#eof? | o | |
+| IO#external_encoding | | |
+| IO#fcntl | | |
+| IO#fdatasync | | |
+| IO#fileno, IO#to_i | o | |
+| IO#flush | o | |
+| IO#fsync | | |
+| IO#getbyte | | |
+| IO#getc | o | |
+| IO#gets | o | |
+| IO#internal_encoding | | |
+| IO#ioctl | | |
+| IO#isatty, IO#tty? | | |
+| IO#lineno | | |
+| IO#lineno= | | |
+| IO#lines | | obsolete |
+| IO#pid | o | |
+| IO#pos, IO#tell | o | |
+| IO#pos= | o | |
+| IO#print | o | |
+| IO#printf | o | |
+| IO#putc | | |
+| IO#puts | o | |
+| IO#read | o | |
+| IO#read_nonblock | | |
+| IO#readbyte | | |
+| IO#readchar | o | |
+| IO#readline | o | |
+| IO#readlines | o | |
+| IO#readpartial | | |
+| IO#reopen | | |
+| IO#rewind | | |
+| IO#seek | o | |
+| IO#set_encoding | | |
+| IO#stat | | |
+| IO#sync | o | |
+| IO#sync= | o | |
+| IO#sysread | o | |
+| IO#sysseek | o | |
+| IO#syswrite | o | |
+| IO#to_io | | |
+| IO#ungetbyte | | |
+| IO#ungetc | o | |
+| IO#write | o | |
+| IO#write_nonblock | | |
+
+### File
+ - http://doc.ruby-lang.org/ja/1.9.3/class/File.html
+
+| method | mruby-io | memo |
+| --------------------------- | -------- | ---- |
+| File.absolute_path | | |
+| File.atime | | |
+| File.basename | o | |
+| File.blockdev? | | FileTest |
+| File.chardev? | | FileTest |
+| File.chmod | | |
+| File.chown | | |
+| File.ctime | | |
+| File.delete, File.unlink | o | |
+| File.directory? | o | FileTest |
+| File.dirname | o | |
+| File.executable? | | FileTest |
+| File.executable_real? | | FileTest |
+| File.exist?, exists? | o | FileTest |
+| File.expand_path | o | |
+| File.extname | o | |
+| File.file? | o | FileTest |
+| File.fnmatch, File.fnmatch? | | |
+| File.ftype | | |
+| File.grpowned? | | FileTest |
+| File.identical? | | FileTest |
+| File.join | o | |
+| File.lchmod | | |
+| File.lchown | | |
+| File.link | | |
+| File.lstat | | |
+| File.mtime | | |
+| File.new, File.open | o | |
+| File.owned? | | FileTest |
+| File.path | | |
+| File.pipe? | o | FileTest |
+| File.readable? | | FileTest |
+| File.readable_real? | | FileTest |
+| File.readlink | | |
+| File.realdirpath | | |
+| File.realpath | o | |
+| File.rename | o | |
+| File.setgid? | | FileTest |
+| File.setuid? | | FileTest |
+| File.size | o | |
+| File.size? | o | FileTest |
+| File.socket? | o | FileTest |
+| File.split | | |
+| File.stat | | |
+| File.sticky? | | FileTest |
+| File.symlink | | |
+| File.symlink? | o | FileTest |
+| File.truncate | | |
+| File.umask | o | |
+| File.utime | | |
+| File.world_readable? | | |
+| File.world_writable? | | |
+| File.writable? | | FileTest |
+| File.writable_real? | | FileTest |
+| File.zero? | o | FileTest |
+| File#atime | | |
+| File#chmod | | |
+| File#chown | | |
+| File#ctime | | |
+| File#flock | o | |
+| File#lstat | | |
+| File#mtime | | |
+| File#path, File#to_path | o | |
+| File#size | | |
+| File#truncate | | |
+
+
+## License
+
+Copyright (c) 2013 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/web/server/h2o/libh2o/deps/mruby-io/include/mruby/ext/io.h b/web/server/h2o/libh2o/deps/mruby-io/include/mruby/ext/io.h
new file mode 100644
index 00000000..3107f105
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/include/mruby/ext/io.h
@@ -0,0 +1,36 @@
+/*
+** io.h - IO class
+*/
+
+#ifndef MRUBY_IO_H
+#define MRUBY_IO_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct mrb_io {
+ int fd; /* file descriptor, or -1 */
+ int fd2; /* file descriptor to write if it's different from fd, or -1 */
+ int pid; /* child's pid (for pipes) */
+ unsigned int writable:1,
+ sync:1;
+};
+
+#define FMODE_READABLE 0x00000001
+#define FMODE_WRITABLE 0x00000002
+#define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE)
+#define FMODE_BINMODE 0x00000004
+#define FMODE_APPEND 0x00000040
+#define FMODE_CREATE 0x00000080
+#define FMODE_TRUNC 0x00000800
+
+#define E_IO_ERROR (mrb_class_get(mrb, "IOError"))
+#define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
+
+mrb_value mrb_io_fileno(mrb_state *mrb, mrb_value io);
+
+#if defined(__cplusplus)
+} /* extern "C" { */
+#endif
+#endif /* MRUBY_IO_H */
diff --git a/web/server/h2o/libh2o/deps/mruby-io/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-io/mrbgem.rake
new file mode 100644
index 00000000..8120f783
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/mrbgem.rake
@@ -0,0 +1,16 @@
+MRuby::Gem::Specification.new('mruby-io') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Internet Initiative Japan Inc.'
+
+ spec.cc.include_paths << "#{build.root}/src"
+
+ case RUBY_PLATFORM
+ when /mingw|mswin/
+ spec.linker.libraries += ['Ws2_32']
+ #spec.cc.include_paths += ["C:/Windows/system/include"]
+ spec.linker.library_paths += ["C:/Windows/system"]
+ end
+ if build.kind_of?(MRuby::CrossBuild) && %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target)
+ spec.linker.libraries += ['ws2_32']
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/mrblib/file.rb b/web/server/h2o/libh2o/deps/mruby-io/mrblib/file.rb
new file mode 100644
index 00000000..aa098193
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/mrblib/file.rb
@@ -0,0 +1,173 @@
+class File < IO
+ include Enumerable
+
+ class FileError < Exception; end
+ class NoFileError < FileError; end
+ class UnableToStat < FileError; end
+ class PermissionError < FileError; end
+
+ attr_accessor :path
+
+ def initialize(fd_or_path, mode = "r", perm = 0666)
+ if fd_or_path.kind_of? Fixnum
+ super(fd_or_path, mode)
+ else
+ @path = fd_or_path
+ fd = IO.sysopen(@path, mode, perm)
+ super(fd, mode)
+ end
+ end
+
+ def self.join(*names)
+ if names.size == 0
+ ""
+ elsif names.size == 1
+ names[0]
+ else
+ if names[0][-1] == File::SEPARATOR
+ s = names[0][0..-2]
+ else
+ s = names[0].dup
+ end
+ (1..names.size-2).each { |i|
+ t = names[i]
+ if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR
+ t = t[1..-2]
+ elsif t[0] == File::SEPARATOR
+ t = t[1..-1]
+ elsif t[-1] == File::SEPARATOR
+ t = t[0..-2]
+ end
+ s += File::SEPARATOR + t if t != ""
+ }
+ if names[-1][0] == File::SEPARATOR
+ s += File::SEPARATOR + names[-1][1..-1]
+ else
+ s += File::SEPARATOR + names[-1]
+ end
+ s
+ end
+ end
+
+ def self.expand_path(path, default_dir = '.')
+ def concat_path(path, base_path)
+ if path[0] == "/" || path[1] == ':' # Windows root!
+ expanded_path = path
+ elsif path[0] == "~"
+ if (path[1] == "/" || path[1] == nil)
+ dir = path[1, path.size]
+ home_dir = _gethome
+
+ unless home_dir
+ raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
+ end
+
+ expanded_path = home_dir
+ expanded_path += dir if dir
+ expanded_path += "/"
+ else
+ splitted_path = path.split("/")
+ user = splitted_path[0][1, splitted_path[0].size]
+ dir = "/" + splitted_path[1, splitted_path.size].join("/")
+
+ home_dir = _gethome(user)
+
+ unless home_dir
+ raise ArgumentError, "user #{user} doesn't exist"
+ end
+
+ expanded_path = home_dir
+ expanded_path += dir if dir
+ expanded_path += "/"
+ end
+ else
+ expanded_path = concat_path(base_path, _getwd)
+ expanded_path += "/" + path
+ end
+
+ expanded_path
+ end
+
+ expanded_path = concat_path(path, default_dir)
+ expand_path_array = []
+ while expanded_path.include?('//')
+ expanded_path = expanded_path.gsub('//', '/')
+ end
+
+ if expanded_path == "/"
+ expanded_path
+ else
+ expanded_path.split('/').each do |path_token|
+ if path_token == '..'
+ if expand_path_array.size > 1
+ expand_path_array.pop
+ end
+ elsif path_token == '.'
+ # nothing to do.
+ else
+ expand_path_array << path_token
+ end
+ end
+
+ expand_path = expand_path_array.join("/")
+ expand_path.empty? ? '/' : expand_path
+ end
+ end
+
+ def self.foreach(file)
+ if block_given?
+ self.open(file) do |f|
+ f.each {|l| yield l}
+ end
+ else
+ return self.new(file)
+ end
+ end
+
+ def self.directory?(file)
+ FileTest.directory?(file)
+ end
+
+ def self.exist?(file)
+ FileTest.exist?(file)
+ end
+
+ def self.exists?(file)
+ FileTest.exists?(file)
+ end
+
+ def self.file?(file)
+ FileTest.file?(file)
+ end
+
+ def self.pipe?(file)
+ FileTest.pipe?(file)
+ end
+
+ def self.size(file)
+ FileTest.size(file)
+ end
+
+ def self.size?(file)
+ FileTest.size?(file)
+ end
+
+ def self.socket?(file)
+ FileTest.socket?(file)
+ end
+
+ def self.symlink?(file)
+ FileTest.symlink?(file)
+ end
+
+ def self.zero?(file)
+ FileTest.zero?(file)
+ end
+
+ def self.extname(filename)
+ fname = self.basename(filename)
+ return '' if fname[0] == '.' || fname.index('.').nil?
+ ext = fname.split('.').last
+ ext.empty? ? '' : ".#{ext}"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/mrblib/file_constants.rb b/web/server/h2o/libh2o/deps/mruby-io/mrblib/file_constants.rb
new file mode 100644
index 00000000..a68ee259
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/mrblib/file_constants.rb
@@ -0,0 +1,29 @@
+class File
+ module Constants
+ RDONLY = 0
+ WRONLY = 1
+ RDWR = 2
+ NONBLOCK = 4
+ APPEND = 8
+
+ BINARY = 0
+ SYNC = 128
+ NOFOLLOW = 256
+ CREAT = 512
+ TRUNC = 1024
+ EXCL = 2048
+
+ NOCTTY = 131072
+ DSYNC = 4194304
+
+ FNM_SYSCASE = 0
+ FNM_NOESCAPE = 1
+ FNM_PATHNAME = 2
+ FNM_DOTMATCH = 4
+ FNM_CASEFOLD = 8
+ end
+end
+
+class File
+ include File::Constants
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/mrblib/io.rb b/web/server/h2o/libh2o/deps/mruby-io/mrblib/io.rb
new file mode 100644
index 00000000..c838b96e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/mrblib/io.rb
@@ -0,0 +1,372 @@
+##
+# IO
+
+class IOError < StandardError; end
+class EOFError < IOError; end
+
+class IO
+ SEEK_SET = 0
+ SEEK_CUR = 1
+ SEEK_END = 2
+
+ BUF_SIZE = 4096
+
+ def self.open(*args, &block)
+ io = self.new(*args)
+
+ return io unless block
+
+ begin
+ yield io
+ ensure
+ begin
+ io.close unless io.closed?
+ rescue StandardError
+ end
+ end
+ end
+
+ def self.popen(command, mode = 'r', &block)
+ io = self._popen(command, mode)
+ return io unless block
+
+ begin
+ yield io
+ ensure
+ begin
+ io.close unless io.closed?
+ rescue IOError
+ # nothing
+ end
+ end
+ end
+
+
+ def self.read(path, length=nil, offset=nil, opt=nil)
+ if not opt.nil? # 4 arguments
+ offset ||= 0
+ elsif not offset.nil? # 3 arguments
+ if offset.is_a? Hash
+ opt = offset
+ offset = 0
+ else
+ opt = {}
+ end
+ elsif not length.nil? # 2 arguments
+ if length.is_a? Hash
+ opt = length
+ offset = 0
+ length = nil
+ else
+ offset = 0
+ opt = {}
+ end
+ else # only 1 argument
+ opt = {}
+ offset = 0
+ length = nil
+ end
+
+ str = ""
+ fd = -1
+ io = nil
+ begin
+ if path[0] == "|"
+ io = IO.popen(path[1..-1], (opt[:mode] || "r"))
+ else
+ fd = IO.sysopen(path)
+ io = IO.open(fd, opt[:mode] || "r")
+ end
+ io.seek(offset) if offset > 0
+ str = io.read(length)
+ ensure
+ if io
+ io.close
+ elsif fd != -1
+ IO._sysclose(fd)
+ end
+ end
+ str
+ end
+
+ def flush
+ # mruby-io always writes immediately (no output buffer).
+ raise IOError, "closed stream" if self.closed?
+ self
+ end
+
+ def write(string)
+ str = string.is_a?(String) ? string : string.to_s
+ return str.size unless str.size > 0
+
+ len = syswrite(str)
+ if len != -1
+ @pos += len
+ return len
+ end
+
+ raise IOError
+ end
+
+ def eof?
+ return true if @buf && @buf.size > 0
+
+ ret = false
+ char = ''
+
+ begin
+ char = sysread(1)
+ rescue EOFError => e
+ ret = true
+ ensure
+ _ungets(char)
+ end
+
+ ret
+ end
+ alias_method :eof, :eof?
+
+ def pos
+ raise IOError if closed?
+ @pos
+ end
+ alias_method :tell, :pos
+
+ def pos=(i)
+ seek(i, SEEK_SET)
+ end
+
+ def seek(i, whence = SEEK_SET)
+ raise IOError if closed?
+ @pos = sysseek(i, whence)
+ @buf = ''
+ 0
+ end
+
+ def _read_buf
+ return @buf if @buf && @buf.size > 0
+ @buf = sysread(BUF_SIZE)
+ end
+
+ def _ungets(substr)
+ raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
+ raise IOError if @pos == 0 || @pos.nil?
+ @pos -= substr.size
+ if @buf.empty?
+ @buf = substr
+ else
+ @buf = substr + @buf
+ end
+ nil
+ end
+
+ def ungetc(char)
+ raise IOError if @pos == 0 || @pos.nil?
+ _ungets(char)
+ nil
+ end
+
+ def read(length = nil)
+ unless length.nil?
+ unless length.is_a? Fixnum
+ raise TypeError.new "can't convert #{length.class} into Integer"
+ end
+ if length < 0
+ raise ArgumentError.new "negative length: #{length} given"
+ end
+ if length == 0
+ return "" # easy case
+ end
+ end
+
+ array = []
+ start_pos = @pos
+ while 1
+ begin
+ _read_buf
+ rescue EOFError => e
+ array = nil if array.empty? and (not length.nil?) and length != 0
+ break
+ end
+
+ if length && (@pos - start_pos + @buf.size) >= length
+ len = length - (@pos - start_pos)
+ array.push @buf[0, len]
+ @pos += len
+ @buf = @buf[len, @buf.size - len]
+ break
+ else
+ array.push @buf
+ @pos += @buf.size
+ @buf = ''
+ end
+ end
+
+ array && array.join
+ end
+
+ def readline(arg = $/, limit = nil)
+ case arg
+ when String
+ rs = arg
+ when Fixnum
+ rs = $/
+ limit = arg
+ else
+ raise ArgumentError
+ end
+
+ if rs.nil?
+ return read
+ end
+
+ if rs == ""
+ rs = $/ + $/
+ end
+
+ array = []
+ start_pos = @pos
+ while 1
+ begin
+ _read_buf
+ rescue EOFError => e
+ array = nil if array.empty?
+ break
+ end
+
+ if limit && (@pos - start_pos + @buf.size) >= limit
+ len = limit - (@pos - start_pos)
+ array.push @buf[0, len]
+ @pos += len
+ @buf = @buf[len, @buf.size - len]
+ break
+ elsif idx = @buf.index(rs)
+ len = idx + rs.size
+ array.push @buf[0, len]
+ @pos += len
+ @buf = @buf[len, @buf.size - len]
+ break
+ else
+ array.push @buf
+ @pos += @buf.size
+ @buf = ''
+ end
+ end
+
+ raise EOFError.new "end of file reached" if array.nil?
+
+ array.join
+ end
+
+ def gets(*args)
+ begin
+ readline(*args)
+ rescue EOFError => e
+ nil
+ end
+ end
+
+ def readchar
+ _read_buf
+ c = @buf[0]
+ @buf = @buf[1, @buf.size]
+ @pos += 1
+ c
+ end
+
+ def getc
+ begin
+ readchar
+ rescue EOFError => e
+ nil
+ end
+ end
+
+ # 15.2.20.5.3
+ def each(&block)
+ while line = self.gets
+ block.call(line)
+ end
+ self
+ end
+
+ # 15.2.20.5.4
+ def each_byte(&block)
+ while char = self.getc
+ block.call(char)
+ end
+ self
+ end
+
+ # 15.2.20.5.5
+ alias each_line each
+
+ alias each_char each_byte
+
+ def readlines
+ ary = []
+ while (line = gets)
+ ary << line
+ end
+ ary
+ end
+
+ def puts(*args)
+ i = 0
+ len = args.size
+ while i < len
+ s = args[i].to_s
+ write s
+ write "\n" if (s[-1] != "\n")
+ i += 1
+ end
+ write "\n" if len == 0
+ nil
+ end
+
+ def print(*args)
+ i = 0
+ len = args.size
+ while i < len
+ write args[i].to_s
+ i += 1
+ end
+ end
+
+ def printf(*args)
+ write sprintf(*args)
+ nil
+ end
+
+ alias_method :to_i, :fileno
+end
+
+STDIN = IO.open(0, "r")
+STDOUT = IO.open(1, "w")
+STDERR = IO.open(2, "w")
+
+$stdin = STDIN
+$stdout = STDOUT
+$stderr = STDERR
+
+module Kernel
+ def print(*args)
+ STDOUT.print(*args)
+ end
+
+ def puts(*args)
+ STDOUT.puts(*args)
+ end
+
+ def printf(*args)
+ STDOUT.printf(*args)
+ end
+
+ def gets(*args)
+ STDIN.gets(*args)
+ end
+
+ def getc(*args)
+ STDIN.getc(*args)
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/mrblib/kernel.rb b/web/server/h2o/libh2o/deps/mruby-io/mrblib/kernel.rb
new file mode 100644
index 00000000..484b5016
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/mrblib/kernel.rb
@@ -0,0 +1,15 @@
+module Kernel
+ def self.`(cmd)
+ IO.popen(cmd) { |io| io.read }
+ end
+
+ def open(file, *rest, &block)
+ raise ArgumentError unless file.is_a?(String)
+
+ if file[0] == "|"
+ IO.popen(file[1..-1], *rest, &block)
+ else
+ File.open(file, *rest, &block)
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/run_test.rb b/web/server/h2o/libh2o/deps/mruby-io/run_test.rb
new file mode 100644
index 00000000..444d18fd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/run_test.rb
@@ -0,0 +1,25 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem :git => 'https://github.com/iij/mruby-env.git'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/src/file.c b/web/server/h2o/libh2o/deps/mruby-io/src/file.c
new file mode 100644
index 00000000..feb8558e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/src/file.c
@@ -0,0 +1,325 @@
+/*
+** file.c - File class
+*/
+
+#include "mruby.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
+#include "mruby/string.h"
+#include "mruby/ext/io.h"
+
+#if MRUBY_RELEASE_NO < 10000
+#include "error.h"
+#else
+#include "mruby/error.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <limits.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined(_WIN32) || defined(_WIN64)
+ #define NULL_FILE "NUL"
+ #define UNLINK _unlink
+ #define GETCWD _getcwd
+ #define CHMOD(a, b) 0
+ #define MAXPATHLEN 1024
+ #if !defined(PATH_MAX)
+ #define PATH_MAX _MAX_PATH
+ #endif
+ #define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
+ #include <direct.h>
+#else
+ #define NULL_FILE "/dev/null"
+ #include <unistd.h>
+ #define UNLINK unlink
+ #define GETCWD getcwd
+ #define CHMOD(a, b) chmod(a,b)
+ #include <sys/file.h>
+ #include <libgen.h>
+ #include <sys/param.h>
+ #include <pwd.h>
+#endif
+
+#if defined(_WIN32) || defined(_WIN64)
+ #define PATH_SEPARATOR ";"
+ #define FILE_SEPARATOR "\\"
+#else
+ #define PATH_SEPARATOR ":"
+ #define FILE_SEPARATOR "/"
+#endif
+
+#ifndef LOCK_SH
+#define LOCK_SH 1
+#endif
+#ifndef LOCK_EX
+#define LOCK_EX 2
+#endif
+#ifndef LOCK_NB
+#define LOCK_NB 4
+#endif
+#ifndef LOCK_UN
+#define LOCK_UN 8
+#endif
+
+#define STAT(p, s) stat(p, s)
+
+
+mrb_value
+mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
+{
+#if defined(_WIN32) || defined(_WIN64)
+ /* nothing to do on windows */
+ return mrb_fixnum_value(0);
+
+#else
+ mrb_int mask, omask;
+ if (mrb_get_args(mrb, "|i", &mask) == 0) {
+ omask = umask(0);
+ umask(omask);
+ } else {
+ omask = umask(mask);
+ }
+ return mrb_fixnum_value(omask);
+#endif
+}
+
+static mrb_value
+mrb_file_s_unlink(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value *argv;
+ mrb_value pathv;
+ mrb_int argc, i;
+ const char *path;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ for (i = 0; i < argc; i++) {
+ pathv = mrb_convert_type(mrb, argv[i], MRB_TT_STRING, "String", "to_str");
+ path = mrb_string_value_cstr(mrb, &pathv);
+ if (UNLINK(path) < 0) {
+ mrb_sys_fail(mrb, path);
+ }
+ }
+ return mrb_fixnum_value(argc);
+}
+
+static mrb_value
+mrb_file_s_rename(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value from, to;
+ const char *src, *dst;
+
+ mrb_get_args(mrb, "SS", &from, &to);
+ src = mrb_string_value_cstr(mrb, &from);
+ dst = mrb_string_value_cstr(mrb, &to);
+ if (rename(src, dst) < 0) {
+ if (CHMOD(dst, 0666) == 0 && UNLINK(dst) == 0 && rename(src, dst) == 0) {
+ return mrb_fixnum_value(0);
+ }
+ mrb_sys_fail(mrb, mrb_str_to_cstr(mrb, mrb_format(mrb, "(%S, %S)", from, to)));
+ }
+ return mrb_fixnum_value(0);
+}
+
+static mrb_value
+mrb_file_dirname(mrb_state *mrb, mrb_value klass)
+{
+ #if defined(_WIN32) || defined(_WIN64)
+ char dname[_MAX_DIR], vname[_MAX_DRIVE];
+ char buffer[_MAX_DRIVE + _MAX_DIR];
+ char *path;
+ mrb_value s;
+ mrb_get_args(mrb, "S", &s);
+ path = mrb_str_to_cstr(mrb, s);
+ _splitpath((const char*)path, vname, dname, NULL, NULL);
+ snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname);
+ return mrb_str_new_cstr(mrb, buffer);
+ #else
+ char *dname, *path;
+ mrb_value s;
+ mrb_get_args(mrb, "S", &s);
+ path = mrb_str_to_cstr(mrb, s);
+
+ if ((dname = dirname(path)) == NULL) {
+ mrb_sys_fail(mrb, "dirname");
+ }
+ #endif
+ return mrb_str_new_cstr(mrb, dname);
+}
+
+static mrb_value
+mrb_file_basename(mrb_state *mrb, mrb_value klass)
+{
+ #if defined(_WIN32) || defined(_WIN64)
+ char bname[_MAX_DIR];
+ char extname[_MAX_EXT];
+ char *path;
+ char buffer[_MAX_DIR + _MAX_EXT];
+ mrb_value s;
+ mrb_get_args(mrb, "S", &s);
+ path = mrb_str_to_cstr(mrb, s);
+ _splitpath((const char*)path, NULL, NULL, bname, extname);
+ snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname);
+ return mrb_str_new_cstr(mrb, buffer);
+ #else
+ char *bname, *path;
+ mrb_value s;
+ mrb_get_args(mrb, "S", &s);
+ path = mrb_str_to_cstr(mrb, s);
+ if ((bname = basename(path)) == NULL) {
+ mrb_sys_fail(mrb, "basename");
+ }
+ return mrb_str_new_cstr(mrb, bname);
+ #endif
+}
+
+static mrb_value
+mrb_file_realpath(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value pathname, dir_string, s, result;
+ int argc;
+ char *cpath;
+
+ argc = mrb_get_args(mrb, "S|S", &pathname, &dir_string);
+ if (argc == 2) {
+ s = mrb_str_dup(mrb, dir_string);
+ s = mrb_str_append(mrb, s, mrb_str_new_cstr(mrb, FILE_SEPARATOR));
+ s = mrb_str_append(mrb, s, pathname);
+ pathname = s;
+ }
+ cpath = mrb_str_to_cstr(mrb, pathname);
+ result = mrb_str_buf_new(mrb, PATH_MAX);
+ if (realpath(cpath, RSTRING_PTR(result)) == NULL)
+ mrb_sys_fail(mrb, cpath);
+ mrb_str_resize(mrb, result, strlen(RSTRING_PTR(result)));
+ return result;
+}
+
+mrb_value
+mrb_file__getwd(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value path;
+
+ path = mrb_str_buf_new(mrb, MAXPATHLEN);
+ if (GETCWD(RSTRING_PTR(path), MAXPATHLEN) == NULL) {
+ mrb_sys_fail(mrb, "getcwd(2)");
+ }
+ mrb_str_resize(mrb, path, strlen(RSTRING_PTR(path)));
+ return path;
+}
+
+static int
+mrb_file_is_absolute_path(const char *path)
+{
+ return (path[0] == '/');
+}
+
+static mrb_value
+mrb_file__gethome(mrb_state *mrb, mrb_value klass)
+{
+#ifndef _WIN32
+ mrb_value username;
+ int argc;
+ char *home;
+
+ argc = mrb_get_args(mrb, "|S", &username);
+ if (argc == 0) {
+ home = getenv("HOME");
+ if (home == NULL) {
+ return mrb_nil_value();
+ }
+ if (!mrb_file_is_absolute_path(home)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "non-absolute home");
+ }
+ } else {
+ const char *cuser = mrb_str_to_cstr(mrb, username);
+ struct passwd *pwd = getpwnam(cuser);
+ if (pwd == NULL) {
+ return mrb_nil_value();
+ }
+ home = pwd->pw_dir;
+ if (!mrb_file_is_absolute_path(home)) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "non-absolute home of ~%S", username);
+ }
+ }
+ return mrb_str_new_cstr(mrb, home);
+#else
+
+ return mrb_nil_value();
+#endif
+}
+
+#ifndef _WIN32
+mrb_value
+mrb_file_flock(mrb_state *mrb, mrb_value self)
+{
+#if defined(sun)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "flock is not supported on Illumos/Solaris");
+#else
+ mrb_int operation;
+ int fd;
+
+ mrb_get_args(mrb, "i", &operation);
+ fd = mrb_fixnum(mrb_io_fileno(mrb, self));
+
+ while (flock(fd, operation) == -1) {
+ switch (errno) {
+ case EINTR:
+ /* retry */
+ break;
+ case EAGAIN: /* NetBSD */
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK: /* FreeBSD OpenBSD Linux */
+#endif
+ if (operation & LOCK_NB) {
+ return mrb_false_value();
+ }
+ /* FALLTHRU - should not happen */
+ default:
+ mrb_sys_fail(mrb, "flock failed");
+ break;
+ }
+ }
+#endif
+ return mrb_fixnum_value(0);
+}
+#endif
+
+void
+mrb_init_file(mrb_state *mrb)
+{
+ struct RClass *io, *file, *cnst;
+
+ io = mrb_class_get(mrb, "IO");
+ file = mrb_define_class(mrb, "File", io);
+ MRB_SET_INSTANCE_TT(file, MRB_TT_DATA);
+ mrb_define_class_method(mrb, file, "umask", mrb_file_s_umask, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, file, "delete", mrb_file_s_unlink, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, file, "unlink", mrb_file_s_unlink, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, file, "rename", mrb_file_s_rename, MRB_ARGS_REQ(2));
+
+ mrb_define_class_method(mrb, file, "dirname", mrb_file_dirname, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, file, "basename", mrb_file_basename, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, file, "realpath", mrb_file_realpath, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
+ mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1));
+
+ #ifndef _WIN32
+ mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1));
+ #endif
+
+ cnst = mrb_define_module_under(mrb, file, "Constants");
+ mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH));
+ mrb_define_const(mrb, cnst, "LOCK_EX", mrb_fixnum_value(LOCK_EX));
+ mrb_define_const(mrb, cnst, "LOCK_UN", mrb_fixnum_value(LOCK_UN));
+ mrb_define_const(mrb, cnst, "LOCK_NB", mrb_fixnum_value(LOCK_NB));
+ mrb_define_const(mrb, cnst, "SEPARATOR", mrb_str_new_cstr(mrb, FILE_SEPARATOR));
+ mrb_define_const(mrb, cnst, "PATH_SEPARATOR", mrb_str_new_cstr(mrb, PATH_SEPARATOR));
+ mrb_define_const(mrb, cnst, "NULL", mrb_str_new_cstr(mrb, NULL_FILE));
+
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-io/src/file_test.c b/web/server/h2o/libh2o/deps/mruby-io/src/file_test.c
new file mode 100644
index 00000000..6c380c4a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/src/file_test.c
@@ -0,0 +1,365 @@
+/*
+** file.c - File class
+*/
+
+#include "mruby.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
+#include "mruby/string.h"
+#include "mruby/ext/io.h"
+
+#if MRUBY_RELEASE_NO < 10000
+#include "error.h"
+#else
+#include "mruby/error.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+ #define LSTAT stat
+ #include <winsock.h>
+#else
+ #define LSTAT lstat
+ #include <sys/file.h>
+ #include <sys/param.h>
+ #include <sys/wait.h>
+ #include <libgen.h>
+ #include <pwd.h>
+ #include <unistd.h>
+#endif
+
+#include <fcntl.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern struct mrb_data_type mrb_io_type;
+
+static int
+mrb_stat0(mrb_state *mrb, mrb_value obj, struct stat *st, int do_lstat)
+{
+ mrb_value tmp;
+ mrb_value io_klass, str_klass;
+
+ io_klass = mrb_obj_value(mrb_class_get(mrb, "IO"));
+ str_klass = mrb_obj_value(mrb_class_get(mrb, "String"));
+
+ tmp = mrb_funcall(mrb, obj, "is_a?", 1, io_klass);
+ if (mrb_test(tmp)) {
+ struct mrb_io *fptr;
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, obj, &mrb_io_type);
+
+ if (fptr && fptr->fd >= 0) {
+ return fstat(fptr->fd, st);
+ }
+
+ mrb_raise(mrb, E_IO_ERROR, "closed stream");
+ return -1;
+ }
+
+ tmp = mrb_funcall(mrb, obj, "is_a?", 1, str_klass);
+ if (mrb_test(tmp)) {
+ if (do_lstat) {
+ return LSTAT(mrb_str_to_cstr(mrb, obj), st);
+ } else {
+ return stat(mrb_str_to_cstr(mrb, obj), st);
+ }
+ }
+
+ return -1;
+}
+
+static int
+mrb_stat(mrb_state *mrb, mrb_value obj, struct stat *st)
+{
+ return mrb_stat0(mrb, obj, st, 0);
+}
+
+static int
+mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
+{
+ return mrb_stat0(mrb, obj, st, 1);
+}
+
+/*
+ * Document-method: directory?
+ *
+ * call-seq:
+ * File.directory?(file_name) -> true or false
+ *
+ * Returns <code>true</code> if the named file is a directory,
+ * or a symlink that points at a directory, and <code>false</code>
+ * otherwise.
+ *
+ * File.directory?(".")
+ */
+
+mrb_value
+mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
+{
+#ifndef S_ISDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_false_value();
+ if (S_ISDIR(st.st_mode))
+ return mrb_true_value();
+
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * File.pipe?(file_name) -> true or false
+ *
+ * Returns <code>true</code> if the named file is a pipe.
+ */
+
+mrb_value
+mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
+{
+#ifdef S_IFIFO
+# ifndef S_ISFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# endif
+
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_false_value();
+ if (S_ISFIFO(st.st_mode))
+ return mrb_true_value();
+
+#endif
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * File.symlink?(file_name) -> true or false
+ *
+ * Returns <code>true</code> if the named file is a symbolic link.
+ */
+
+mrb_value
+mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
+{
+#ifndef S_ISLNK
+# ifdef _S_ISLNK
+# define S_ISLNK(m) _S_ISLNK(m)
+# else
+# ifdef _S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
+# else
+# ifdef S_IFLNK
+# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+# endif
+# endif
+# endif
+#endif
+
+#ifdef S_ISLNK
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_lstat(mrb, obj, &st) == -1)
+ return mrb_false_value();
+ if (S_ISLNK(st.st_mode))
+ return mrb_true_value();
+#endif
+
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * File.socket?(file_name) -> true or false
+ *
+ * Returns <code>true</code> if the named file is a socket.
+ */
+
+mrb_value
+mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
+{
+#ifndef S_ISSOCK
+# ifdef _S_ISSOCK
+# define S_ISSOCK(m) _S_ISSOCK(m)
+# else
+# ifdef _S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
+# else
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# endif
+# endif
+# endif
+#endif
+
+#ifdef S_ISSOCK
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_false_value();
+ if (S_ISSOCK(st.st_mode))
+ return mrb_true_value();
+#endif
+
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * File.exist?(file_name) -> true or false
+ * File.exists?(file_name) -> true or false
+ *
+ * Return <code>true</code> if the named file exists.
+ */
+
+mrb_value
+mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
+{
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_false_value();
+
+ return mrb_true_value();
+}
+
+/*
+ * call-seq:
+ * File.file?(file_name) -> true or false
+ *
+ * Returns <code>true</code> if the named file exists and is a
+ * regular file.
+ */
+
+mrb_value
+mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
+{
+#ifndef S_ISREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_false_value();
+ if (S_ISREG(st.st_mode))
+ return mrb_true_value();
+
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * File.zero?(file_name) -> true or false
+ *
+ * Returns <code>true</code> if the named file exists and has
+ * a zero size.
+ */
+
+mrb_value
+mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
+{
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_false_value();
+ if (st.st_size == 0)
+ return mrb_true_value();
+
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * File.size(file_name) -> integer
+ *
+ * Returns the size of <code>file_name</code>.
+ *
+ * _file_name_ can be an IO object.
+ */
+
+mrb_value
+mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
+{
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ mrb_sys_fail(mrb, "mrb_stat");
+
+ return mrb_fixnum_value(st.st_size);
+}
+
+/*
+ * call-seq:
+ * File.size?(file_name) -> Integer or nil
+ *
+ * Returns +nil+ if +file_name+ doesn't exist or has zero size, the size of the
+ * file otherwise.
+ */
+
+mrb_value
+mrb_filetest_s_size_p(mrb_state *mrb, mrb_value klass)
+{
+ struct stat st;
+ mrb_value obj;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_stat(mrb, obj, &st) < 0)
+ return mrb_nil_value();
+ if (st.st_size == 0)
+ return mrb_nil_value();
+
+ return mrb_fixnum_value(st.st_size);
+}
+
+void
+mrb_init_file_test(mrb_state *mrb)
+{
+ struct RClass *f;
+
+ f = mrb_define_class(mrb, "FileTest", mrb->object_class);
+
+ mrb_define_class_method(mrb, f, "directory?", mrb_filetest_s_directory_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "exist?", mrb_filetest_s_exist_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "exists?", mrb_filetest_s_exist_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "file?", mrb_filetest_s_file_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "pipe?", mrb_filetest_s_pipe_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "size", mrb_filetest_s_size, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "size?", mrb_filetest_s_size_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "socket?", mrb_filetest_s_socket_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "symlink?", mrb_filetest_s_symlink_p, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, f, "zero?", mrb_filetest_s_zero_p, MRB_ARGS_REQ(1));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-io/src/io.c b/web/server/h2o/libh2o/deps/mruby-io/src/io.c
new file mode 100644
index 00000000..1d2f98f3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/src/io.c
@@ -0,0 +1,941 @@
+/*
+** io.c - IO class
+*/
+
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
+#include "mruby/data.h"
+#include "mruby/hash.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+#include "mruby/ext/io.h"
+
+#if MRUBY_RELEASE_NO < 10000
+#include "error.h"
+#else
+#include "mruby/error.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(_WIN32) || defined(_WIN64)
+ #include <winsock.h>
+ #include <io.h>
+ #define open _open
+ #define close _close
+ #define read _read
+ #define write _write
+ #define lseek _lseek
+#else
+ #include <sys/wait.h>
+ #include <unistd.h>
+#endif
+
+#include <fcntl.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static int mrb_io_modestr_to_flags(mrb_state *mrb, const char *modestr);
+static int mrb_io_flags_to_modenum(mrb_state *mrb, int flags);
+static void fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int noraise);
+
+#if MRUBY_RELEASE_NO < 10000
+static struct RClass *
+mrb_module_get(mrb_state *mrb, const char *name)
+{
+ return mrb_class_get(mrb, name);
+}
+#endif
+
+static int
+mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
+{
+ int flags = 0;
+ const char *m = mode;
+
+ switch (*m++) {
+ case 'r':
+ flags |= FMODE_READABLE;
+ break;
+ case 'w':
+ flags |= FMODE_WRITABLE | FMODE_CREATE | FMODE_TRUNC;
+ break;
+ case 'a':
+ flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
+ break;
+ default:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %S", mrb_str_new_cstr(mrb, mode));
+ }
+
+ while (*m) {
+ switch (*m++) {
+ case 'b':
+ flags |= FMODE_BINMODE;
+ break;
+ case '+':
+ flags |= FMODE_READWRITE;
+ break;
+ case ':':
+ /* XXX: PASSTHROUGH*/
+ default:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %S", mrb_str_new_cstr(mrb, mode));
+ }
+ }
+
+ return flags;
+}
+
+static int
+mrb_io_flags_to_modenum(mrb_state *mrb, int flags)
+{
+ int modenum = 0;
+
+ switch(flags & (FMODE_READABLE|FMODE_WRITABLE|FMODE_READWRITE)) {
+ case FMODE_READABLE:
+ modenum = O_RDONLY;
+ break;
+ case FMODE_WRITABLE:
+ modenum = O_WRONLY;
+ break;
+ case FMODE_READWRITE:
+ modenum = O_RDWR;
+ break;
+ }
+
+ if (flags & FMODE_APPEND) {
+ modenum |= O_APPEND;
+ }
+ if (flags & FMODE_TRUNC) {
+ modenum |= O_TRUNC;
+ }
+ if (flags & FMODE_CREATE) {
+ modenum |= O_CREAT;
+ }
+#ifdef O_BINARY
+ if (flags & FMODE_BINMODE) {
+ modenum |= O_BINARY;
+ }
+#endif
+
+ return modenum;
+}
+
+void
+mrb_fd_cloexec(mrb_state *mrb, int fd)
+{
+ int flags, flags2;
+
+#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1) {
+ mrb_sys_fail(mrb, "fcntl");
+ }
+ if (fd <= 2) {
+ flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
+ }
+ else {
+ flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
+ }
+ if (flags != flags2) {
+ if (fcntl(fd, F_SETFD, flags2) == -1) {
+ mrb_sys_fail(mrb, "fcntl");
+ }
+ }
+#endif
+}
+
+#ifndef _WIN32
+static int
+mrb_proc_exec(const char *pname)
+{
+ const char *s;
+ s = pname;
+
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+
+ if (!*s) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ execl("/bin/sh", "sh", "-c", pname, (char *)NULL);
+ return -1;
+}
+#endif
+
+static void
+mrb_io_free(mrb_state *mrb, void *ptr)
+{
+ struct mrb_io *io = (struct mrb_io *)ptr;
+ if (io != NULL) {
+ fptr_finalize(mrb, io, TRUE);
+ mrb_free(mrb, io);
+ }
+}
+
+struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
+
+static struct mrb_io *
+mrb_io_alloc(mrb_state *mrb)
+{
+ struct mrb_io *fptr;
+
+ fptr = (struct mrb_io *)mrb_malloc(mrb, sizeof(struct mrb_io));
+ fptr->fd = -1;
+ fptr->fd2 = -1;
+ fptr->pid = 0;
+ fptr->writable = 0;
+ fptr->sync = 0;
+ return fptr;
+}
+
+#ifndef NOFILE
+#define NOFILE 64
+#endif
+
+#ifndef _WIN32
+mrb_value
+mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value cmd, io, result;
+ mrb_value mode = mrb_str_new_cstr(mrb, "r");
+ mrb_value opt = mrb_hash_new(mrb);
+
+ struct mrb_io *fptr;
+ const char *pname;
+ int pid, flags, fd, write_fd = -1;
+ int pr[2] = { -1, -1 };
+ int pw[2] = { -1, -1 };
+ int doexec;
+ int saved_errno;
+
+ mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
+ io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
+
+ pname = mrb_string_value_cstr(mrb, &cmd);
+ flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
+
+ doexec = (strcmp("-", pname) != 0);
+
+ if (flags & FMODE_READABLE) {
+ if (pipe(pr) == -1) {
+ mrb_sys_fail(mrb, "pipe");
+ }
+ mrb_fd_cloexec(mrb, pr[0]);
+ mrb_fd_cloexec(mrb, pr[1]);
+ }
+
+ if (flags & FMODE_WRITABLE) {
+ if (pipe(pw) == -1) {
+ if (pr[0] != -1) close(pr[0]);
+ if (pr[1] != -1) close(pr[1]);
+ mrb_sys_fail(mrb, "pipe");
+ }
+ mrb_fd_cloexec(mrb, pw[0]);
+ mrb_fd_cloexec(mrb, pw[1]);
+ }
+
+ if (!doexec) {
+ // XXX
+ fflush(stdin);
+ fflush(stdout);
+ fflush(stderr);
+ }
+
+ result = mrb_nil_value();
+ switch (pid = fork()) {
+ case 0: /* child */
+ if (flags & FMODE_READABLE) {
+ close(pr[0]);
+ if (pr[1] != 1) {
+ dup2(pr[1], 1);
+ close(pr[1]);
+ }
+ }
+ if (flags & FMODE_WRITABLE) {
+ close(pw[1]);
+ if (pw[0] != 0) {
+ dup2(pw[0], 0);
+ close(pw[0]);
+ }
+ }
+ if (doexec) {
+ for (fd = 3; fd < NOFILE; fd++) {
+ close(fd);
+ }
+ mrb_proc_exec(pname);
+ mrb_raisef(mrb, E_IO_ERROR, "command not found: %S", cmd);
+ _exit(127);
+ }
+ result = mrb_nil_value();
+ break;
+
+ default: /* parent */
+ if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) {
+ close(pr[1]);
+ fd = pr[0];
+ close(pw[0]);
+ write_fd = pw[1];
+ } else if (flags & FMODE_READABLE) {
+ close(pr[1]);
+ fd = pr[0];
+ } else {
+ close(pw[0]);
+ fd = pw[1];
+ }
+
+ mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, ""));
+ mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@pos"), mrb_fixnum_value(0));
+
+ fptr = mrb_io_alloc(mrb);
+ fptr->fd = fd;
+ fptr->fd2 = write_fd;
+ fptr->pid = pid;
+ fptr->writable = ((flags & FMODE_WRITABLE) != 0);
+ fptr->sync = 0;
+
+ DATA_TYPE(io) = &mrb_io_type;
+ DATA_PTR(io) = fptr;
+ result = io;
+ break;
+
+ case -1: /* error */
+ saved_errno = errno;
+ if (flags & FMODE_READABLE) {
+ close(pr[0]);
+ close(pr[1]);
+ }
+ if (flags & FMODE_WRITABLE) {
+ close(pw[0]);
+ close(pw[1]);
+ }
+ errno = saved_errno;
+ mrb_sys_fail(mrb, "pipe_open failed.");
+ break;
+ }
+ return result;
+}
+#endif
+
+mrb_value
+mrb_io_initialize(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ mrb_int fd;
+ mrb_value mode, opt;
+ int flags;
+
+ mode = opt = mrb_nil_value();
+
+ mrb_get_args(mrb, "i|So", &fd, &mode, &opt);
+ if (mrb_nil_p(mode)) {
+ mode = mrb_str_new_cstr(mrb, "r");
+ }
+ if (mrb_nil_p(opt)) {
+ opt = mrb_hash_new(mrb);
+ }
+
+ flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
+
+ mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, ""));
+ mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@pos"), mrb_fixnum_value(0));
+
+ fptr = DATA_PTR(io);
+ if (fptr != NULL) {
+ fptr_finalize(mrb, fptr, 0);
+ mrb_free(mrb, fptr);
+ }
+ fptr = mrb_io_alloc(mrb);
+
+ DATA_TYPE(io) = &mrb_io_type;
+ DATA_PTR(io) = fptr;
+
+ fptr->fd = fd;
+ fptr->writable = ((flags & FMODE_WRITABLE) != 0);
+ fptr->sync = 0;
+ return io;
+}
+
+static void
+fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int noraise)
+{
+ int n = 0;
+
+ if (fptr == NULL) {
+ return;
+ }
+
+ if (fptr->fd > 2) {
+ n = close(fptr->fd);
+ if (n == 0) {
+ fptr->fd = -1;
+ }
+ }
+ if (fptr->fd2 > 2) {
+ n = close(fptr->fd2);
+ if (n == 0) {
+ fptr->fd2 = -1;
+ }
+ }
+
+#if !defined(_WIN32) && !defined(_WIN64)
+ if (fptr->pid != 0) {
+ pid_t pid;
+ do {
+ pid = waitpid(fptr->pid, NULL, 0);
+ } while (pid == -1 && errno == EINTR);
+ }
+#endif
+
+ if (!noraise && n != 0) {
+ mrb_sys_fail(mrb, "fptr_finalize failed.");
+ }
+}
+
+mrb_value
+mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
+{
+ struct RClass *c = mrb_class_ptr(klass);
+ enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
+ mrb_value obj;
+
+ /* copied from mrb_instance_alloc() */
+ if (ttype == 0) ttype = MRB_TT_OBJECT;
+ obj = mrb_obj_value((struct RObject*)mrb_obj_alloc(mrb, ttype, c));
+ return mrb_io_initialize(mrb, obj);
+}
+
+mrb_value
+mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
+{
+ mrb_int fd;
+ mrb_get_args(mrb, "i", &fd);
+ if (close(fd) == -1) {
+ mrb_sys_fail(mrb, "close");
+ }
+ return mrb_fixnum_value(0);
+}
+
+int
+mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
+{
+ int fd, retry = FALSE;
+
+#ifdef O_CLOEXEC
+ /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
+ flags |= O_CLOEXEC;
+#elif defined O_NOINHERIT
+ flags |= O_NOINHERIT;
+#endif
+reopen:
+ fd = open(pathname, flags, mode);
+ if (fd == -1) {
+ if (!retry) {
+ switch (errno) {
+ case ENFILE:
+ case EMFILE:
+ mrb_garbage_collect(mrb);
+ retry = TRUE;
+ goto reopen;
+ }
+ }
+ mrb_sys_fail(mrb, "open");
+ }
+
+ if (fd <= 2) {
+ mrb_fd_cloexec(mrb, fd);
+ }
+ return fd;
+}
+
+mrb_value
+mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value path = mrb_nil_value();
+ mrb_value mode = mrb_nil_value();
+ mrb_int fd, flags, perm = -1;
+ const char *pat;
+ int modenum;
+
+ mrb_get_args(mrb, "S|Si", &path, &mode, &perm);
+ if (mrb_nil_p(mode)) {
+ mode = mrb_str_new_cstr(mrb, "r");
+ }
+ if (perm < 0) {
+ perm = 0666;
+ }
+
+ pat = mrb_string_value_cstr(mrb, &path);
+ flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
+ modenum = mrb_io_flags_to_modenum(mrb, flags);
+ fd = mrb_cloexec_open(mrb, pat, modenum, perm);
+ return mrb_fixnum_value(fd);
+}
+
+mrb_value
+mrb_io_sysread(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ mrb_value buf = mrb_nil_value();
+ mrb_int maxlen;
+ int ret;
+
+ mrb_get_args(mrb, "i|S", &maxlen, &buf);
+ if (maxlen < 0) {
+ return mrb_nil_value();
+ }
+
+ if (mrb_nil_p(buf)) {
+ buf = mrb_str_new(mrb, NULL, maxlen);
+ }
+ if (RSTRING_LEN(buf) != maxlen) {
+ buf = mrb_str_resize(mrb, buf, maxlen);
+ }
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ ret = read(fptr->fd, RSTRING_PTR(buf), maxlen);
+ switch (ret) {
+ case 0: /* EOF */
+ if (maxlen == 0) {
+ buf = mrb_str_new_cstr(mrb, "");
+ } else {
+ mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
+ }
+ break;
+ case -1: /* Error */
+ mrb_sys_fail(mrb, "sysread failed");
+ break;
+ default:
+ if (RSTRING_LEN(buf) != ret) {
+ buf = mrb_str_resize(mrb, buf, ret);
+ }
+ break;
+ }
+
+ return buf;
+}
+
+mrb_value
+mrb_io_sysseek(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ int pos;
+ mrb_int offset, whence = -1;
+
+ mrb_get_args(mrb, "i|i", &offset, &whence);
+ if (whence < 0) {
+ whence = 0;
+ }
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ pos = lseek(fptr->fd, offset, whence);
+ if (pos < 0) {
+ mrb_raise(mrb, E_IO_ERROR, "sysseek faield");
+ }
+
+ return mrb_fixnum_value(pos);
+}
+
+mrb_value
+mrb_io_syswrite(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ mrb_value str, buf;
+ int fd, length;
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ if (! fptr->writable) {
+ mrb_raise(mrb, E_IO_ERROR, "not opened for writing");
+ }
+
+ mrb_get_args(mrb, "S", &str);
+ if (mrb_type(str) != MRB_TT_STRING) {
+ buf = mrb_funcall(mrb, str, "to_s", 0);
+ } else {
+ buf = str;
+ }
+
+ if (fptr->fd2 == -1) {
+ fd = fptr->fd;
+ } else {
+ fd = fptr->fd2;
+ }
+ length = write(fd, RSTRING_PTR(buf), RSTRING_LEN(buf));
+
+ return mrb_fixnum_value(length);
+}
+
+mrb_value
+mrb_io_close(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ if (fptr && fptr->fd < 0) {
+ mrb_raise(mrb, E_IO_ERROR, "closed stream.");
+ }
+ fptr_finalize(mrb, fptr, FALSE);
+ return mrb_nil_value();
+}
+
+mrb_value
+mrb_io_closed(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ if (fptr->fd >= 0) {
+ return mrb_false_value();
+ }
+
+ return mrb_true_value();
+}
+
+mrb_value
+mrb_io_pid(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+
+ if (fptr->pid > 0) {
+ return mrb_fixnum_value(fptr->pid);
+ }
+
+ return mrb_nil_value();
+}
+
+static struct timeval
+time2timeval(mrb_state *mrb, mrb_value time)
+{
+ struct timeval t = { 0, 0 };
+
+ switch (mrb_type(time)) {
+ case MRB_TT_FIXNUM:
+ t.tv_sec = mrb_fixnum(time);
+ t.tv_usec = 0;
+ break;
+
+ case MRB_TT_FLOAT:
+ t.tv_sec = mrb_float(time);
+ t.tv_usec = (mrb_float(time) - t.tv_sec) * 1000000.0;
+ break;
+
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+
+ return t;
+}
+
+static int
+mrb_io_read_data_pending(mrb_state *mrb, mrb_value io)
+{
+ mrb_value buf = mrb_iv_get(mrb, io, mrb_intern_cstr(mrb, "@buf"));
+ if (mrb_type(buf) == MRB_TT_STRING && RSTRING_LEN(buf) > 0) {
+ return 1;
+ }
+ return 0;
+}
+
+static mrb_value
+mrb_io_s_select(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value *argv;
+ mrb_int argc;
+ mrb_value read, read_io, write, except, timeout, list;
+ struct timeval *tp, timerec;
+ fd_set pset, rset, wset, eset;
+ fd_set *rp, *wp, *ep;
+ struct mrb_io *fptr;
+ int pending = 0;
+ mrb_value result;
+ int max = 0;
+ int interrupt_flag = 0;
+ int i, n;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ if (argc < 1 || argc > 4) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1..4)", mrb_fixnum_value(argc));
+ }
+
+ timeout = mrb_nil_value();
+ except = mrb_nil_value();
+ write = mrb_nil_value();
+ if (argc > 3)
+ timeout = argv[3];
+ if (argc > 2)
+ except = argv[2];
+ if (argc > 1)
+ write = argv[1];
+ read = argv[0];
+
+ if (mrb_nil_p(timeout)) {
+ tp = NULL;
+ } else {
+ timerec = time2timeval(mrb, timeout);
+ tp = &timerec;
+ }
+
+ FD_ZERO(&pset);
+ if (!mrb_nil_p(read)) {
+ mrb_check_type(mrb, read, MRB_TT_ARRAY);
+ rp = &rset;
+ FD_ZERO(rp);
+ for (i = 0; i < RARRAY_LEN(read); i++) {
+ read_io = RARRAY_PTR(read)[i];
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, read_io, &mrb_io_type);
+ FD_SET(fptr->fd, rp);
+ if (mrb_io_read_data_pending(mrb, read_io)) {
+ pending++;
+ FD_SET(fptr->fd, &pset);
+ }
+ if (max < fptr->fd)
+ max = fptr->fd;
+ }
+ if (pending) {
+ timerec.tv_sec = timerec.tv_usec = 0;
+ tp = &timerec;
+ }
+ } else {
+ rp = NULL;
+ }
+
+ if (!mrb_nil_p(write)) {
+ mrb_check_type(mrb, write, MRB_TT_ARRAY);
+ wp = &wset;
+ FD_ZERO(wp);
+ for (i = 0; i < RARRAY_LEN(write); i++) {
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(write)[i], &mrb_io_type);
+ FD_SET(fptr->fd, wp);
+ if (max < fptr->fd)
+ max = fptr->fd;
+ if (fptr->fd2 >= 0) {
+ FD_SET(fptr->fd2, wp);
+ if (max < fptr->fd2)
+ max = fptr->fd2;
+ }
+ }
+ } else {
+ wp = NULL;
+ }
+
+ if (!mrb_nil_p(except)) {
+ mrb_check_type(mrb, except, MRB_TT_ARRAY);
+ ep = &eset;
+ FD_ZERO(ep);
+ for (i = 0; i < RARRAY_LEN(except); i++) {
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(except)[i], &mrb_io_type);
+ FD_SET(fptr->fd, ep);
+ if (max < fptr->fd)
+ max = fptr->fd;
+ if (fptr->fd2 >= 0) {
+ FD_SET(fptr->fd2, ep);
+ if (max < fptr->fd2)
+ max = fptr->fd2;
+ }
+ }
+ } else {
+ ep = NULL;
+ }
+
+ max++;
+
+retry:
+ n = select(max, rp, wp, ep, tp);
+ if (n < 0) {
+ if (errno != EINTR)
+ mrb_sys_fail(mrb, "select failed");
+ if (tp == NULL)
+ goto retry;
+ interrupt_flag = 1;
+ }
+
+ if (!pending && n == 0)
+ return mrb_nil_value();
+
+ result = mrb_ary_new_capa(mrb, 3);
+ mrb_ary_push(mrb, result, rp? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
+ mrb_ary_push(mrb, result, wp? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
+ mrb_ary_push(mrb, result, ep? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
+
+ if (interrupt_flag == 0) {
+ if (rp) {
+ list = RARRAY_PTR(result)[0];
+ for (i = 0; i < RARRAY_LEN(read); i++) {
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(read)[i], &mrb_io_type);
+ if (FD_ISSET(fptr->fd, rp) ||
+ FD_ISSET(fptr->fd, &pset)) {
+ mrb_ary_push(mrb, list, RARRAY_PTR(read)[i]);
+ }
+ }
+ }
+
+ if (wp) {
+ list = RARRAY_PTR(result)[1];
+ for (i = 0; i < RARRAY_LEN(write); i++) {
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(write)[i], &mrb_io_type);
+ if (FD_ISSET(fptr->fd, wp)) {
+ mrb_ary_push(mrb, list, RARRAY_PTR(write)[i]);
+ } else if (fptr->fd2 >= 0 && FD_ISSET(fptr->fd2, wp)) {
+ mrb_ary_push(mrb, list, RARRAY_PTR(write)[i]);
+ }
+ }
+ }
+
+ if (ep) {
+ list = RARRAY_PTR(result)[2];
+ for (i = 0; i < RARRAY_LEN(except); i++) {
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(except)[i], &mrb_io_type);
+ if (FD_ISSET(fptr->fd, ep)) {
+ mrb_ary_push(mrb, list, RARRAY_PTR(except)[i]);
+ } else if (fptr->fd2 >= 0 && FD_ISSET(fptr->fd2, ep)) {
+ mrb_ary_push(mrb, list, RARRAY_PTR(except)[i]);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+mrb_value
+mrb_io_fileno(mrb_state *mrb, mrb_value io)
+{
+ struct mrb_io *fptr;
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ return mrb_fixnum_value(fptr->fd);
+}
+
+mrb_value
+mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value io)
+{
+#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
+ struct mrb_io *fptr;
+ int ret;
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ if (fptr->fd < 0) {
+ mrb_raise(mrb, E_IO_ERROR, "closed stream");
+ }
+
+ if (fptr->fd2 >= 0) {
+ if ((ret = fcntl(fptr->fd2, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
+ if (!(ret & FD_CLOEXEC)) return mrb_false_value();
+ }
+
+ if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
+ if (!(ret & FD_CLOEXEC)) return mrb_false_value();
+ return mrb_true_value();
+
+#else
+ mrb_raise(mrb, E_NOTIMP_ERROR, "IO#close_on_exec? is not supported on the platform");
+ return mrb_false_value();
+#endif
+}
+
+mrb_value
+mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value io)
+{
+#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
+ struct mrb_io *fptr;
+ int flag, ret;
+ mrb_bool b;
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, io, &mrb_io_type);
+ if (fptr->fd < 0) {
+ mrb_raise(mrb, E_IO_ERROR, "closed stream");
+ }
+
+ mrb_get_args(mrb, "b", &b);
+ flag = b ? FD_CLOEXEC : 0;
+
+ if (fptr->fd2 >= 0) {
+ if ((ret = fcntl(fptr->fd2, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
+ if ((ret & FD_CLOEXEC) != flag) {
+ ret = (ret & ~FD_CLOEXEC) | flag;
+ ret = fcntl(fptr->fd2, F_SETFD, ret);
+
+ if (ret == -1) mrb_sys_fail(mrb, "F_SETFD failed");
+ }
+ }
+
+ if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) mrb_sys_fail(mrb, "F_GETFD failed");
+ if ((ret & FD_CLOEXEC) != flag) {
+ ret = (ret & ~FD_CLOEXEC) | flag;
+ ret = fcntl(fptr->fd, F_SETFD, ret);
+ if (ret == -1) mrb_sys_fail(mrb, "F_SETFD failed");
+ }
+
+ return mrb_bool_value(b);
+#else
+ mrb_raise(mrb, E_NOTIMP_ERROR, "IO#close_on_exec= is not supported on the platform");
+ return mrb_nil_value();
+#endif
+}
+
+mrb_value
+mrb_io_set_sync(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_io *fptr;
+ mrb_bool b;
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, self, &mrb_io_type);
+ if (fptr->fd < 0) {
+ mrb_raise(mrb, E_IO_ERROR, "closed stream.");
+ }
+
+ mrb_get_args(mrb, "b", &b);
+ fptr->sync = b;
+ return mrb_bool_value(b);
+}
+
+mrb_value
+mrb_io_sync(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_io *fptr;
+
+ fptr = (struct mrb_io *)mrb_get_datatype(mrb, self, &mrb_io_type);
+ if (fptr->fd < 0) {
+ mrb_raise(mrb, E_IO_ERROR, "closed stream.");
+ }
+ return mrb_bool_value(fptr->sync);
+}
+
+void
+mrb_init_io(mrb_state *mrb)
+{
+ struct RClass *io;
+
+ io = mrb_define_class(mrb, "IO", mrb->object_class);
+ MRB_SET_INSTANCE_TT(io, MRB_TT_DATA);
+
+ mrb_include_module(mrb, io, mrb_module_get(mrb, "Enumerable")); /* 15.2.20.3 */
+#ifndef _WIN32
+ mrb_define_class_method(mrb, io, "_popen", mrb_io_s_popen, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, io, "_sysclose", mrb_io_s_sysclose, MRB_ARGS_REQ(1));
+#endif
+ mrb_define_class_method(mrb, io, "for_fd", mrb_io_s_for_fd, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, io, "select", mrb_io_s_select, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, io, "sysopen", mrb_io_s_sysopen, MRB_ARGS_ANY());
+
+ mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ANY()); /* 15.2.20.5.21 (x)*/
+ mrb_define_method(mrb, io, "sync", mrb_io_sync, MRB_ARGS_NONE());
+ mrb_define_method(mrb, io, "sync=", mrb_io_set_sync, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, io, "sysread", mrb_io_sysread, MRB_ARGS_ANY());
+ mrb_define_method(mrb, io, "sysseek", mrb_io_sysseek, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, io, "syswrite", mrb_io_syswrite, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, io, "close", mrb_io_close, MRB_ARGS_NONE()); /* 15.2.20.5.1 */
+ mrb_define_method(mrb, io, "close_on_exec=", mrb_io_set_close_on_exec, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, io, "close_on_exec?", mrb_io_close_on_exec_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, io, "closed?", mrb_io_closed, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
+ mrb_define_method(mrb, io, "pid", mrb_io_pid, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
+ mrb_define_method(mrb, io, "fileno", mrb_io_fileno, MRB_ARGS_NONE());
+
+
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$/"), mrb_str_new_cstr(mrb, "\n"));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-io/src/mruby_io_gem.c b/web/server/h2o/libh2o/deps/mruby-io/src/mruby_io_gem.c
new file mode 100644
index 00000000..6880e667
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/src/mruby_io_gem.c
@@ -0,0 +1,20 @@
+#include "mruby.h"
+
+void mrb_init_io(mrb_state *mrb);
+void mrb_init_file(mrb_state *mrb);
+void mrb_init_file_test(mrb_state *mrb);
+
+#define DONE mrb_gc_arena_restore(mrb, 0)
+
+void
+mrb_mruby_io_gem_init(mrb_state* mrb)
+{
+ mrb_init_io(mrb); DONE;
+ mrb_init_file(mrb); DONE;
+ mrb_init_file_test(mrb); DONE;
+}
+
+void
+mrb_mruby_io_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-io/test/file.rb b/web/server/h2o/libh2o/deps/mruby-io/test/file.rb
new file mode 100644
index 00000000..d6f39ceb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/test/file.rb
@@ -0,0 +1,108 @@
+##
+# IO Test
+
+assert('File', '15.2.21') do
+ File.class == Class
+end
+
+assert('File', '15.2.21.2') do
+ File.superclass == IO
+end
+
+assert('File TEST SETUP') do
+ MRubyIOTestUtil.io_test_setup
+end
+
+assert('File#initialize', '15.2.21.4.1') do
+ io = File.open($mrbtest_io_rfname, "r")
+ assert_nil io.close
+ assert_raise IOError do
+ io.close
+ end
+end
+
+assert('File#path', '15.2.21.4.2') do
+ io = File.open($mrbtest_io_rfname, "r")
+ assert_equal $mrbtest_io_msg, io.read
+ assert_equal $mrbtest_io_rfname, io.path
+ io.close
+ assert_equal $mrbtest_io_rfname, io.path
+ io.closed?
+end
+
+assert('File.basename') do
+ assert_equal '/', File.basename('//')
+ assert_equal 'a', File.basename('/a/')
+ assert_equal 'b', File.basename('/a/b')
+ assert_equal 'b', File.basename('../a/b')
+end
+
+assert('File.dirname') do
+ assert_equal '.', File.dirname('')
+ assert_equal '.', File.dirname('a')
+ assert_equal '/', File.dirname('/a')
+ assert_equal 'a', File.dirname('a/b')
+ assert_equal '/a', File.dirname('/a/b')
+end
+
+assert('File.extname') do
+ assert_equal '.txt', File.extname('foo/foo.txt')
+ assert_equal '.gz', File.extname('foo/foo.tar.gz')
+ assert_equal '', File.extname('foo/bar')
+ assert_equal '', File.extname('foo/.bar')
+ assert_equal '', File.extname('foo.txt/bar')
+ assert_equal '', File.extname('.foo')
+end
+
+assert('IO#flock') do
+ f = File.open $mrbtest_io_rfname
+ assert_equal(f.flock(File::LOCK_SH), 0)
+ assert_equal(f.flock(File::LOCK_UN), 0)
+ assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0)
+ assert_equal(f.flock(File::LOCK_UN), 0)
+ f.close
+ true
+end
+
+assert('File.join') do
+ File.join() == "" and
+ File.join("a") == "a" and
+ File.join("/a") == "/a" and
+ File.join("a/") == "a/" and
+ File.join("a", "b", "c") == "a/b/c" and
+ File.join("/a", "b", "c") == "/a/b/c" and
+ File.join("a", "b", "c/") == "a/b/c/" and
+ File.join("a/", "/b/", "/c") == "a/b/c"
+end
+
+assert('File.realpath') do
+ usrbin = IO.popen("cd bin; /bin/pwd -P") { |f| f.read.chomp }
+ assert_equal usrbin, File.realpath("bin")
+end
+
+assert('File TEST CLEANUP') do
+ assert_nil MRubyIOTestUtil.io_test_cleanup
+end
+
+assert('File.expand_path') do
+ assert_equal "/", File.expand_path("..", "/tmp"), "parent path with base_dir (1)"
+ assert_equal "/tmp", File.expand_path("..", "/tmp/mruby"), "parent path with base_dir (2)"
+
+ assert_equal "/home", File.expand_path("/home"), "absolute"
+ assert_equal "/home", File.expand_path("/home", "."), "absolute with base_dir"
+
+ assert_equal "/hoge", File.expand_path("/tmp/..//hoge")
+ assert_equal "/hoge", File.expand_path("////tmp/..///////hoge")
+
+ assert_equal "/", File.expand_path("../../../..", "/")
+ assert_equal "/", File.expand_path(([".."] * 100).join("/"))
+end
+
+assert('File.expand_path (with ENV)') do
+ skip unless Object.const_defined?(:ENV) && ENV['HOME']
+
+ assert_equal ENV['HOME'], File.expand_path("~/"), "home"
+ assert_equal ENV['HOME'], File.expand_path("~/", "/"), "home with base_dir"
+
+ assert_equal "#{ENV['HOME']}/user", File.expand_path("user", ENV['HOME']), "relative with base_dir"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/test/file_test.rb b/web/server/h2o/libh2o/deps/mruby-io/test/file_test.rb
new file mode 100644
index 00000000..11742f2d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/test/file_test.rb
@@ -0,0 +1,95 @@
+##
+# FileTest
+
+assert('FileTest TEST SETUP') do
+ MRubyIOTestUtil.io_test_setup
+end
+
+assert("FileTest.directory?") do
+ assert_equal true, FileTest.directory?("/tmp")
+ assert_equal false, FileTest.directory?("/bin/sh")
+end
+
+assert("FileTest.exist?") do
+ assert_equal true, FileTest.exist?($mrbtest_io_rfname), "filename - exist"
+ assert_equal false, FileTest.exist?($mrbtest_io_rfname + "-"), "filename - not exist"
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ assert_equal true, FileTest.exist?(io), "io obj - exist"
+ io.close
+ assert_equal true, io.closed?
+ assert_raise IOError do
+ FileTest.exist?(io)
+ end
+end
+
+assert("FileTest.file?") do
+ assert_equal false, FileTest.file?("/tmp")
+ assert_equal true, FileTest.file?("/bin/sh")
+end
+
+assert("FileTest.pipe?") do
+ io = IO.popen("ls")
+ assert_equal true, FileTest.pipe?(io)
+ assert_equal false, FileTest.pipe?("/tmp")
+end
+
+assert('FileTest.size') do
+ assert_equal FileTest.size($mrbtest_io_rfname), $mrbtest_io_msg.size
+ assert_equal FileTest.size($mrbtest_io_wfname), 0
+end
+
+assert("FileTest.size?") do
+ assert_equal $mrbtest_io_msg.size, FileTest.size?($mrbtest_io_rfname)
+ assert_equal nil, FileTest.size?($mrbtest_io_wfname)
+ assert_equal nil, FileTest.size?("not-exist-test-target-file")
+
+ fp1 = File.open($mrbtest_io_rfname)
+ fp2 = File.open($mrbtest_io_wfname)
+ assert_equal $mrbtest_io_msg.size, FileTest.size?(fp1)
+ assert_equal nil, FileTest.size?(fp2)
+ fp1.close
+ fp2.close
+
+ assert_raise IOError do
+ FileTest.size?(fp1)
+ end
+ assert_raise IOError do
+ FileTest.size?(fp2)
+ end
+
+ fp1.closed? && fp2.closed?
+end
+
+assert("FileTest.socket?") do
+ assert_true FileTest.socket?($mrbtest_io_socketname)
+end
+
+assert("FileTest.symlink?") do
+ assert_true FileTest.symlink?($mrbtest_io_symlinkname)
+end
+
+assert("FileTest.zero?") do
+ assert_equal false, FileTest.zero?($mrbtest_io_rfname)
+ assert_equal true, FileTest.zero?($mrbtest_io_wfname)
+ assert_equal false, FileTest.zero?("not-exist-test-target-file")
+
+ fp1 = File.open($mrbtest_io_rfname)
+ fp2 = File.open($mrbtest_io_wfname)
+ assert_equal false, FileTest.zero?(fp1)
+ assert_equal true, FileTest.zero?(fp2)
+ fp1.close
+ fp2.close
+
+ assert_raise IOError do
+ FileTest.zero?(fp1)
+ end
+ assert_raise IOError do
+ FileTest.zero?(fp2)
+ end
+
+ fp1.closed? && fp2.closed?
+end
+
+assert('FileTest TEST CLEANUP') do
+ assert_nil MRubyIOTestUtil.io_test_cleanup
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/test/gc_filedes.sh b/web/server/h2o/libh2o/deps/mruby-io/test/gc_filedes.sh
new file mode 100644
index 00000000..6e5d1bbf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/test/gc_filedes.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+ulimit -n 20
+mruby -e '100.times { File.open "'$0'" }'
diff --git a/web/server/h2o/libh2o/deps/mruby-io/test/io.rb b/web/server/h2o/libh2o/deps/mruby-io/test/io.rb
new file mode 100644
index 00000000..b828fef4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/test/io.rb
@@ -0,0 +1,416 @@
+##
+# IO Test
+
+assert('IO TEST SETUP') do
+ MRubyIOTestUtil.io_test_setup
+end
+
+assert('IO', '15.2.20') do
+ assert_equal(Class, IO.class)
+end
+
+assert('IO', '15.2.20.2') do
+ assert_equal(Object, IO.superclass)
+end
+
+assert('IO', '15.2.20.3') do
+ assert_include(IO.included_modules, Enumerable)
+end
+
+assert('IO.open', '15.2.20.4.1') do
+ fd = IO.sysopen $mrbtest_io_rfname
+ assert_equal Fixnum, fd.class
+ io = IO.open fd
+ assert_equal IO, io.class
+ assert_equal $mrbtest_io_msg, io.read
+ io.close
+
+ fd = IO.sysopen $mrbtest_io_rfname
+ IO.open(fd) do |io|
+ assert_equal $mrbtest_io_msg, io.read
+ end
+
+ true
+end
+
+assert('IO#close', '15.2.20.5.1') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ assert_nil io.close
+end
+
+assert('IO#closed?', '15.2.20.5.2') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ assert_false io.closed?
+ io.close
+ assert_true io.closed?
+end
+
+#assert('IO#each', '15.2.20.5.3') do
+#assert('IO#each_byte', '15.2.20.5.4') do
+#assert('IO#each_line', '15.2.20.5.5') do
+
+assert('IO#eof?', '15.2.20.5.6') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ $mrbtest_io_msg.each_char { |ch|
+ # XXX
+ #assert_false io.eof?
+ io.getc
+ }
+ assert_true io.eof?
+ io.close
+ true
+end
+
+assert('IO#flush', '15.2.20.5.7') do
+ # Note: mruby-io does not have any buffer to be flushed now.
+ io = IO.new(IO.sysopen($mrbtest_io_wfname))
+ assert_equal io, io.flush
+ io.close
+ assert_raise(IOError) do
+ io.flush
+ end
+end
+
+assert('IO#getc', '15.2.20.5.8') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ $mrbtest_io_msg.each_char { |ch|
+ assert_equal ch, io.getc
+ }
+ assert_equal nil, io.getc
+ io.close
+ true
+end
+
+#assert('IO#gets', '15.2.20.5.9') do
+#assert('IO#initialize_copy', '15.2.20.5.10') do
+#assert('IO#print', '15.2.20.5.11') do
+#assert('IO#putc', '15.2.20.5.12') do
+#assert('IO#puts', '15.2.20.5.13') do
+
+assert('IO#read', '15.2.20.5.14') do
+ IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
+ assert_raise(ArgumentError) { io.read(-5) }
+ assert_raise(TypeError) { io.read("str") }
+
+ len = $mrbtest_io_msg.length
+ assert_equal '', io.read(0)
+ assert_equal 'mruby', io.read(5)
+ assert_equal $mrbtest_io_msg[5,len], io.read(len)
+
+ assert_equal "", io.read
+ assert_nil io.read(1)
+ end
+
+ IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
+ assert_equal $mrbtest_io_msg, io.read
+ end
+end
+
+assert('IO#readchar', '15.2.20.5.15') do
+ # almost same as IO#getc
+ IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
+ $mrbtest_io_msg.each_char { |ch|
+ assert_equal ch, io.readchar
+ }
+ assert_raise(EOFError) do
+ io.readchar
+ end
+ end
+end
+
+#assert('IO#readline', '15.2.20.5.16') do
+#assert('IO#readlines', '15.2.20.5.17') do
+
+assert('IO#sync', '15.2.20.5.18') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ s = io.sync
+ assert_true(s == true || s == false)
+ io.close
+ assert_raise(IOError) do
+ io.sync
+ end
+end
+
+assert('IO#sync=', '15.2.20.5.19') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ io.sync = true
+ assert_true io.sync
+ io.sync = false
+ assert_false io.sync
+ io.close
+ assert_raise(IOError) do
+ io.sync = true
+ end
+end
+
+assert('IO#write', '15.2.20.5.20') do
+ io = IO.open(IO.sysopen($mrbtest_io_wfname))
+ assert_equal 0, io.write("")
+ io.close
+ true
+end
+
+assert('IO.for_fd') do
+ fd = IO.sysopen($mrbtest_io_rfname)
+ io = IO.for_fd(fd)
+ assert_equal $mrbtest_io_msg, io.read
+ io.close
+ true
+end
+
+assert('IO.new') do
+ io = IO.new(0)
+ io.close
+ true
+end
+
+assert('IO gc check') do
+ 100.times { IO.new(0) }
+end
+
+assert('IO.sysopen("./nonexistent")') do
+ if Object.const_defined? :Errno
+ eclass = Errno::ENOENT
+ else
+ eclass = RuntimeError
+ end
+ assert_raise eclass do
+ fd = IO.sysopen "./nonexistent"
+ IO._sysclose fd
+ end
+end
+
+assert('IO.sysopen, IO#sysread') do
+ fd = IO.sysopen $mrbtest_io_rfname
+ io = IO.new fd
+ str1 = " "
+ str2 = io.sysread(5, str1)
+ assert_equal $mrbtest_io_msg[0,5], str1
+ assert_equal $mrbtest_io_msg[0,5], str2
+ assert_raise EOFError do
+ io.sysread(10000)
+ io.sysread(10000)
+ end
+ io.close
+ io.closed?
+end
+
+assert('IO.sysopen, IO#syswrite') do
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ str = "abcdefg"
+ len = io.syswrite(str)
+ assert_equal str.size, len
+ io.close
+
+ io = IO.new(IO.sysopen($mrbtest_io_rfname), "r")
+ assert_raise(IOError) { io.syswrite("a") }
+ io.close
+
+ true
+end
+
+assert('IO#_read_buf') do
+ fd = IO.sysopen $mrbtest_io_rfname
+ io = IO.new fd
+ def io._buf
+ @buf
+ end
+ msg_len = $mrbtest_io_msg.size
+ assert_equal '', io._buf
+ assert_equal $mrbtest_io_msg, io._read_buf
+ assert_equal $mrbtest_io_msg, io._buf
+ assert_equal 'mruby', io.read(5)
+ assert_equal 5, io.pos
+ assert_equal msg_len - 5, io._buf.size
+ assert_equal $mrbtest_io_msg[5,100], io.read
+ assert_equal 0, io._buf.size
+ assert_raise EOFError do
+ io._read_buf
+ end
+ assert_equal true, io.eof
+ assert_equal true, io.eof?
+ io.close
+ io.closed?
+end
+
+assert('IO#pos=, IO#seek') do
+ fd = IO.sysopen $mrbtest_io_rfname
+ io = IO.new fd
+ def io._buf
+ @buf
+ end
+ assert_equal 'm', io.getc
+ assert_equal 1, io.pos
+ assert_equal 0, io.seek(0)
+ assert_equal 0, io.pos
+ io.close
+ io.closed?
+end
+
+assert('IO#gets') do
+ fd = IO.sysopen $mrbtest_io_rfname
+ io = IO.new fd
+
+ # gets without arguments
+ assert_equal $mrbtest_io_msg, io.gets, "gets without arguments"
+ assert_equal nil, io.gets, "gets returns nil, when EOF"
+
+ # gets with limit
+ io.pos = 0
+ assert_equal $mrbtest_io_msg[0, 5], io.gets(5), "gets with limit"
+
+ # gets with rs
+ io.pos = 0
+ assert_equal $mrbtest_io_msg[0, 6], io.gets(' '), "gets with rs"
+
+ # gets with rs, limit
+ io.pos = 0
+ assert_equal $mrbtest_io_msg[0, 5], io.gets(' ', 5), "gets with rs, limit"
+ io.close
+ assert_equal true, io.closed?, "close success"
+
+ # reading many-lines file.
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ io.write "0123456789" * 2 + "\na"
+ assert_equal 22, io.pos
+ io.close
+ assert_equal true, io.closed?
+
+ fd = IO.sysopen $mrbtest_io_wfname
+ io = IO.new fd
+ line = io.gets
+
+ # gets first line
+ assert_equal "0123456789" * 2 + "\n", line, "gets first line"
+ assert_equal 21, line.size
+ assert_equal 21, io.pos
+
+ # gets second line
+ assert_equal "a", io.gets, "gets second line"
+
+ # gets third line
+ assert_equal nil, io.gets, "gets third line; returns nil"
+
+ io.close
+ io.closed?
+end
+
+assert('IO#gets - paragraph mode') do
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ io.write "0" * 10 + "\n"
+ io.write "1" * 10 + "\n\n"
+ io.write "2" * 10 + "\n"
+ assert_equal 34, io.pos
+ io.close
+ assert_equal true, io.closed?
+
+ fd = IO.sysopen $mrbtest_io_wfname
+ io = IO.new fd
+ para1 = "#{'0' * 10}\n#{'1' * 10}\n\n"
+ text1 = io.gets("")
+ assert_equal para1, text1
+ para2 = "#{'2' * 10}\n"
+ text2 = io.gets("")
+ assert_equal para2, text2
+ io.close
+ io.closed?
+end
+
+assert('IO.popen') do
+ io = IO.popen("ls")
+ assert_true io.close_on_exec?
+ assert_equal Fixnum, io.pid.class
+ ls = io.read
+ assert_equal ls.class, String
+ assert_include ls, 'AUTHORS'
+ assert_include ls, 'mrblib'
+ io.close
+ io.closed?
+end
+
+assert('IO.read') do
+ # empty file
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ io.close
+ assert_equal "", IO.read($mrbtest_io_wfname)
+ assert_equal nil, IO.read($mrbtest_io_wfname, 1)
+
+ # one byte file
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ io.write "123"
+ io.close
+ assert_equal "123", IO.read($mrbtest_io_wfname)
+ assert_equal "", IO.read($mrbtest_io_wfname, 0)
+ assert_equal "1", IO.read($mrbtest_io_wfname, 1)
+ assert_equal "", IO.read($mrbtest_io_wfname, 0, 10)
+ assert_equal "23", IO.read($mrbtest_io_wfname, 2, 1)
+ assert_equal "23", IO.read($mrbtest_io_wfname, 10, 1)
+ assert_equal "", IO.read($mrbtest_io_wfname, nil, 10)
+ assert_equal nil, IO.read($mrbtest_io_wfname, 1, 10)
+end
+
+assert('IO#fileno') do
+ fd = IO.sysopen $mrbtest_io_rfname
+ io = IO.new fd
+ assert_equal io.fileno, fd
+ assert_equal io.to_i, fd
+ io.close
+ io.closed?
+end
+
+assert('IO#close_on_exec') do
+ fd = IO.sysopen $mrbtest_io_wfname, "w"
+ io = IO.new fd, "w"
+ begin
+ # IO.sysopen opens a file descripter with O_CLOEXEC flag.
+ assert_true io.close_on_exec?
+ rescue ScriptError
+ skip "IO\#close_on_exec is not implemented."
+ end
+
+ io.close_on_exec = false
+ assert_equal(false, io.close_on_exec?)
+ io.close_on_exec = true
+ assert_equal(true, io.close_on_exec?)
+ io.close_on_exec = false
+ assert_equal(false, io.close_on_exec?)
+
+ io.close
+ io.closed?
+
+ # # Use below when IO.pipe is implemented.
+ # begin
+ # r, w = IO.pipe
+ # assert_equal(false, r.close_on_exec?)
+ # r.close_on_exec = true
+ # assert_equal(true, r.close_on_exec?)
+ # r.close_on_exec = false
+ # assert_equal(false, r.close_on_exec?)
+ # r.close_on_exec = true
+ # assert_equal(true, r.close_on_exec?)
+
+ # assert_equal(false, w.close_on_exec?)
+ # w.close_on_exec = true
+ # assert_equal(true, w.close_on_exec?)
+ # w.close_on_exec = false
+ # assert_equal(false, w.close_on_exec?)
+ # w.close_on_exec = true
+ # assert_equal(true, w.close_on_exec?)
+ # ensure
+ # r.close unless r.closed?
+ # w.close unless w.closed?
+ # end
+end
+
+assert('`cmd`') do
+ assert_equal `echo foo`, "foo\n"
+end
+
+assert('IO TEST CLEANUP') do
+ assert_nil MRubyIOTestUtil.io_test_cleanup
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-io/test/mruby_io_test.c b/web/server/h2o/libh2o/deps/mruby-io/test/mruby_io_test.c
new file mode 100644
index 00000000..f58f9ff8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-io/test/mruby_io_test.c
@@ -0,0 +1,141 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "mruby.h"
+#include "mruby/array.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+
+static mrb_value
+mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
+{
+ char rfname[] = "tmp.mruby-io-test.XXXXXXXX";
+ char wfname[] = "tmp.mruby-io-test.XXXXXXXX";
+ char symlinkname[] = "tmp.mruby-io-test.XXXXXXXX";
+ char socketname[] = "tmp.mruby-io-test.XXXXXXXX";
+ char msg[] = "mruby io test\n";
+ mode_t mask;
+ int fd0, fd1, fd2, fd3;
+ FILE *fp;
+ struct sockaddr_un sun0;
+
+ mask = umask(077);
+ fd0 = mkstemp(rfname);
+ fd1 = mkstemp(wfname);
+ fd2 = mkstemp(symlinkname);
+ fd3 = mkstemp(socketname);
+ if (fd0 == -1 || fd1 == -1 || fd2 == -1 || fd3 == -1) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
+ return mrb_nil_value();
+ }
+ umask(mask);
+
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_str_new_cstr(mrb, rfname));
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_str_new_cstr(mrb, wfname));
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_str_new_cstr(mrb, symlinkname));
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_str_new_cstr(mrb, socketname));
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_str_new_cstr(mrb, msg));
+
+ fp = fopen(rfname, "w");
+ if (fp == NULL) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
+ return mrb_nil_value();
+ }
+ fputs(msg, fp);
+ fclose(fp);
+
+ fp = fopen(wfname, "w");
+ if (fp == NULL) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
+ return mrb_nil_value();
+ }
+ fclose(fp);
+
+ unlink(symlinkname);
+ close(fd2);
+ if (symlink("hoge", symlinkname) == -1) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
+ }
+
+ unlink(socketname);
+ close(fd3);
+ fd3 = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd3 == -1) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket");
+ }
+ sun0.sun_family = AF_UNIX;
+ snprintf(sun0.sun_path, sizeof(sun0.sun_path), "%s", socketname);
+ if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket bi");
+ }
+ close(fd3);
+
+ return mrb_true_value();
+}
+
+static mrb_value
+mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
+{
+ mrb_value rfname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"));
+ mrb_value wfname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"));
+ mrb_value symlinkname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"));
+ mrb_value socketname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"));
+
+ if (mrb_type(rfname) == MRB_TT_STRING) {
+ remove(RSTRING_PTR(rfname));
+ }
+ if (mrb_type(wfname) == MRB_TT_STRING) {
+ remove(RSTRING_PTR(wfname));
+ }
+ if (mrb_type(symlinkname) == MRB_TT_STRING) {
+ remove(RSTRING_PTR(symlinkname));
+ }
+ if (mrb_type(socketname) == MRB_TT_STRING) {
+ remove(RSTRING_PTR(socketname));
+ }
+
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_nil_value());
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_nil_value());
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_nil_value());
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_nil_value());
+ mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_nil_value());
+
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_io_test_file_setup(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary = mrb_io_test_io_setup(mrb, self);
+ if (symlink("/usr/bin", "test-bin") == -1) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
+ }
+
+ return ary;
+}
+
+static mrb_value
+mrb_io_test_file_cleanup(mrb_state *mrb, mrb_value self)
+{
+ mrb_io_test_io_cleanup(mrb, self);
+ remove("test-bin");
+
+ return mrb_nil_value();
+}
+
+void
+mrb_mruby_io_gem_test(mrb_state* mrb)
+{
+ struct RClass *io_test = mrb_define_module(mrb, "MRubyIOTestUtil");
+ mrb_define_class_method(mrb, io_test, "io_test_setup", mrb_io_test_io_setup, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, io_test, "io_test_cleanup", mrb_io_test_io_cleanup, MRB_ARGS_NONE());
+
+ mrb_define_class_method(mrb, io_test, "file_test_setup", mrb_io_test_file_setup, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, io_test, "file_test_cleanup", mrb_io_test_file_cleanup, MRB_ARGS_NONE());
+
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis.yml b/web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis.yml
new file mode 100644
index 00000000..5a0d1ddf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis.yml
@@ -0,0 +1,10 @@
+sudo: false
+addons:
+ apt:
+ packages:
+ - gperf
+script:
+ - export MRUBY_CONFIG="$TRAVIS_BUILD_DIR/.travis_config.rb"
+ - git clone --depth 1 "https://github.com/mruby/mruby.git"
+ - cd mruby
+ - ./minirake all test
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis_config.rb b/web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis_config.rb
new file mode 100644
index 00000000..769446c4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/.travis_config.rb
@@ -0,0 +1,21 @@
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ enable_debug
+ enable_test
+
+ gem :core => 'mruby-print'
+ gem :core => 'mruby-sprintf'
+ gem "#{MRUBY_ROOT}/.."
+end
+
+MRuby::Build.new("onigmo-bundled") do |conf|
+ toolchain :gcc
+ enable_debug
+ enable_test
+
+ gem :core => 'mruby-print'
+ gem :core => 'mruby-sprintf'
+ gem "#{MRUBY_ROOT}/.." do |g|
+ g.bundle_onigmo
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/Onigmo-6.1.1.tar.gz b/web/server/h2o/libh2o/deps/mruby-onig-regexp/Onigmo-6.1.1.tar.gz
new file mode 100644
index 00000000..13922658
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/Onigmo-6.1.1.tar.gz
Binary files differ
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/README.md b/web/server/h2o/libh2o/deps/mruby-onig-regexp/README.md
new file mode 100644
index 00000000..41eada48
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/README.md
@@ -0,0 +1,45 @@
+# mruby-onig-regexp
+
+[![Build Status](https://travis-ci.org/mattn/mruby-onig-regexp.svg)](https://travis-ci.org/mattn/mruby-onig-regexp)
+
+## install by mrbgems
+```ruby
+MRuby::Build.new do |conf|
+
+ # ... (snip) ...
+
+ conf.gem :github => 'mattn/mruby-onig-regexp'
+end
+```
+
+## Example
+```ruby
+
+def matchstr(str)
+ reg = Regexp.compile("abc")
+
+ if reg =~ str then
+ p "match"
+ else
+ p "not match"
+ end
+end
+
+matchstr("abcdef") # => match
+matchstr("ghijkl") # => not match
+matchstr("xyzabc") # => match
+```
+
+## License
+
+MIT
+
+### License of Onigmo
+BSD licensed.
+
+ Onigmo (Oniguruma-mod) -- (C) K.Takata <kentkt AT csc DOT jp>
+ Oniguruma ---- (C) K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+
+## Author
+
+Yasuhiro Matsumoto (a.k.a mattn)
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-onig-regexp/mrbgem.rake
new file mode 100644
index 00000000..67998670
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/mrbgem.rake
@@ -0,0 +1,113 @@
+MRuby::Gem::Specification.new('mruby-onig-regexp') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'mattn'
+
+ def spec.bundle_onigmo
+ return if @onigmo_bundled
+ @onigmo_bundled = true
+
+ visualcpp = ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+
+ require 'open3'
+
+ # remove libonig, instead link directly against pthread
+ unless ENV['OS'] == 'Windows_NT'
+ linker.libraries = ['pthread']
+ end
+
+ version = '6.1.1'
+ oniguruma_dir = "#{build_dir}/onigmo-#{version}"
+ oniguruma_lib = libfile "#{oniguruma_dir}/.libs/libonigmo"
+ unless ENV['OS'] == 'Windows_NT'
+ oniguruma_lib = libfile "#{oniguruma_dir}/.libs/libonigmo"
+ else
+ if ENV['PROCESSOR_ARCHITECTURE'] == 'AMD64'
+ oniguruma_lib = libfile "#{oniguruma_dir}/build-x86-64/onigmo"
+ else
+ oniguruma_lib = libfile "#{oniguruma_dir}/build-i686/onigmo"
+ end
+ end
+ header = "#{oniguruma_dir}/onigmo.h"
+
+ task :clean do
+ FileUtils.rm_rf [oniguruma_dir]
+ end
+
+ file header do |t|
+ FileUtils.mkdir_p oniguruma_dir
+ Dir.chdir(build_dir) do
+ _pp 'extracting', "Onigmo-#{version}"
+ `gzip -dc "#{dir}/Onigmo-#{version}.tar.gz" | tar xf -`
+ end
+ end
+
+ def run_command(env, command)
+ STDOUT.sync = true
+ Open3.popen2e(env, command) do |stdin, stdout, thread|
+ print stdout.read
+ fail "#{command} failed" if thread.value != 0
+ end
+ end
+
+ libonig_objs_dir = "#{oniguruma_dir}/libonig_objs"
+ libmruby_a = libfile("#{build.build_dir}/lib/libmruby")
+ objext = visualcpp ? '.obj' : '.o'
+
+ file oniguruma_lib => header do |t|
+ Dir.chdir(oniguruma_dir) do
+ e = {
+ 'CC' => "#{build.cc.command} #{build.cc.flags.join(' ')}",
+ 'CXX' => "#{build.cxx.command} #{build.cxx.flags.join(' ')}",
+ 'LD' => "#{build.linker.command} #{build.linker.flags.join(' ')}",
+ 'AR' => build.archiver.command }
+ unless ENV['OS'] == 'Windows_NT'
+ if build.kind_of? MRuby::CrossBuild
+ host = "--host #{build.name}"
+ end
+
+ _pp 'autotools', oniguruma_dir
+ run_command e, './autogen.sh' if File.exists? 'autogen.sh'
+ run_command e, "./configure --disable-shared --enable-static #{host}"
+ run_command e, 'make'
+ else
+ run_command e, 'cmd /c "copy /Y win32 > NUL"'
+ if visualcpp
+ run_command e, 'nmake -f Makefile'
+ else
+ run_command e, 'make -f Makefile.mingw'
+ end
+ end
+ end
+
+ FileUtils.mkdir_p libonig_objs_dir
+ Dir.chdir(libonig_objs_dir) do
+ unless visualcpp
+ `ar x #{oniguruma_lib}`
+ else
+ winname = oniguruma_lib.gsub(%'/', '\\')
+ `lib -nologo -list #{winname}`.each_line do |line|
+ line.chomp!
+ `lib -nologo -extract:#{line} #{winname}`
+ end
+ end
+ end
+ file libmruby_a => Dir.glob("#{libonig_objs_dir}/*#{objext}")
+ end
+
+ file libmruby_a => Dir.glob("#{libonig_objs_dir}/*#{objext}") if File.exists? oniguruma_lib
+
+ file "#{dir}/src/mruby_onig_regexp.c" => oniguruma_lib
+ cc.include_paths << oniguruma_dir
+ cc.defines += ['HAVE_ONIGMO_H']
+ end
+
+ if spec.respond_to? :search_package and spec.search_package 'onigmo'
+ spec.cc.defines += ['HAVE_ONIGMO_H']
+ elsif spec.respond_to? :search_package and spec.search_package 'oniguruma'
+ spec.cc.defines += ['HAVE_ONIGURUMA_H']
+ elsif build.cc.respond_to? :search_header_path and build.cc.search_header_path 'oniguruma.h'
+ spec.linker.libraries << 'onig'
+ else
+ spec.bundle_onigmo
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/mrblib/onig_regexp.rb b/web/server/h2o/libh2o/deps/mruby-onig-regexp/mrblib/onig_regexp.rb
new file mode 100644
index 00000000..2dc8d55e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/mrblib/onig_regexp.rb
@@ -0,0 +1,140 @@
+class OnigRegexp
+ @memo = {}
+
+ # ISO 15.2.15.6.1
+ def self.compile(*args)
+ as = args.to_s
+ unless @memo.key? as
+ @memo[as] = self.new(*args)
+ end
+ @memo[as]
+ end
+
+ # ISO 15.2.15.6.3
+ def self.last_match
+ @last_match
+ end
+
+ # ISO 15.2.15.7.2
+ def initialize_copy(other)
+ initialize(other.source, other.options)
+ end
+
+ # ISO 15.2.15.7.4
+ def ===(str)
+ not self.match(str).nil?
+ end
+
+ # ISO 15.2.15.7.5
+ def =~(str)
+ m = self.match(str)
+ m ? m.begin(0) : nil
+ end
+
+ # ISO 15.2.15.7.8
+ attr_reader :source
+end
+
+class String
+ # ISO 15.2.10.5.5
+ def =~(a)
+ begin
+ (a.class.to_s == 'String' ? Regexp.new(a.to_s) : a) =~ self
+ rescue
+ false
+ end
+ end
+
+ # redefine methods with oniguruma regexp version
+ [:sub, :gsub, :split, :scan].each do |v|
+ alias_method "string_#{v}".to_sym, v
+ alias_method v, "onig_regexp_#{v}".to_sym
+ end
+
+ alias_method :old_slice, :slice
+ alias_method :old_square_brancket, :[]
+
+ def [](*args)
+ return old_square_brancket(*args) unless args[0].class == Regexp
+
+ if args.size == 2
+ match = args[0].match(self)
+ if match
+ if args[1] == 0
+ str = match[0]
+ else
+ str = match.captures[args[1] - 1]
+ end
+ return str
+ end
+ end
+
+ match_data = args[0].match(self)
+ if match_data
+ result = match_data.to_s
+ return result
+ end
+ end
+
+ alias_method :slice, :[]
+
+ def slice!(*args)
+ if args.size < 2
+ result = slice(*args)
+ nth = args[0]
+
+ if nth.class == Regexp
+ lm = Regexp.last_match
+ self[nth] = '' if result
+ Regexp.last_match = lm
+ else
+ self[nth] = '' if result
+ end
+ else
+ result = slice(*args)
+
+ nth = args[0]
+ len = args[1]
+
+ if nth.class == Regexp
+ lm = Regexp.last_match
+ self[nth, len] = '' if result
+ Regexp.last_match = lm
+ else
+ self[nth, len] = '' if result && nth != self.size
+ end
+ end
+
+ result
+ end
+
+ alias_method :old_index, :index
+
+ def index(pattern, pos=0)
+ if pattern.class == Regexp
+ str = self[pos..-1]
+ if str
+ if num = (pattern =~ str)
+ if pos < 0
+ num += self.size
+ end
+ return num + pos
+ end
+ end
+ nil
+ else
+ self.old_index(pattern, pos)
+ end
+ end
+end
+
+module Kernel
+ def =~(_)
+ nil
+ end
+end
+
+Regexp = OnigRegexp unless Object.const_defined?(:Regexp)
+MatchData = OnigMatchData unless Object.const_defined? :MatchData
+
+# This is based on https://github.com/masamitsu-murase/mruby-hs-regexp
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/src/mruby_onig_regexp.c b/web/server/h2o/libh2o/deps/mruby-onig-regexp/src/mruby_onig_regexp.c
new file mode 100644
index 00000000..38d93ccb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/src/mruby_onig_regexp.c
@@ -0,0 +1,1064 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2015 mattn.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <memory.h>
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/variable.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/data.h>
+#include <mruby/variable.h>
+#ifdef _MSC_VER
+#define ONIG_EXTERN extern
+#endif
+#ifdef HAVE_ONIGMO_H
+#include <onigmo.h>
+#elif defined(HAVE_ONIGURUMA_H)
+#include <oniguruma.h>
+#else
+#include "oniguruma.h"
+#endif
+
+#ifdef MRUBY_VERSION
+#define mrb_args_int mrb_int
+#else
+#define mrb_args_int int
+#endif
+
+static const char utf8len_codepage[256] =
+{
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,
+};
+
+static mrb_int
+utf8len(const char* p, const char* e)
+{
+ mrb_int len;
+ mrb_int i;
+
+ len = utf8len_codepage[(unsigned char)*p];
+ if (p + len > e) return 1;
+ for (i = 1; i < len; ++i)
+ if ((p[i] & 0xc0) != 0x80)
+ return 1;
+ return len;
+}
+
+static void
+onig_regexp_free(mrb_state *mrb, void *p) {
+ onig_free((OnigRegex) p);
+}
+
+static struct mrb_data_type mrb_onig_regexp_type = {
+ "PosixRegexp", onig_regexp_free
+};
+
+static void
+match_data_free(mrb_state* mrb, void* p) {
+ (void)mrb;
+ onig_region_free((OnigRegion*)p, 1);
+}
+
+static struct mrb_data_type mrb_onig_region_type = {
+ "OnigRegion", match_data_free
+};
+
+static mrb_value
+onig_regexp_initialize(mrb_state *mrb, mrb_value self) {
+ mrb_value str, flag = mrb_nil_value(), code = mrb_nil_value();
+ mrb_get_args(mrb, "S|oo", &str, &flag, &code);
+
+ int cflag = 0;
+ OnigEncoding enc = ONIG_ENCODING_UTF8;
+ if(mrb_string_p(code)) {
+ char const* str_code = mrb_string_value_ptr(mrb, code);
+ if(strchr(str_code, 'n') || strchr(str_code, 'N')) {
+ enc = ONIG_ENCODING_ASCII;
+ }
+ }
+ if(mrb_nil_p(flag)) {
+ } else if(mrb_type(flag) == MRB_TT_TRUE) {
+ cflag |= ONIG_OPTION_IGNORECASE;
+ } else if(mrb_fixnum_p(flag)) {
+ int int_flags = mrb_fixnum(flag);
+ if(int_flags & 0x1) { cflag |= ONIG_OPTION_IGNORECASE; }
+ if(int_flags & 0x2) { cflag |= ONIG_OPTION_EXTEND; }
+ if(int_flags & 0x4) { cflag |= ONIG_OPTION_MULTILINE; }
+ } else if(mrb_string_p(flag)) {
+ char const* str_flags = mrb_string_value_ptr(mrb, flag);
+ if(strchr(str_flags, 'i')) { cflag |= ONIG_OPTION_IGNORECASE; }
+ if(strchr(str_flags, 'x')) { cflag |= ONIG_OPTION_EXTEND; }
+ if(strchr(str_flags, 'm')) { cflag |= ONIG_OPTION_MULTILINE; }
+ } else {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "unknown regexp flag: %S", flag);
+ }
+
+ OnigErrorInfo einfo;
+ OnigRegex reg;
+ int result = onig_new(&reg, (OnigUChar*)RSTRING_PTR(str), (OnigUChar*) RSTRING_PTR(str) + RSTRING_LEN(str),
+ cflag, enc, ONIG_SYNTAX_RUBY, &einfo);
+ if (result != ONIG_NORMAL) {
+ char err[ONIG_MAX_ERROR_MESSAGE_LEN] = "";
+ onig_error_code_to_str((OnigUChar*)err, result);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "'%S' is an invalid regular expression because %S.",
+ str, mrb_str_new_cstr(mrb, err));
+ }
+ mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@source"), str);
+
+ DATA_PTR(self) = reg;
+ DATA_TYPE(self) = &mrb_onig_regexp_type;
+
+ return self;
+}
+
+static mrb_value
+create_onig_region(mrb_state* mrb, mrb_value const str, mrb_value rex) {
+ mrb_assert(mrb_string_p(str));
+ mrb_assert(mrb_type(rex) == MRB_TT_DATA && DATA_TYPE(rex) == &mrb_onig_regexp_type);
+ mrb_value const c = mrb_obj_value(mrb_data_object_alloc(
+ mrb, mrb_class_get(mrb, "OnigMatchData"), onig_region_new(), &mrb_onig_region_type));
+ mrb_iv_set(mrb, c, mrb_intern_lit(mrb, "string"), mrb_str_dup(mrb, str));
+ mrb_iv_set(mrb, c, mrb_intern_lit(mrb, "regexp"), rex);
+ return c;
+}
+
+static int
+onig_match_common(mrb_state* mrb, OnigRegex reg, mrb_value match_value, mrb_value str, int pos) {
+ mrb_assert(mrb_string_p(str));
+ mrb_assert(DATA_TYPE(match_value) == &mrb_onig_region_type);
+ OnigRegion* const match = (OnigRegion*)DATA_PTR(match_value);
+ OnigUChar const* str_ptr = (OnigUChar const*)RSTRING_PTR(str);
+ int const result = onig_search(reg, str_ptr, str_ptr + RSTRING_LEN(str),
+ str_ptr + pos, str_ptr + RSTRING_LEN(str), match, 0);
+ if (result != ONIG_MISMATCH && result < 0) {
+ char err[ONIG_MAX_ERROR_MESSAGE_LEN] = "";
+ onig_error_code_to_str((OnigUChar*)err, result);
+ mrb_raise(mrb, E_REGEXP_ERROR, err);
+ }
+
+ struct RObject* const cls = (struct RObject*)mrb_class_get(mrb, "OnigRegexp");
+ mrb_obj_iv_set(mrb, cls, mrb_intern_lit(mrb, "@last_match"), match_value);
+
+ if (result != ONIG_MISMATCH &&
+ mrb_class_get(mrb, "Regexp") == (struct RClass*)cls &&
+ mrb_bool(mrb_obj_iv_get(mrb, (struct RObject*)cls, mrb_intern_lit(mrb, "@set_global_variables"))))
+ {
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$~"), match_value);
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$&"),
+ mrb_funcall(mrb, match_value, "[]", 1, mrb_fixnum_value(0)));
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$`"), mrb_funcall(mrb, match_value, "pre_match", 0));
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$'"), mrb_funcall(mrb, match_value, "post_match", 0));
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$+"),
+ mrb_funcall(mrb, match_value, "[]", 1, mrb_fixnum_value(match->num_regs - 1)));
+
+ // $1 to $9
+ int idx = 1;
+ int const idx_max = match->num_regs > 10? 10 : match->num_regs;
+ for(; idx < idx_max; ++idx) {
+ char const n[] = { '$', '0' + idx };
+ mrb_gv_set(mrb, mrb_intern(mrb, n, 2),
+ mrb_funcall(mrb, match_value, "[]", 1, mrb_fixnum_value(idx)));
+ }
+
+ for(; idx < 10; ++idx) {
+ char const n[] = { '$', '0' + idx };
+ mrb_gv_remove(mrb, mrb_intern(mrb, n, 2));
+ }
+ }
+
+ return result;
+}
+
+static mrb_value
+onig_regexp_match(mrb_state *mrb, mrb_value self) {
+ mrb_value str = mrb_nil_value();
+ OnigRegex reg;
+ mrb_int pos = 0;
+
+ mrb_get_args(mrb, "o|i", &str, &pos);
+ if (pos < 0 || (pos > 0 && pos >= RSTRING_LEN(str))) {
+ return mrb_nil_value();
+ }
+
+ if (mrb_nil_p(str)) {
+ return mrb_nil_value();
+ }
+ str = mrb_string_type(mrb, str);
+
+ Data_Get_Struct(mrb, self, &mrb_onig_regexp_type, reg);
+
+ mrb_value const ret = create_onig_region(mrb, str, self);
+ return (onig_match_common(mrb, reg, ret, str, pos) == ONIG_MISMATCH)
+ ? mrb_nil_value() : ret;
+}
+
+static mrb_value
+onig_regexp_equal(mrb_state *mrb, mrb_value self) {
+ mrb_value other;
+ OnigRegex self_reg, other_reg;
+
+ mrb_get_args(mrb, "o", &other);
+ if (mrb_obj_equal(mrb, self, other)){
+ return mrb_true_value();
+ }
+ if (mrb_nil_p(other)) {
+ return mrb_false_value();
+ }
+ if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "OnigRegexp"))) {
+ return mrb_false_value();
+ }
+ Data_Get_Struct(mrb, self, &mrb_onig_regexp_type, self_reg);
+ Data_Get_Struct(mrb, other, &mrb_onig_regexp_type, other_reg);
+
+ if (!self_reg || !other_reg){
+ mrb_raise(mrb, E_RUNTIME_ERROR, "Invalid OnigRegexp");
+ }
+ if (onig_get_options(self_reg) != onig_get_options(other_reg)){
+ return mrb_false_value();
+ }
+ return mrb_str_equal(mrb, mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@source")), mrb_iv_get(mrb, other, mrb_intern_lit(mrb, "@source"))) ?
+ mrb_true_value() : mrb_false_value();
+}
+
+static mrb_value
+onig_regexp_casefold_p(mrb_state *mrb, mrb_value self) {
+ OnigRegex reg;
+
+ Data_Get_Struct(mrb, self, &mrb_onig_regexp_type, reg);
+ return (onig_get_options(reg) & ONIG_OPTION_IGNORECASE) ? mrb_true_value() : mrb_false_value();
+}
+
+static mrb_value
+onig_regexp_options(mrb_state *mrb, mrb_value self) {
+ OnigRegex reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_regexp_type, reg);
+ return mrb_fixnum_value(onig_get_options(reg));
+}
+
+static char *
+option_to_str(char str[4], int options) {
+ char *p = str;
+ if (options & ONIG_OPTION_MULTILINE) *p++ = 'm';
+ if (options & ONIG_OPTION_IGNORECASE) *p++ = 'i';
+ if (options & ONIG_OPTION_EXTEND) *p++ = 'x';
+ *p = 0;
+ return str;
+}
+
+static mrb_value
+regexp_expr_str(mrb_state *mrb, mrb_value str, const char *p, int len) {
+ const char *pend;
+ char buf[5];
+
+ pend = (const char *) p + len;
+ for (;p < pend; p++) {
+ unsigned char c, cc;
+
+ c = *p;
+ if (c == '/'|| c == '\\') {
+ buf[0] = '\\'; buf[1] = c;
+ mrb_str_cat(mrb, str, buf, 2);
+ continue;
+ }
+ if (ISPRINT(c)) {
+ buf[0] = c;
+ mrb_str_cat(mrb, str, buf, 1);
+ continue;
+ }
+ switch (c) {
+ case '\n': cc = 'n'; break;
+ case '\r': cc = 'r'; break;
+ case '\t': cc = 't'; break;
+ default: cc = 0; break;
+ }
+ if (cc) {
+ buf[0] = '\\';
+ buf[1] = (char)cc;
+ mrb_str_cat(mrb, str, buf, 2);
+ continue;
+ }
+ else {
+ buf[0] = '\\';
+ buf[3] = '0' + c % 8; c /= 8;
+ buf[2] = '0' + c % 8; c /= 8;
+ buf[1] = '0' + c % 8;
+ mrb_str_cat(mrb, str, buf, 4);
+ continue;
+ }
+ }
+ return str;
+}
+
+static mrb_value
+onig_regexp_inspect(mrb_state *mrb, mrb_value self) {
+ OnigRegex reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_regexp_type, reg);
+ mrb_value str = mrb_str_new_lit(mrb, "/");
+ mrb_value src = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@source"));
+ regexp_expr_str(mrb, str, (const char *)RSTRING_PTR(src), RSTRING_LEN(src));
+ mrb_str_cat_lit(mrb, str, "/");
+ char opts[4];
+ if (*option_to_str(opts, onig_get_options(reg))) {
+ mrb_str_cat_cstr(mrb, str, opts);
+ }
+ if (onig_get_encoding(reg) == ONIG_ENCODING_ASCII) {
+ mrb_str_cat_lit(mrb, str, "n");
+ }
+ return str;
+}
+
+static mrb_value
+onig_regexp_to_s(mrb_state *mrb, mrb_value self) {
+ int options;
+ const int embeddable = ONIG_OPTION_MULTILINE|ONIG_OPTION_IGNORECASE|ONIG_OPTION_EXTEND;
+ long len;
+ const char* ptr;
+ mrb_value str = mrb_str_new_lit(mrb, "(?");
+ char optbuf[5];
+
+ OnigRegex reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_regexp_type, reg);
+ options = onig_get_options(reg);
+ mrb_value src = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@source"));
+ ptr = RSTRING_PTR(src);
+ len = RSTRING_LEN(src);
+
+ again:
+ if (len >= 4 && ptr[0] == '(' && ptr[1] == '?') {
+ int err = 1;
+ ptr += 2;
+ if ((len -= 2) > 0) {
+ do {
+ if(strchr(ptr, 'i')) { options |= ONIG_OPTION_IGNORECASE; }
+ if(strchr(ptr, 'x')) { options |= ONIG_OPTION_EXTEND; }
+ if(strchr(ptr, 'm')) { options |= ONIG_OPTION_MULTILINE; }
+ ++ptr;
+ } while (--len > 0);
+ }
+ if (len > 1 && *ptr == '-') {
+ ++ptr;
+ --len;
+ do {
+ if(strchr(ptr, 'i')) { options &= ~ONIG_OPTION_IGNORECASE; }
+ if(strchr(ptr, 'x')) { options &= ~ONIG_OPTION_EXTEND; }
+ if(strchr(ptr, 'm')) { options &= ~ONIG_OPTION_MULTILINE; }
+ ++ptr;
+ } while (--len > 0);
+ }
+ if (*ptr == ')') {
+ --len;
+ ++ptr;
+ goto again;
+ }
+ if (*ptr == ':' && ptr[len-1] == ')') {
+ OnigRegex rp;
+ ++ptr;
+ len -= 2;
+ err = onig_new(&rp, (OnigUChar*)ptr, (OnigUChar*)ptr + len, ONIG_OPTION_DEFAULT,
+ ONIG_ENCODING_UTF8, OnigDefaultSyntax, NULL);
+ onig_free(rp);
+ }
+ if (err) {
+ options = onig_get_options(reg);
+ ptr = RSTRING_PTR(src);
+ len = RSTRING_LEN(src);
+ }
+ }
+
+ if (*option_to_str(optbuf, options)) mrb_str_cat_cstr(mrb, str, optbuf);
+
+ if ((options & embeddable) != embeddable) {
+ optbuf[0] = '-';
+ option_to_str(optbuf + 1, ~options);
+ mrb_str_cat_cstr(mrb, str, optbuf);
+ }
+
+ mrb_str_cat_cstr(mrb, str, ":");
+ regexp_expr_str(mrb, str, ptr, len);
+ mrb_str_cat_cstr(mrb, str, ")");
+ return str;
+}
+
+
+static mrb_value
+onig_regexp_version(mrb_state* mrb, mrb_value self) {
+ (void)self;
+ return mrb_str_new_cstr(mrb, onig_version());
+}
+
+static mrb_value
+match_data_to_a(mrb_state* mrb, mrb_value self);
+
+static mrb_int
+match_data_actual_index(mrb_state* mrb, mrb_value self, mrb_value idx_value) {
+ if(mrb_fixnum_p(idx_value)) { return mrb_fixnum(idx_value); }
+
+ char const* name = NULL;
+ char const* name_end = NULL;
+ if(mrb_symbol_p(idx_value)) {
+ mrb_int sym_len;
+ name = mrb_sym2name_len(mrb, mrb_symbol(idx_value), &sym_len);
+ name_end = name + sym_len;
+ } else if(mrb_string_p(idx_value)) {
+ name = mrb_string_value_ptr(mrb, idx_value);
+ name_end = name + strlen(name);
+ } else { mrb_assert(FALSE); }
+ mrb_assert(name && name_end);
+
+ mrb_value const regexp = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "regexp"));
+ mrb_assert(!mrb_nil_p(regexp));
+ mrb_assert(DATA_TYPE(regexp) == &mrb_onig_regexp_type);
+ mrb_assert(DATA_TYPE(self) == &mrb_onig_region_type);
+ int const idx = onig_name_to_backref_number(
+ (OnigRegex)DATA_PTR(regexp), (OnigUChar const*)name, (OnigUChar const*)name_end,
+ (OnigRegion*)DATA_PTR(self));
+ if (idx < 0) {
+ mrb_raisef(mrb, E_INDEX_ERROR, "undefined group name reference: %S", idx_value);
+ }
+ return idx;
+}
+
+// ISO 15.2.16.3.1
+static mrb_value
+match_data_index(mrb_state* mrb, mrb_value self) {
+ mrb_value src;
+ mrb_int argc; mrb_value *argv;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ src = match_data_to_a(mrb, self);
+
+ if (argc == 1) {
+ switch (mrb_type(argv[0])) {
+ case MRB_TT_FIXNUM:
+ case MRB_TT_SYMBOL:
+ case MRB_TT_STRING:
+ return mrb_ary_entry(src, match_data_actual_index(mrb, self, argv[0]));
+ default: break;
+ }
+ }
+
+ return mrb_funcall_argv(mrb, src, mrb_intern_lit(mrb, "[]"), argc, argv);
+}
+
+#define match_data_check_index(idx) \
+ if(idx < 0 || reg->num_regs <= idx) \
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of matches", mrb_fixnum_value(idx)) \
+
+// ISO 15.2.16.3.2
+static mrb_value
+match_data_begin(mrb_state* mrb, mrb_value self) {
+ mrb_value idx_value;
+ mrb_get_args(mrb, "o", &idx_value);
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ mrb_int const idx = match_data_actual_index(mrb, self, idx_value);
+ match_data_check_index(idx);
+ return mrb_fixnum_value(reg->beg[idx]);
+}
+
+// ISO 15.2.16.3.3
+static mrb_value
+match_data_captures(mrb_state* mrb, mrb_value self) {
+ mrb_value ary = match_data_to_a(mrb, self);
+ return mrb_ary_new_from_values(mrb, RARRAY_LEN(ary) - 1, RARRAY_PTR(ary) + 1);
+}
+
+// ISO 15.2.16.3.4
+static mrb_value
+match_data_end(mrb_state* mrb, mrb_value self) {
+ mrb_value idx_value;
+ mrb_get_args(mrb, "o", &idx_value);
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ mrb_int const idx = match_data_actual_index(mrb, self, idx_value);
+ match_data_check_index(idx);
+ return mrb_fixnum_value(reg->end[idx]);
+}
+
+// ISO 15.2.16.3.5
+static mrb_value
+match_data_copy(mrb_state* mrb, mrb_value self) {
+ mrb_value src_val;
+ mrb_get_args(mrb, "o", &src_val);
+
+ OnigRegion* src;
+ Data_Get_Struct(mrb, src_val, &mrb_onig_region_type, src);
+
+ OnigRegion* dst = onig_region_new();
+ onig_region_copy(dst, src);
+
+ DATA_PTR(self) = dst;
+ DATA_TYPE(self) = &mrb_onig_region_type;
+ mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "string"), mrb_iv_get(mrb, src_val, mrb_intern_lit(mrb, "string")));
+ mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "regexp"), mrb_iv_get(mrb, src_val, mrb_intern_lit(mrb, "regexp")));
+ return self;
+}
+
+// ISO 15.2.16.3.6
+// ISO 15.2.16.3.10
+static mrb_value
+match_data_length(mrb_state* mrb, mrb_value self) {
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ return mrb_fixnum_value(reg->num_regs);
+}
+
+// ISO 15.2.16.3.7
+static mrb_value
+match_data_offset(mrb_state* mrb, mrb_value self) {
+ mrb_value idx_value;
+ mrb_get_args(mrb, "o", &idx_value);
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ mrb_int const idx = match_data_actual_index(mrb, self, idx_value);
+ match_data_check_index(idx);
+ mrb_value ret = mrb_ary_new_capa(mrb, 2);
+ mrb_ary_push(mrb, ret, mrb_fixnum_value(reg->beg[idx]));
+ mrb_ary_push(mrb, ret, mrb_fixnum_value(reg->end[idx]));
+ return ret;
+}
+
+// ISO 15.2.16.3.8
+static mrb_value
+match_data_post_match(mrb_state* mrb, mrb_value self) {
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ mrb_value str = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "string"));
+ return mrb_str_substr(mrb, str, reg->end[0], RSTRING_LEN(str) - reg->end[0]);
+}
+
+// ISO 15.2.16.3.9
+static mrb_value
+match_data_pre_match(mrb_state* mrb, mrb_value self) {
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ mrb_value str = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "string"));
+ return mrb_str_substr(mrb, str, 0, reg->beg[0]);
+}
+
+// ISO 15.2.16.3.11
+static mrb_value
+match_data_string(mrb_state* mrb, mrb_value self) {
+ return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "string"));
+}
+
+static mrb_value
+match_data_regexp(mrb_state* mrb, mrb_value self) {
+ return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "regexp"));
+}
+
+// ISO 15.2.16.3.12
+static mrb_value
+match_data_to_a(mrb_state* mrb, mrb_value self) {
+ mrb_value cache = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "cache"));
+ if(!mrb_nil_p(cache)) {
+ return cache;
+ }
+
+ mrb_value str = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "string"));
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+
+ mrb_value ret = mrb_ary_new_capa(mrb, reg->num_regs);
+ int i, ai = mrb_gc_arena_save(mrb);
+ for(i = 0; i < reg->num_regs; ++i) {
+ if(reg->beg[i] == ONIG_REGION_NOTPOS) {
+ mrb_ary_push(mrb, ret, mrb_nil_value());
+ } else {
+ mrb_ary_push(mrb, ret, mrb_str_substr(mrb, str, reg->beg[i], reg->end[i] - reg->beg[i]));
+ }
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ return ret;
+}
+
+// ISO 15.2.16.3.13
+static mrb_value
+match_data_to_s(mrb_state* mrb, mrb_value self) {
+ mrb_value str = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "string"));
+ OnigRegion* reg;
+ Data_Get_Struct(mrb, self, &mrb_onig_region_type, reg);
+ return mrb_str_substr(mrb, str, reg->beg[0], reg->end[0] - reg->beg[0]);
+}
+
+static void
+append_replace_str(mrb_state* mrb, mrb_value result, mrb_value replace,
+ mrb_value src, OnigRegex reg, OnigRegion* match)
+{
+ mrb_assert(mrb_string_p(replace));
+ char const* ch;
+ char const* const end = RSTRING_PTR(replace) + RSTRING_LEN(replace);
+ for(ch = RSTRING_PTR(replace); ch < end; ++ch) {
+ if (*ch != '\\' || (ch + 1) >= end) {
+ mrb_str_cat(mrb, result, ch, 1);
+ continue;
+ }
+
+ switch(*(++ch)) { // skip back slash and get next char
+ case 'k': { // group name
+ if ((ch + 2) >= end || ch[1] != '<') { goto replace_expr_error; }
+ char const* name_beg = ch += 2;
+ while (*ch != '>') { if(++ch == end) { goto replace_expr_error; } }
+ mrb_assert(ch < end);
+ mrb_assert(*ch == '>');
+ int const idx = onig_name_to_backref_number(
+ reg, (OnigUChar const*)name_beg, (OnigUChar const*)ch, match);
+ if (idx < 0) {
+ mrb_raisef(mrb, E_INDEX_ERROR, "undefined group name reference: %S",
+ mrb_str_substr(mrb, replace, name_beg - RSTRING_PTR(replace), ch - name_beg));
+ }
+ mrb_str_cat(mrb, result, RSTRING_PTR(src) + match->beg[idx], match->end[idx] - match->beg[idx]);
+ } break;
+
+ case '\\': // escaped back slash
+ mrb_str_cat(mrb, result, ch, 1);
+ break;
+
+ default:
+ if (isdigit(*ch)) { // group number 0-9
+ int const idx = *ch - '0';
+ if (idx < match->num_regs) {
+ mrb_str_cat(mrb, result, RSTRING_PTR(src) + match->beg[idx], match->end[idx] - match->beg[idx]);
+ }
+ } else {
+ char const str[] = { '\\', *ch };
+ mrb_str_cat(mrb, result, str, 2);
+ }
+ break;
+ }
+ }
+
+ if(ch == end) { return; }
+
+replace_expr_error:
+ mrb_raisef(mrb, E_REGEXP_ERROR, "invalid replace expression: %S", replace);
+}
+
+// ISO 15.2.10.5.18
+static mrb_value
+string_gsub(mrb_state* mrb, mrb_value self) {
+ mrb_value blk, match_expr, replace_expr = mrb_nil_value();
+ int const argc = mrb_get_args(mrb, "&o|S", &blk, &match_expr, &replace_expr);
+
+ if(mrb_string_p(match_expr)) {
+ mrb_value argv[] = { match_expr, replace_expr };
+ return mrb_funcall_with_block(mrb, self, mrb_intern_lit(mrb, "string_gsub"), argc, argv, blk);
+ }
+
+ if(!mrb_nil_p(blk) && !mrb_nil_p(replace_expr)) {
+ blk = mrb_nil_value();
+ }
+
+ OnigRegex reg;
+ Data_Get_Struct(mrb, match_expr, &mrb_onig_regexp_type, reg);
+ mrb_value const result = mrb_str_new(mrb, NULL, 0);
+ mrb_value const match_value = create_onig_region(mrb, self, match_expr);
+ OnigRegion* const match = (OnigRegion*)DATA_PTR(match_value);
+ int last_end_pos = 0;
+
+ while(1) {
+ if(onig_match_common(mrb, reg, match_value, self, last_end_pos) == ONIG_MISMATCH) { break; }
+
+ mrb_str_cat(mrb, result, RSTRING_PTR(self) + last_end_pos, match->beg[0] - last_end_pos);
+
+ if(mrb_nil_p(blk)) {
+ append_replace_str(mrb, result, replace_expr, self, reg, match);
+ } else {
+ mrb_value const tmp_str = mrb_str_to_str(mrb, mrb_yield(mrb, blk, mrb_str_substr(
+ mrb, self, match->beg[0], match->end[0] - match->beg[0])));
+ mrb_assert(mrb_string_p(tmp_str));
+ mrb_str_concat(mrb, result, tmp_str);
+ }
+
+ last_end_pos = match->end[0];
+ if (match->beg[0] == match->end[0]) {
+ /*
+ * Always consume at least one character of the input string
+ * in order to prevent infinite loops.
+ */
+ char* p = RSTRING_PTR(self) + last_end_pos;
+ char* e = p + RSTRING_LEN(self);
+ int len = utf8len(p, e);
+ if (RSTRING_LEN(self) < last_end_pos + len) break;
+ mrb_str_cat(mrb, result, p, len);
+ last_end_pos += len;
+ }
+ }
+
+ mrb_str_cat(mrb, result, RSTRING_PTR(self) + last_end_pos, RSTRING_LEN(self) - last_end_pos);
+ return result;
+}
+
+// ISO 15.2.10.5.32
+static mrb_value
+string_scan(mrb_state* mrb, mrb_value self) {
+ mrb_value blk, match_expr;
+ mrb_get_args(mrb, "&o", &blk, &match_expr);
+
+ if(mrb_string_p(match_expr)) {
+ return mrb_funcall_with_block(mrb, self, mrb_intern_lit(mrb, "string_scan"),
+ 1, &match_expr, blk);
+ }
+
+ OnigRegex reg;
+ Data_Get_Struct(mrb, match_expr, &mrb_onig_regexp_type, reg);
+ mrb_value const result = mrb_nil_p(blk)? mrb_ary_new(mrb) : self;
+ mrb_value m_value = create_onig_region(mrb, self, match_expr);
+ OnigRegion* const m = (OnigRegion*)DATA_PTR(m_value);
+ int last_end_pos = 0;
+ int i;
+
+ while (1) {
+ if(onig_match_common(mrb, reg, m_value, self, last_end_pos) == ONIG_MISMATCH) { break; }
+
+ if(mrb_nil_p(blk)) {
+ mrb_assert(mrb_array_p(result));
+ if(m->num_regs == 1) {
+ mrb_ary_push(mrb, result, mrb_str_substr(mrb, self, m->beg[0], m->end[0] - m->beg[0]));
+ } else {
+ mrb_value const elem = mrb_ary_new_capa(mrb, m->num_regs - 1);
+ for(i = 1; i < m->num_regs; ++i) {
+ mrb_ary_push(mrb, elem, mrb_str_substr(mrb, self, m->beg[i], m->end[i] - m->beg[i]));
+ }
+ mrb_ary_push(mrb, result, elem);
+ }
+ } else { // call block
+ mrb_assert(mrb_string_p(result));
+ if(m->num_regs == 1) {
+ mrb_yield(mrb, blk, mrb_str_substr(mrb, self, m->beg[0], m->end[0] - m->beg[0]));
+ } else {
+ mrb_value argv = mrb_ary_new_capa(mrb, m->num_regs - 1);
+ for(i = 1; i < m->num_regs; ++i) {
+ mrb_ary_push(mrb, argv, mrb_str_substr(mrb, self, m->beg[i], m->end[i] - m->beg[i]));
+ }
+ mrb_yield(mrb, blk, argv);
+ }
+ }
+
+ last_end_pos = m->end[0];
+ }
+
+ return result;
+}
+
+// ISO 15.2.10.5.35
+static mrb_value
+string_split(mrb_state* mrb, mrb_value self) {
+ mrb_value pattern = mrb_nil_value(); mrb_int limit = 0;
+ int argc = mrb_get_args(mrb, "|oi", &pattern, &limit);
+
+ if(argc == 0) { // check $; global variable
+ pattern = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$;"));
+ if(!mrb_nil_p(pattern)) { argc = 1; }
+ }
+
+ if(mrb_nil_p(pattern) || mrb_string_p(pattern)) {
+ return mrb_funcall(mrb, self, "string_split", argc, pattern, mrb_fixnum_value(limit));
+ }
+
+ mrb_value const result = mrb_ary_new(mrb);
+ if(RSTRING_LEN(self) == 0) { return result; }
+
+ OnigRegex reg;
+ Data_Get_Struct(mrb, pattern, &mrb_onig_regexp_type, reg);
+ mrb_value const match_value = create_onig_region(mrb, self, pattern);
+ OnigRegion* const match = (OnigRegion*)DATA_PTR(match_value);
+ int last_end_pos = 0, next_match_pos = 0;
+ mrb_int num_matches = 0;
+
+ while (limit <= 0 || (limit - 1) > num_matches) {
+ int i;
+ if(next_match_pos >= RSTRING_LEN(self) ||
+ onig_match_common(mrb, reg, match_value, self, next_match_pos) == ONIG_MISMATCH) { break; }
+
+ if (last_end_pos == match->end[0]) {
+ ++next_match_pos;
+ // Remove this loop if not using UTF-8
+ for (; next_match_pos < RSTRING_LEN(self) && (RSTRING_PTR(self)[next_match_pos] & 0xC0) == 0x80;
+ ++next_match_pos) {}
+ } else {
+ mrb_ary_push(mrb, result, mrb_str_substr(
+ mrb, self, last_end_pos, match->beg[0] - last_end_pos));
+ // If there are captures, add them to the array
+ for (i = 1; i < match->num_regs; ++i) {
+ mrb_ary_push(mrb, result, mrb_str_substr(
+ mrb, self, match->beg[i], match->end[i] - match->beg[i]));
+ }
+ last_end_pos = match->end[0];
+ next_match_pos = last_end_pos;
+ ++num_matches;
+ }
+ }
+ if (last_end_pos <= RSTRING_LEN(self)) {
+ mrb_ary_push(mrb, result, mrb_str_substr(
+ mrb, self, last_end_pos, RSTRING_LEN(self) - last_end_pos));
+ }
+
+ if (limit == 0) { // remove empty trailing elements
+ int count = 0, i;
+ for (i = RARRAY_LEN(result); i > 0; --i) {
+ mrb_assert(mrb_string_p(RARRAY_PTR(result)[i - 1]));
+ if (RSTRING_LEN(RARRAY_PTR(result)[i - 1]) != 0) { break; }
+ else { ++count; }
+ }
+ if(count > 0) {
+ return mrb_ary_new_from_values(mrb, RARRAY_LEN(result) - count, RARRAY_PTR(result));
+ }
+ }
+
+ return result;
+}
+
+// ISO 15.2.10.5.36
+static mrb_value
+string_sub(mrb_state* mrb, mrb_value self) {
+ mrb_value blk, match_expr, replace_expr = mrb_nil_value();
+ int const argc = mrb_get_args(mrb, "&o|S", &blk, &match_expr, &replace_expr);
+
+ if(mrb_string_p(match_expr)) {
+ mrb_value argv[] = { match_expr, replace_expr };
+ return mrb_funcall_with_block(mrb, self, mrb_intern_lit(mrb, "string_sub"), argc, argv, blk);
+ }
+
+ if(!mrb_nil_p(blk) && !mrb_nil_p(replace_expr)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "both block and replace expression must not be passed");
+ }
+
+ OnigRegex reg;
+ Data_Get_Struct(mrb, match_expr, &mrb_onig_regexp_type, reg);
+ mrb_value const result = mrb_str_new(mrb, NULL, 0);
+ mrb_value const match_value = create_onig_region(mrb, self, match_expr);
+ OnigRegion* const match = (OnigRegion*)DATA_PTR(match_value);
+
+ int const onig_result = onig_match_common(mrb, reg, match_value, self, 0);
+ if(onig_result == ONIG_MISMATCH) { return self; }
+
+ mrb_str_cat(mrb, result, RSTRING_PTR(self), match->beg[0]);
+
+ if(mrb_nil_p(blk)) {
+ append_replace_str(mrb, result, replace_expr, self, reg, match);
+ } else {
+ mrb_value const tmp_str = mrb_str_to_str(mrb, mrb_yield(mrb, blk, mrb_str_substr(
+ mrb, self, match->beg[0], match->end[0] - match->beg[0])));
+ mrb_assert(mrb_string_p(tmp_str));
+ mrb_str_concat(mrb, result, tmp_str);
+ }
+
+ int const last_end_pos = match->end[0];
+ mrb_str_cat(mrb, result, RSTRING_PTR(self) + last_end_pos, RSTRING_LEN(self) - last_end_pos);
+
+ return result;
+}
+
+static mrb_value
+onig_regexp_clear_global_variables(mrb_state* mrb, mrb_value self) {
+ mrb_gv_remove(mrb, mrb_intern_lit(mrb, "$~"));
+ mrb_gv_remove(mrb, mrb_intern_lit(mrb, "$&"));
+ mrb_gv_remove(mrb, mrb_intern_lit(mrb, "$`"));
+ mrb_gv_remove(mrb, mrb_intern_lit(mrb, "$'"));
+ mrb_gv_remove(mrb, mrb_intern_lit(mrb, "$+"));
+
+ int idx;
+ for(idx = 1; idx < 10; ++idx) {
+ char const n[] = { '$', '0' + idx };
+ mrb_gv_remove(mrb, mrb_intern(mrb, n, 2));
+ }
+
+ return self;
+}
+
+static mrb_value
+onig_regexp_does_set_global_variables(mrb_state* mrb, mrb_value self) {
+ (void)self;
+ return mrb_obj_iv_get(mrb, (struct RObject*)mrb_class_get(mrb, "OnigRegexp"),
+ mrb_intern_lit(mrb, "@set_global_variables"));
+}
+static mrb_value
+onig_regexp_set_set_global_variables(mrb_state* mrb, mrb_value self) {
+ mrb_value arg;
+ mrb_get_args(mrb, "o", &arg);
+ mrb_value const ret = mrb_bool_value(mrb_bool(arg));
+ mrb_obj_iv_set(mrb, (struct RObject*)mrb_class_get(mrb, "OnigRegexp"),
+ mrb_intern_lit(mrb, "@set_global_variables"), ret);
+ onig_regexp_clear_global_variables(mrb, self);
+ return ret;
+}
+
+// ISO 15.2.15.6.2
+static mrb_value
+onig_regexp_escape(mrb_state* mrb, mrb_value self) {
+ char* str_begin; mrb_args_int str_len;
+ mrb_get_args(mrb, "s", &str_begin, &str_len);
+
+ mrb_value const ret = mrb_str_new(mrb, NULL, 0);
+ char escaped_char = 0;
+ int substr_count = 0;
+ char const* str = str_begin;
+
+ for(; str < (str_begin + str_len); ++str) {
+ switch(*str) {
+ case '\n': escaped_char = 'n'; break;
+ case '\t': escaped_char = 't'; break;
+ case '\r': escaped_char = 'r'; break;
+ case '\f': escaped_char = 'f'; break;
+
+ case ' ':
+ case '#':
+ case '$':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case '-':
+ case '.':
+ case '?':
+ case '[':
+ case '\\':
+ case ']':
+ case '^':
+ case '{':
+ case '|':
+ case '}':
+ escaped_char = *str; break;
+
+ default: ++substr_count; continue;
+ }
+
+ mrb_str_cat(mrb, ret, str - substr_count, substr_count);
+ substr_count = 0;
+
+ char const c[] = { '\\', escaped_char };
+ mrb_str_cat(mrb, ret, c, 2);
+ }
+ mrb_str_cat(mrb, ret, str - substr_count, substr_count);
+ return ret;
+}
+
+void
+mrb_mruby_onig_regexp_gem_init(mrb_state* mrb) {
+ struct RClass *clazz;
+
+ clazz = mrb_define_class(mrb, "OnigRegexp", mrb->object_class);
+ MRB_SET_INSTANCE_TT(clazz, MRB_TT_DATA);
+
+ // enable global variables setting in onig_match_common by default
+ mrb_obj_iv_set(mrb, (struct RObject*)clazz, mrb_intern_lit(mrb, "@set_global_variables"), mrb_true_value());
+
+ mrb_define_const(mrb, clazz, "IGNORECASE", mrb_fixnum_value(ONIG_OPTION_IGNORECASE));
+ mrb_define_const(mrb, clazz, "EXTENDED", mrb_fixnum_value(ONIG_OPTION_EXTEND));
+ mrb_define_const(mrb, clazz, "MULTILINE", mrb_fixnum_value(ONIG_OPTION_MULTILINE));
+ mrb_define_const(mrb, clazz, "SINGLELINE", mrb_fixnum_value(ONIG_OPTION_SINGLELINE));
+ mrb_define_const(mrb, clazz, "FIND_LONGEST", mrb_fixnum_value(ONIG_OPTION_FIND_LONGEST));
+ mrb_define_const(mrb, clazz, "FIND_NOT_EMPTY", mrb_fixnum_value(ONIG_OPTION_FIND_NOT_EMPTY));
+ mrb_define_const(mrb, clazz, "NEGATE_SINGLELINE", mrb_fixnum_value(ONIG_OPTION_NEGATE_SINGLELINE));
+ mrb_define_const(mrb, clazz, "DONT_CAPTURE_GROUP", mrb_fixnum_value(ONIG_OPTION_DONT_CAPTURE_GROUP));
+ mrb_define_const(mrb, clazz, "CAPTURE_GROUP", mrb_fixnum_value(ONIG_OPTION_CAPTURE_GROUP));
+ mrb_define_const(mrb, clazz, "NOTBOL", mrb_fixnum_value(ONIG_OPTION_NOTBOL));
+ mrb_define_const(mrb, clazz, "NOTEOL", mrb_fixnum_value(ONIG_OPTION_NOTEOL));
+#ifdef ONIG_OPTION_POSIX_REGION
+ mrb_define_const(mrb, clazz, "POSIX_REGION", mrb_fixnum_value(ONIG_OPTION_POSIX_REGION));
+#endif
+#ifdef ONIG_OPTION_ASCII_RANGE
+ mrb_define_const(mrb, clazz, "ASCII_RANGE", mrb_fixnum_value(ONIG_OPTION_ASCII_RANGE));
+#endif
+#ifdef ONIG_OPTION_POSIX_BRACKET_ALL_RANGE
+ mrb_define_const(mrb, clazz, "POSIX_BRACKET_ALL_RANGE", mrb_fixnum_value(ONIG_OPTION_POSIX_BRACKET_ALL_RANGE));
+#endif
+#ifdef ONIG_OPTION_WORD_BOUND_ALL_RANGE
+ mrb_define_const(mrb, clazz, "WORD_BOUND_ALL_RANGE", mrb_fixnum_value(ONIG_OPTION_WORD_BOUND_ALL_RANGE));
+#endif
+#ifdef ONIG_OPTION_NEWLINE_CRLF
+ mrb_define_const(mrb, clazz, "NEWLINE_CRLF", mrb_fixnum_value(ONIG_OPTION_NEWLINE_CRLF));
+#endif
+#ifdef ONIG_OPTION_NOTBOS
+ mrb_define_const(mrb, clazz, "NOTBOS", mrb_fixnum_value(ONIG_OPTION_NOTBOS));
+#endif
+#ifdef ONIG_OPTION_NOTEOS
+ mrb_define_const(mrb, clazz, "NOTEOS", mrb_fixnum_value(ONIG_OPTION_NOTEOS));
+#endif
+
+ mrb_define_method(mrb, clazz, "initialize", onig_regexp_initialize, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(2));
+ mrb_define_method(mrb, clazz, "==", onig_regexp_equal, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, clazz, "match", onig_regexp_match, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, clazz, "casefold?", onig_regexp_casefold_p, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, clazz, "options", onig_regexp_options, MRB_ARGS_NONE());
+ mrb_define_method(mrb, clazz, "inspect", onig_regexp_inspect, MRB_ARGS_NONE());
+ mrb_define_method(mrb, clazz, "to_s", onig_regexp_to_s, MRB_ARGS_NONE());
+
+ mrb_define_module_function(mrb, clazz, "escape", onig_regexp_escape, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, clazz, "quote", onig_regexp_escape, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, clazz, "version", onig_regexp_version, MRB_ARGS_NONE());
+ mrb_define_module_function(mrb, clazz, "set_global_variables?", onig_regexp_does_set_global_variables, MRB_ARGS_NONE());
+ mrb_define_module_function(mrb, clazz, "set_global_variables=", onig_regexp_set_set_global_variables, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, clazz, "clear_global_variables", onig_regexp_clear_global_variables, MRB_ARGS_NONE());
+
+ struct RClass* match_data = mrb_define_class(mrb, "OnigMatchData", mrb->object_class);
+ MRB_SET_INSTANCE_TT(clazz, MRB_TT_DATA);
+ mrb_undef_class_method(mrb, match_data, "new");
+
+ // mrb_define_method(mrb, match_data, "==", &match_data_eq);
+ mrb_define_method(mrb, match_data, "[]", &match_data_index, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, match_data, "begin", &match_data_begin, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, match_data, "captures", &match_data_captures, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "end", &match_data_end, MRB_ARGS_REQ(1));
+ // mrb_define_method(mrb, match_data, "eql?", &match_data_eq);
+ // mrb_define_method(mrb, match_data, "hash", &match_data_hash);
+ mrb_define_method(mrb, match_data, "initialize_copy", &match_data_copy, MRB_ARGS_REQ(1));
+ // mrb_define_method(mrb, match_data, "inspect", &match_data_inspect);
+ mrb_define_method(mrb, match_data, "length", &match_data_length, MRB_ARGS_NONE());
+ // mrb_define_method(mrb, match_data, "names", &match_data_names);
+ mrb_define_method(mrb, match_data, "offset", &match_data_offset, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, match_data, "post_match", &match_data_post_match, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "pre_match", &match_data_pre_match, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "regexp", &match_data_regexp, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "size", &match_data_length, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "string", &match_data_string, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "to_a", &match_data_to_a, MRB_ARGS_NONE());
+ mrb_define_method(mrb, match_data, "to_s", &match_data_to_s, MRB_ARGS_NONE());
+ // mrb_define_method(mrb, match_data, "values_at", &match_data_values_at);
+
+ mrb_define_method(mrb, mrb->string_class, "onig_regexp_gsub", &string_gsub, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
+ mrb_define_method(mrb, mrb->string_class, "onig_regexp_sub", &string_sub, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1) | MRB_ARGS_BLOCK());
+ mrb_define_method(mrb, mrb->string_class, "onig_regexp_split", &string_split, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mrb->string_class, "onig_regexp_scan", &string_scan, MRB_ARGS_REQ(1) | MRB_ARGS_BLOCK());
+}
+
+void
+mrb_mruby_onig_regexp_gem_final(mrb_state* mrb) {
+ (void)mrb;
+}
+
+// vim:set et:
diff --git a/web/server/h2o/libh2o/deps/mruby-onig-regexp/test/mruby_onig_regexp.rb b/web/server/h2o/libh2o/deps/mruby-onig-regexp/test/mruby_onig_regexp.rb
new file mode 100644
index 00000000..e70b06fd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-onig-regexp/test/mruby_onig_regexp.rb
@@ -0,0 +1,398 @@
+
+# Constant
+assert("OnigRegexp::CONSTANT") do
+ OnigRegexp::IGNORECASE == 1 and OnigRegexp::EXTENDED == 2 and OnigRegexp::MULTILINE == 4
+end
+
+
+# Class method
+assert('OnigRgexp.compile', '15.2.15.6.2') do
+ assert_equal OnigRegexp.compile('.*'), OnigRegexp.compile('.*')
+end
+
+assert('OnigRegexp.escape', '15.2.15.6.2') do
+ escaping_chars = "\n\t\r\f #$()*+-.?[\\]^{|}"
+ assert_equal '\n\t\r\f\\ \#\$\(\)\*\+\-\.\?\[\\\\\]\^\{\|\}', OnigRegexp.escape(escaping_chars)
+ assert_equal 'cute\nmruby\tcute', OnigRegexp.escape("cute\nmruby\tcute")
+end
+
+assert('OnigRegexp.last_match', '15.2.15.6.3') do
+ OnigRegexp.new('.*') =~ 'ginka'
+ assert_equal 'ginka', OnigRegexp.last_match[0]
+end
+
+assert('OnigRegexp.quote', '15.2.15.6.4') do
+ assert_equal '\n', OnigRegexp.quote("\n")
+end
+
+# Instance method
+assert('OnigRegexp#initialize', '15.2.15.7.1') do
+ OnigRegexp.new(".*") and OnigRegexp.new(".*", OnigRegexp::MULTILINE)
+end
+
+assert('OnigRegexp#initialize_copy', '15.2.15.7.2') do
+ r1 = OnigRegexp.new(".*")
+ r2 = r1.dup
+ assert_equal r1, r2
+ assert_equal 'kawa', r2.match('kawa')[0]
+end
+
+assert("OnigRegexp#==", '15.2.15.7.3') do
+ reg1 = reg2 = OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+")
+ reg3 = OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+")
+ reg4 = OnigRegexp.new("(https://[^/]+)[-a-zA-Z0-9./]+")
+
+ assert_true(reg1 == reg2 && reg1 == reg3 && !(reg1 == reg4))
+
+ assert_false(OnigRegexp.new("a") == "a")
+end
+
+assert("OnigRegexp#===", '15.2.15.7.4') do
+ reg = OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+")
+ assert_true reg === "http://example.com"
+ assert_false reg === "htt://example.com"
+end
+
+assert('OnigRegexp#=~', '15.2.15.7.5') do
+ assert_equal(0) { OnigRegexp.new('.*') =~ 'akari' }
+ assert_equal(nil) { OnigRegexp.new('t') =~ 'akari' }
+end
+
+assert("OnigRegexp#casefold?", '15.2.15.7.6') do
+ assert_false OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+", OnigRegexp::MULTILINE).casefold?
+ assert_true OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+", OnigRegexp::IGNORECASE | OnigRegexp::EXTENDED).casefold?
+ assert_true OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+", OnigRegexp::MULTILINE | OnigRegexp::IGNORECASE).casefold?
+ assert_false OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+").casefold?
+ assert_true OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+", true).casefold?
+end
+
+assert("OnigRegexp#match", '15.2.15.7.7') do
+ reg = OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+")
+ assert_false reg.match("http://masamitsu-murase.12345/hoge.html").nil?
+ assert_nil reg.match("http:///masamitsu-murase.12345/hoge.html")
+end
+
+assert("OnigRegexp#source", '15.2.15.7.8') do
+ str = "(https?://[^/]+)[-a-zA-Z0-9./]+"
+ reg = OnigRegexp.new(str)
+
+ reg.source == str
+end
+
+if OnigRegexp.const_defined? :ASCII_RANGE
+ assert('OnigRegexp#options (no options)') do
+ assert_equal OnigRegexp::ASCII_RANGE | OnigRegexp::POSIX_BRACKET_ALL_RANGE | OnigRegexp::WORD_BOUND_ALL_RANGE, OnigRegexp.new(".*").options
+ end
+
+ assert('OnigRegexp#options (multiline)') do
+ assert_equal OnigRegexp::MULTILINE | OnigRegexp::ASCII_RANGE | OnigRegexp::POSIX_BRACKET_ALL_RANGE | OnigRegexp::WORD_BOUND_ALL_RANGE, OnigRegexp.new(".*", OnigRegexp::MULTILINE).options
+ end
+end
+
+assert("OnigRegexp#inspect") do
+ reg = OnigRegexp.new("(https?://[^/]+)[-a-zA-Z0-9./]+")
+
+ assert_equal '/(https?:\/\/[^\/]+)[-a-zA-Z0-9.\/]+/', reg.inspect
+ assert_equal '/abc\nd\te/mi', OnigRegexp.new("abc\nd\te", OnigRegexp::MULTILINE | OnigRegexp::IGNORECASE).inspect
+ assert_equal '/abc/min', OnigRegexp.new("abc", OnigRegexp::MULTILINE | OnigRegexp::IGNORECASE, "none").inspect
+end
+
+assert("OnigRegexp#to_s") do
+ assert_equal '(?-mix:ab+c)', OnigRegexp.new("ab+c").to_s
+ assert_equal '(?-mix:ab+c)', /ab+c/.to_s
+ assert_equal '(?mx-i:ab+c)', OnigRegexp.new("ab+c", OnigRegexp::MULTILINE | OnigRegexp::EXTENDED).to_s
+ assert_equal '(?mi-x:ab+c)', /ab+c/im.to_s
+ assert_equal '(?mi-x:ab+c)', /ab+c/imn.to_s
+end
+
+assert("OnigRegexp#to_s (composition)") do
+ re1 = OnigRegexp.new("ab+c")
+ re2 = OnigRegexp.new("xy#{re1}z")
+ assert_equal '(?-mix:xy(?-mix:ab+c)z)', re2.to_s
+
+ re3 = OnigRegexp.new("ab.+c", OnigRegexp::MULTILINE)
+ re4 = OnigRegexp.new("xy#{re3}z", OnigRegexp::IGNORECASE)
+ assert_equal '(?i-mx:xy(?m-ix:ab.+c)z)', re4.to_s
+end
+
+# Extended patterns.
+assert("OnigRegexp#match (no flags)") do
+ [
+ [ ".*", "abcd\nefg", "abcd" ],
+ [ "^a.", "abcd\naefg", "ab" ],
+ [ "^a.", "bacd\naefg", "ae" ],
+ [ ".$", "bacd\naefg", "d" ]
+ ].each do |reg, str, result|
+ m = OnigRegexp.new(reg).match(str)
+ assert_equal result, m[0] if assert_false m.nil?
+ end
+end
+
+assert("OnigRegexp#match (multiline)") do
+ patterns = [
+ [ OnigRegexp.new(".*", OnigRegexp::MULTILINE), "abcd\nefg", "abcd\nefg" ]
+ ]
+
+ patterns.all?{ |reg, str, result| reg.match(str)[0] == result }
+end
+
+assert("OnigRegexp#match (ignorecase)") do
+ [
+ [ "aBcD", "00AbcDef", "AbcD" ],
+ [ "0x[a-f]+", "00XaBCdefG", "0XaBCdef" ],
+ [ "0x[^c-f]+", "00XaBCdefG", "0XaB" ]
+ ].each do |reg, str, result|
+ m = OnigRegexp.new(reg, OnigRegexp::IGNORECASE|OnigRegexp::EXTENDED).match(str)
+ assert_equal result, m[0] if assert_false m.nil?
+ end
+end
+
+assert("OnigRegexp#match (none encoding)") do
+ assert_equal 2, /\x82/n =~ "あ"
+end
+
+assert('OnigRegexp.version') do
+ OnigRegexp.version.kind_of? String
+end
+
+def onig_match_data_example
+ OnigRegexp.new('(\w+)(\w)').match('+aaabb-')
+end
+
+assert('OnigMatchData.new') do
+ assert_raise(NoMethodError) { OnigMatchData.new('aaa', 'i') }
+end
+
+assert('OnigMatchData#[]', '15.2.16.3.1') do
+ m = onig_match_data_example
+ assert_equal 'aaabb', m[0]
+ assert_equal 'aaab', m[1]
+ assert_equal 'b', m[2]
+ assert_nil m[3]
+
+ m = OnigRegexp.new('(?<name>\w\w)').match('aba')
+ assert_raise(TypeError) { m[[]] }
+ assert_raise(IndexError) { m['nam'] }
+ assert_equal 'ab', m[:name]
+ assert_equal 'ab', m['name']
+ assert_equal 'ab', m[1]
+
+ m = OnigRegexp.new('(\w) (\w) (\w) (\w)').match('a b c d')
+ assert_equal %w(a b c d), m[1..-1]
+end
+
+assert('OnigMatchData#begin', '15.2.16.3.2') do
+ m = onig_match_data_example
+ assert_equal 1, m.begin(0)
+ assert_equal 1, m.begin(1)
+ assert_raise(IndexError) { m.begin 3 }
+end
+
+assert('OnigMatchData#captures', '15.2.16.3.3') do
+ m = onig_match_data_example
+ assert_equal ['aaab', 'b'], m.captures
+
+ m = OnigRegexp.new('(\w+)(\d)?').match('+aaabb-')
+ assert_equal ['aaabb', nil], m.captures
+end
+
+assert('OnigMatchData#end', '15.2.16.3.4') do
+ m = onig_match_data_example
+ assert_equal 6, m.end(0)
+ assert_equal 5, m.end(1)
+ assert_raise(IndexError) { m.end 3 }
+end
+
+assert('OnigMatchData#initialize_copy', '15.2.16.3.5') do
+ m = onig_match_data_example
+ c = m.dup
+ assert_equal m.to_a, c.to_a
+end
+
+assert('OnigMatchData#length', '15.2.16.3.6') do
+ assert_equal 3, onig_match_data_example.length
+end
+
+assert('OnigMatchData#offset', '15.2.16.3.7') do
+ assert_equal [1, 6], onig_match_data_example.offset(0)
+ assert_equal [1, 5], onig_match_data_example.offset(1)
+end
+
+assert('OnigMatchData#post_match', '15.2.16.3.8') do
+ assert_equal '-', onig_match_data_example.post_match
+end
+
+assert('OnigMatchData#pre_match', '15.2.16.3.9') do
+ assert_equal '+', onig_match_data_example.pre_match
+end
+
+assert('OnigMatchData#size', '15.2.16.3.10') do
+ assert_equal 3, onig_match_data_example.length
+end
+
+assert('OnigMatchData#string', '15.2.16.3.11') do
+ assert_equal '+aaabb-', onig_match_data_example.string
+end
+
+assert('OnigMatchData#to_a', '15.2.16.3.12') do
+ assert_equal ['aaabb', 'aaab', 'b'], onig_match_data_example.to_a
+end
+
+assert('OnigMatchData#to_s', '15.2.16.3.13') do
+ assert_equal 'aaabb', onig_match_data_example.to_s
+end
+
+assert('OnigMatchData#regexp') do
+ assert_equal '(\w+)(\w)', onig_match_data_example.regexp.source
+end
+
+assert('Invalid regexp') do
+ assert_raise(ArgumentError) { OnigRegexp.new '[aio' }
+end
+
+assert('String#onig_regexp_gsub') do
+ test_str = 'hello mruby'
+ assert_equal 'h*ll* mr*by', test_str.onig_regexp_gsub(OnigRegexp.new('[aeiou]'), '*')
+ assert_equal 'h<e>ll<o> mr<u>by', test_str.onig_regexp_gsub(OnigRegexp.new('([aeiou])'), '<\1>')
+ assert_equal 'h e l l o m r u b y ', test_str.onig_regexp_gsub(OnigRegexp.new('\w')) { |v| v + ' ' }
+ assert_equal 'h{e}ll{o} mr{u}by', test_str.onig_regexp_gsub(OnigRegexp.new('(?<hoge>[aeiou])'), '{\k<hoge>}')
+ assert_equal '.h.e.l.l.o. .m.r.u.b.y.', test_str.onig_regexp_gsub(OnigRegexp.new(''), '.')
+ assert_equal " hello\n mruby", "hello\nmruby".onig_regexp_gsub(OnigRegexp.new('^'), ' ')
+ assert_equal "he<l><><l><>o mruby", test_str.onig_regexp_gsub(OnigRegexp.new('(l)'), '<\1><\2>')
+end
+
+assert('String#onig_regexp_scan') do
+ test_str = 'mruby world'
+ assert_equal ['mruby', 'world'], test_str.onig_regexp_scan(OnigRegexp.new('\w+'))
+ assert_equal ['mru', 'by ', 'wor'], test_str.onig_regexp_scan(OnigRegexp.new('...'))
+ assert_equal [['mru'], ['by '], ['wor']], test_str.onig_regexp_scan(OnigRegexp.new('(...)'))
+ assert_equal [['mr', 'ub'], ['y ', 'wo']], test_str.onig_regexp_scan(OnigRegexp.new('(..)(..)'))
+
+ result = []
+ assert_equal test_str, test_str.onig_regexp_scan(OnigRegexp.new('\w+')) { |v| result << "<<#{v}>>" }
+ assert_equal ['<<mruby>>', '<<world>>'], result
+
+ result = ''
+ assert_equal test_str, test_str.onig_regexp_scan(OnigRegexp.new('(.)(.)')) { |x, y| result += y; result += x }
+ assert_equal 'rmbu yowlr', result
+end
+
+assert('String#onig_regexp_sub') do
+ test_str = 'hello mruby'
+ assert_equal 'h*llo mruby', test_str.onig_regexp_sub(OnigRegexp.new('[aeiou]'), '*')
+ assert_equal 'h<e>llo mruby', test_str.onig_regexp_sub(OnigRegexp.new('([aeiou])'), '<\1>')
+ assert_equal 'h ello mruby', test_str.onig_regexp_sub(OnigRegexp.new('\w')) { |v| v + ' ' }
+ assert_equal 'h{e}llo mruby', test_str.onig_regexp_sub(OnigRegexp.new('(?<hoge>[aeiou])'), '{\k<hoge>}')
+end
+
+assert('String#onig_regexp_split') do
+ test_str = 'cute mruby cute'
+ assert_equal ['cute', 'mruby', 'cute'], test_str.onig_regexp_split
+ assert_equal ['cute', 'mruby', 'cute'], test_str.onig_regexp_split(OnigRegexp.new(' '))
+
+ prev_splitter = $;
+ $; = OnigRegexp.new ' \w'
+ assert_equal ['cute', 'ruby', 'ute'], test_str.onig_regexp_split
+ $; = 't'
+ assert_equal ['cu', 'e mruby cu', 'e'], test_str.onig_regexp_split
+ $; = prev_splitter
+
+ assert_equal ['h', 'e', 'l', 'l', 'o'], 'hello'.onig_regexp_split(OnigRegexp.new(''))
+ assert_equal ['h', 'e', 'llo'], 'hello'.onig_regexp_split(OnigRegexp.new(''), 3)
+ assert_equal ['h', 'i', 'd', 'a', 'd'], 'hi dad'.onig_regexp_split(OnigRegexp.new('\s*'))
+
+ test_str = '1, 2, 3, 4, 5,, 6'
+ assert_equal ['1', '2', '3', '4', '5', '', '6'], test_str.onig_regexp_split(OnigRegexp.new(',\s*'))
+
+ test_str = '1,,2,3,,4,,'
+ assert_equal ['1', '', '2', '3', '', '4'], test_str.onig_regexp_split(OnigRegexp.new(','))
+ assert_equal ['1', '', '2', '3,,4,,'], test_str.onig_regexp_split(OnigRegexp.new(','), 4)
+ assert_equal ['1', '', '2', '3', '', '4', '', ''], test_str.onig_regexp_split(OnigRegexp.new(','), -4)
+
+ assert_equal [], ''.onig_regexp_split(OnigRegexp.new(','), -1)
+end
+
+assert('String#index') do
+ assert_equal 0, 'abc'.index('a')
+ assert_nil 'abc'.index('d')
+ assert_equal 3, 'abcabc'.index('a', 1)
+ assert_equal 1, "hello".index(?e)
+
+ assert_equal 0, 'abcabc'.index(/a/)
+ assert_nil 'abc'.index(/d/)
+ assert_equal 3, 'abcabc'.index(/a/, 1)
+ assert_equal 4, "hello".index(/[aeiou]/, -3)
+ assert_equal 3, "regexpindex".index(/e.*x/, 2)
+end
+
+prev_regexp = Regexp
+
+Regexp = OnigRegexp
+
+# global variables
+assert('$~') do
+ m = onig_match_data_example
+ assert_equal m[0], $~[0]
+end
+
+assert('$&') do
+ m = onig_match_data_example
+ assert_equal m[0], $&
+end
+
+assert('$`') do
+ m = onig_match_data_example
+ assert_equal m.pre_match, $`
+end
+
+assert('$\'') do
+ m = onig_match_data_example
+ assert_equal m.post_match, $'
+end
+
+assert('$+') do
+ m = onig_match_data_example
+ assert_equal m[-1], $+
+end
+
+assert('$1 to $9') do
+ onig_match_data_example
+ assert_equal 'aaab', $1
+ assert_equal 'b', $2
+ assert_nil $3
+ assert_nil $4
+ assert_nil $5
+ assert_nil $6
+ assert_nil $7
+ assert_nil $8
+ assert_nil $9
+end
+
+assert('default OnigRegexp.set_global_variables?') do
+ assert_true OnigRegexp.set_global_variables?
+end
+
+assert('change set_global_variables') do
+ m = onig_match_data_example
+ assert_equal m[0], $~[0]
+
+ OnigRegexp.set_global_variables = false
+ assert_false OnigRegexp.set_global_variables?
+
+ # global variables must be cleared when OnigRegexp.set_global_variables gets change
+ assert_nil $~
+
+ onig_match_data_example
+ assert_nil $~
+
+ OnigRegexp.set_global_variables = true
+end
+
+Regexp = Object
+
+assert('OnigRegexp not default') do
+ onig_match_data_example
+ assert_nil $~
+end
+
+Regexp = prev_regexp
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/.gitignore b/web/server/h2o/libh2o/deps/mruby-pack/.gitignore
new file mode 100644
index 00000000..55ef3162
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/.gitignore
@@ -0,0 +1,5 @@
+gem_*
+gem-*
+mrb-*.a
+src/*.o
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/.travis.yml b/web/server/h2o/libh2o/deps/mruby-pack/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/README.md b/web/server/h2o/libh2o/deps/mruby-pack/README.md
new file mode 100644
index 00000000..91addce8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/README.md
@@ -0,0 +1,67 @@
+mruby-pack (pack / unpack)
+=========
+
+mruby-pack provides `Array#pack` and `String#unpack` for mruby.
+
+
+## Installation
+Add the line below into your `build_config.rb`:
+
+```
+ conf.gem :github => 'iij/mruby-pack'
+```
+
+There is no dependency on other mrbgems.
+
+
+## Supported template string
+ - A : arbitrary binary string (space padded, count is width)
+ - a : arbitrary binary string (null padded, count is width)
+ - C : 8-bit unsigned (unsigned char)
+ - c : 8-bit signed (signed char)
+ - D, d: 64-bit float, native format
+ - E : 64-bit float, little endian byte order
+ - e : 32-bit float, little endian byte order
+ - F, f: 32-bit float, native format
+ - G : 64-bit float, network (big-endian) byte order
+ - g : 32-bit float, network (big-endian) byte order
+ - H : hex string (high nibble first)
+ - h : hex string (low nibble first)
+ - I : unsigned integer, native endian (`unsigned int` in C)
+ - i : signed integer, native endian (`int` in C)
+ - L : 32-bit unsigned, native endian (`uint32_t`)
+ - l : 32-bit signed, native endian (`int32_t`)
+ - m : base64 encoded string (see RFC 2045, count is width)
+ - N : 32-bit unsigned, network (big-endian) byte order
+ - n : 16-bit unsigned, network (big-endian) byte order
+ - Q : 64-bit unsigned, native endian (`uint64_t`)
+ - q : 64-bit signed, native endian (`int64_t`)
+ - S : 16-bit unsigned, native endian (`uint16_t`)
+ - s : 16-bit signed, native endian (`int16_t`)
+ - V : 32-bit unsigned, VAX (little-endian) byte order
+ - v : 16-bit unsigned, VAX (little-endian) byte order
+ - Z : same as "a", except that null is added with *
+
+
+## License
+
+Copyright (c) 2012 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-pack/mrbgem.rake
new file mode 100644
index 00000000..2b9dea5b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-pack') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Internet Initiative Japan Inc.'
+
+ spec.cc.include_paths << "#{build.root}/src"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/packtest.rb b/web/server/h2o/libh2o/deps/mruby-pack/packtest.rb
new file mode 100644
index 00000000..e8be7c76
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/packtest.rb
@@ -0,0 +1,154 @@
+# encoding: ascii
+
+# a = Array, s = String, t = Template
+
+def packtest(a, s, t)
+ begin
+ r = a.pack(t)
+ return if r == s
+ puts "#{a.inspect}.pack(#{t.inspect}) -> #{r.inspect} should be #{s.inspect}"
+ rescue => r
+ unless r.is_a? s
+ puts "#{a.inspect}.pack(#{t.inspect}) -> #{r.inspect} should be #{s.inspect}"
+ end
+ end
+end
+
+def unpacktest(a, s, t)
+ r = s.unpack(t)
+ return if r == a
+ puts "#{s.inspect}.unpack(#{t.inspect}) -> #{r.inspect} should be #{a.inspect}"
+end
+
+def pptest(a, s, t)
+ packtest(a, s, t)
+ unpacktest(a, s, t)
+end
+
+pptest [1], "\x01", "C"
+
+packtest [1.1], "\x01", "C"
+packtest [-1], "\xff", "C"
+packtest [1,2], "\x01\x02", "C2"
+#packtest [1], "X", ArgumentError
+
+unpacktest [48, nil], "0", "CC"
+unpacktest [160, -96], "\xa0\xa0", "Cc"
+unpacktest [49, 50, 51], "123", "C*"
+
+pptest [12849], "12", "S"
+unpacktest [nil], "0", "S"
+unpacktest [12849, nil], "123", "SS"
+unpacktest [12849], "123", "S*"
+
+pptest [10000], "\x27\x10", "s>"
+pptest [-10000], "\xd8\xf0", "s>"
+pptest [50000], "\xc3\x50", "S>"
+
+pptest [10000], "\x10\x27", "s<"
+pptest [-10000], "\xf0\xd8", "s<"
+pptest [50000], "\x50\xc3", "S<"
+
+pptest [1000000000], "\x3b\x9a\xca\x00", "l>"
+pptest [-1000000000], "\xc4\x65\x36\x00", "l>"
+
+pptest [1], "\x01\x00\x00\x00", "L<"
+pptest [258], "\x02\x01\x00\x00", "L<"
+pptest [66051], "\x03\x02\x01\x00", "L<"
+pptest [16909060], "\x04\x03\x02\x01", "L<"
+pptest [16909060], "\x01\x02\x03\x04", "L>"
+
+packtest [-1], "\xff\xff\xff\xff", "L<"
+
+pptest [1000000000], "\x00\x00\x00\x00\x3b\x9a\xca\x00", "q>"
+pptest [-1000000000], "\xff\xff\xff\xff\xc4\x65\x36\x00", "q>"
+
+if (2**33).is_a? Fixnum
+ pptest [81985529216486895], "\x01\x23\x45\x67\x89\xab\xcd\xef", "q>"
+ pptest [-1167088121787636991], "\x01\x23\x45\x67\x89\xab\xcd\xef", "q<"
+end
+
+pptest [16909060], "\x01\x02\x03\x04", "N"
+pptest [258], "\x01\x02", "n"
+pptest [32769], "\x80\x01", "n"
+
+pptest [16909060], "\x04\x03\x02\x01", "V"
+pptest [258], "\x02\x01", "v"
+
+packtest [""], "", "m"
+packtest ["a"], "YQ==\n", "m"
+packtest ["ab"], "YWI=\n", "m"
+packtest ["abc"], "YWJj\n", "m"
+packtest ["abcd"], "YWJjZA==\n", "m"
+
+unpacktest [""], "", "m"
+unpacktest ["a"], "YQ==\n", "m"
+unpacktest ["ab"], "YWI=\n", "m"
+unpacktest ["abc"], "YWJj\n", "m"
+unpacktest ["abcd"], "YWJjZA==\n", "m"
+
+packtest [""], "\0", "H"
+packtest ["3"], "0", "H"
+packtest ["34"], "", "H0"
+packtest ["34"], "0", "H"
+packtest ["34"], "4", "H2"
+packtest ["34"], "4\0", "H3"
+packtest ["3456"], "4P", "H3"
+packtest ["34563"], "4V0", "H*"
+packtest ["5a"], "Z", "H*"
+packtest ["5A"], "Z", "H*"
+
+unpacktest [""], "", "H"
+unpacktest [""], "0", "H0"
+unpacktest ["3"], "0", "H"
+unpacktest ["30"], "0", "H2"
+unpacktest ["30"], "0", "H3"
+unpacktest ["303"], "01", "H3"
+unpacktest ["303132"], "012", "H*"
+unpacktest ["3031", 50], "012", "H4C"
+unpacktest ["5a"], "Z", "H*"
+
+packtest [""], "\0", "h"
+packtest ["3"], "\03", "h"
+packtest ["34"], "", "h0"
+packtest ["34"], "\03", "h"
+packtest ["34"], "C", "h2"
+packtest ["34"], "C\0", "h3"
+packtest ["3456"], "C\05", "h3"
+packtest ["34563"], "Ce\03", "h*"
+
+packtest [""], " ", "A"
+unpacktest [""], "", "A"
+pptest ["1"], "1", "A"
+pptest ["1"], "1 ", "A2"
+unpacktest ["1"], "1", "A2"
+unpacktest ["1"], "1 ", "A2"
+unpacktest ["1"], "1\0", "A2"
+packtest ["12"], "1", "A"
+unpacktest ["1"], "12", "A"
+pptest ["123"], "123", "A*"
+packtest ["1","2"], "2", "A0A"
+unpacktest ["","2"], "2", "A0A"
+
+packtest [""], "\0", "a"
+unpacktest [""], "", "a"
+pptest ["1"], "1", "a"
+pptest ["1 "], "1 ", "a2"
+pptest ["1\0"], "1\0", "a2"
+packtest ["1"], "1\0", "a2"
+pptest ["123"], "123", "a*"
+
+packtest [""], "\0", "Z"
+unpacktest [""], "", "Z"
+pptest ["1"], "1", "Z"
+pptest ["1"], "1\0", "Z2"
+pptest ["1 "], "1 ", "Z2"
+pptest ["123"], "123\0", "Z*"
+pptest ["1","2"], "12", "ZZ"
+pptest ["1","2"], "1\0002", "Z*Z"
+unpacktest ["1","3"], "1\00023", "Z3Z"
+
+packtest [1, 2], "\x01\x02", "CyC"
+
+packtest [65], "A", 'U'
+packtest [59411], "\xEE\xA0\x93", 'U'
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/run_test.rb b/web/server/h2o/libh2o/deps/mruby-pack/run_test.rb
new file mode 100644
index 00000000..d9566a2a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/run_test.rb
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+gemname = File.basename(File.dirname(File.expand_path __FILE__))
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+ build_args = ARGV
+ build_args = ['all', 'test'] if build_args.nil? or build_args.empty?
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/src/pack.c b/web/server/h2o/libh2o/deps/mruby-pack/src/pack.c
new file mode 100644
index 00000000..9095ad03
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/src/pack.c
@@ -0,0 +1,1144 @@
+/*
+ ** pack.c - Array#pack, String#unpack
+ */
+
+#include "mruby.h"
+#include "error.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
+#include "mruby/numeric.h"
+#include "mruby/string.h"
+#include "mruby/variable.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+struct tmpl {
+ mrb_value str;
+ int idx;
+};
+
+enum {
+ PACK_DIR_CHAR, /* C */
+ PACK_DIR_SHORT, /* S */
+ PACK_DIR_LONG, /* L */
+ PACK_DIR_QUAD, /* Q */
+ //PACK_DIR_INT, /* i */
+ //PACK_DIR_VAX,
+ PACK_DIR_UTF8, /* U */
+ //PACK_DIR_BER,
+ PACK_DIR_DOUBLE, /* E */
+ PACK_DIR_FLOAT, /* f */
+ PACK_DIR_STR, /* A */
+ PACK_DIR_HEX, /* h */
+ PACK_DIR_BASE64, /* m */
+ PACK_DIR_INVALID
+};
+
+enum {
+ PACK_TYPE_INTEGER,
+ PACK_TYPE_FLOAT,
+ PACK_TYPE_STRING,
+ PACK_TYPE_NONE
+};
+
+#define PACK_FLAG_s 0x00000001 /* native size ("_" "!") */
+#define PACK_FLAG_a 0x00000002 /* null padding ("a") */
+#define PACK_FLAG_Z 0x00000004 /* append nul char ("z") */
+#define PACK_FLAG_SIGNED 0x00000008 /* native size ("_" "!") */
+#define PACK_FLAG_GT 0x00000010 /* big endian (">") */
+#define PACK_FLAG_LT 0x00000020 /* little endian ("<") */
+#define PACK_FLAG_WIDTH 0x00000040 /* "count" is "width" */
+#define PACK_FLAG_LSB 0x00000080 /* LSB / low nibble first */
+#define PACK_FLAG_COUNT2 0x00000100 /* "count" is special... */
+#define PACK_FLAG_LITTLEENDIAN 0x00000200 /* little endian actually */
+
+#define PACK_BASE64_IGNORE 0xff
+#define PACK_BASE64_PADDING 0xfe
+
+static int littleendian = 0;
+
+const static unsigned char base64chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static signed char base64_dec_tab[128];
+
+
+static int
+check_little_endian(void)
+{
+ unsigned int n = 1;
+ return (*(unsigned char *)&n == 1);
+}
+
+static unsigned int
+hex2int(unsigned char ch)
+{
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return 10 + (ch - 'A');
+ else if (ch >= 'a' && ch <= 'f')
+ return 10 + (ch - 'a');
+ else
+ return 0;
+}
+
+static void
+make_base64_dec_tab(void)
+{
+ int i;
+ memset(base64_dec_tab, PACK_BASE64_IGNORE, sizeof(base64_dec_tab));
+ for (i = 0; i < 26; i++)
+ base64_dec_tab['A' + i] = i;
+ for (i = 0; i < 26; i++)
+ base64_dec_tab['a' + i] = i + 26;
+ for (i = 0; i < 10; i++)
+ base64_dec_tab['0' + i] = i + 52;
+ base64_dec_tab['+'] = 62;
+ base64_dec_tab['/'] = 63;
+ base64_dec_tab['='] = PACK_BASE64_PADDING;
+}
+
+static mrb_value
+str_len_ensure(mrb_state *mrb, mrb_value str, int len)
+{
+ int n = RSTRING_LEN(str);
+ if (len > n) {
+ do {
+ n *= 2;
+ } while (len > n);
+ str = mrb_str_resize(mrb, str, n);
+ }
+ return str;
+}
+
+
+static int
+pack_c(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
+{
+ str = str_len_ensure(mrb, str, sidx + 1);
+ RSTRING_PTR(str)[sidx] = mrb_fixnum(o);
+ return 1;
+}
+
+static int
+unpack_c(mrb_state *mrb, const void *src, int srclen, mrb_value ary, unsigned int flags)
+{
+ if (flags & PACK_FLAG_SIGNED)
+ mrb_ary_push(mrb, ary, mrb_fixnum_value(*(signed char *)src));
+ else
+ mrb_ary_push(mrb, ary, mrb_fixnum_value(*(unsigned char *)src));
+ return 1;
+}
+
+static int
+pack_s(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
+{
+ unsigned short n;
+
+ str = str_len_ensure(mrb, str, sidx + 2);
+ n = mrb_fixnum(o);
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+ RSTRING_PTR(str)[sidx+0] = n % 256;
+ RSTRING_PTR(str)[sidx+1] = n / 256;
+ } else {
+ RSTRING_PTR(str)[sidx+0] = n / 256;
+ RSTRING_PTR(str)[sidx+1] = n % 256;
+ }
+ return 2;
+}
+
+static int
+unpack_s(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
+{
+ int n;
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+ n = src[1] * 256 + src[0];
+ } else {
+ n = src[0] * 256 + src[1];
+ }
+ if ((flags & PACK_FLAG_SIGNED) && (n >= 0x8000)) {
+ n -= 0x10000;
+ }
+ mrb_ary_push(mrb, ary, mrb_fixnum_value(n));
+ return 2;
+}
+
+static int
+pack_l(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
+{
+ unsigned long n;
+ str = str_len_ensure(mrb, str, sidx + 4);
+ n = mrb_fixnum(o);
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+ RSTRING_PTR(str)[sidx+0] = n & 0xff;
+ RSTRING_PTR(str)[sidx+1] = n >> 8;
+ RSTRING_PTR(str)[sidx+2] = n >> 16;
+ RSTRING_PTR(str)[sidx+3] = n >> 24;
+ } else {
+ RSTRING_PTR(str)[sidx+0] = n >> 24;
+ RSTRING_PTR(str)[sidx+1] = n >> 16;
+ RSTRING_PTR(str)[sidx+2] = n >> 8;
+ RSTRING_PTR(str)[sidx+3] = n & 0xff;
+ }
+ return 4;
+}
+
+static int
+unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
+{
+ char msg[60];
+ uint32_t ul;
+ mrb_int n;
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+ ul = (uint32_t)src[3] * 256*256*256;
+ ul += (uint32_t)src[2] *256*256;
+ ul += (uint32_t)src[1] *256;
+ ul += (uint32_t)src[0];
+ } else {
+ ul = (uint32_t)src[0] * 256*256*256;
+ ul += (uint32_t)src[1] *256*256;
+ ul += (uint32_t)src[2] *256;
+ ul += (uint32_t)src[3];
+ }
+ if (flags & PACK_FLAG_SIGNED) {
+ int32_t sl = ul;
+ if (!FIXABLE(sl)) {
+ snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %ld", (long)sl);
+ mrb_raise(mrb, E_RANGE_ERROR, msg);
+ }
+ n = sl;
+ } else {
+ if (!POSFIXABLE(ul)) {
+ snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %lu", (unsigned long)ul);
+ mrb_raise(mrb, E_RANGE_ERROR, msg);
+ }
+ n = ul;
+ }
+ mrb_ary_push(mrb, ary, mrb_fixnum_value(n));
+ return 4;
+}
+
+static int
+pack_q(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
+{
+ unsigned long long n;
+ str = str_len_ensure(mrb, str, sidx + 8);
+ n = mrb_fixnum(o);
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+ RSTRING_PTR(str)[sidx+0] = n & 0xff;
+ RSTRING_PTR(str)[sidx+1] = n >> 8;
+ RSTRING_PTR(str)[sidx+2] = n >> 16;
+ RSTRING_PTR(str)[sidx+3] = n >> 24;
+ RSTRING_PTR(str)[sidx+4] = n >> 32;
+ RSTRING_PTR(str)[sidx+5] = n >> 40;
+ RSTRING_PTR(str)[sidx+6] = n >> 48;
+ RSTRING_PTR(str)[sidx+7] = n >> 56;
+ } else {
+ RSTRING_PTR(str)[sidx+0] = n >> 56;
+ RSTRING_PTR(str)[sidx+1] = n >> 48;
+ RSTRING_PTR(str)[sidx+2] = n >> 40;
+ RSTRING_PTR(str)[sidx+3] = n >> 32;
+ RSTRING_PTR(str)[sidx+4] = n >> 24;
+ RSTRING_PTR(str)[sidx+5] = n >> 16;
+ RSTRING_PTR(str)[sidx+6] = n >> 8;
+ RSTRING_PTR(str)[sidx+7] = n & 0xff;
+ }
+ return 8;
+}
+
+static int
+unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
+{
+ char msg[60];
+ uint64_t ull;
+ int i, pos, step;
+ mrb_int n;
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+ pos = 7;
+ step = -1;
+ } else {
+ pos = 0;
+ step = 1;
+ }
+ ull = 0;
+ for (i = 0; i < 8; i++) {
+ ull = ull * 256 + (uint64_t)src[pos];
+ pos += step;
+ }
+ if (flags & PACK_FLAG_SIGNED) {
+ int64_t sll = ull;
+ if (!FIXABLE(sll)) {
+ snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %lld", (long long)sll);
+ mrb_raise(mrb, E_RANGE_ERROR, msg);
+ }
+ n = sll;
+ } else {
+ if (!POSFIXABLE(ull)) {
+ snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %llu", (unsigned long long)ull);
+ mrb_raise(mrb, E_RANGE_ERROR, msg);
+ }
+ n = ull;
+ }
+ mrb_ary_push(mrb, ary, mrb_fixnum_value(n));
+ return 8;
+}
+
+static int
+pack_double(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
+{
+ int i;
+ double d;
+ uint8_t *buffer = (uint8_t *)&d;
+ str = str_len_ensure(mrb, str, sidx + 8);
+ d = mrb_float(o);
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+#ifdef MRB_ENDIAN_BIG
+ for (i = 0; i < 8; ++i) {
+ RSTRING_PTR(str)[sidx + i] = buffer[8 - i - 1];
+ }
+#else
+ memcpy(RSTRING_PTR(str) + sidx, buffer, 8);
+#endif
+ } else {
+#ifdef MRB_ENDIAN_BIG
+ memcpy(RSTRING_PTR(str) + sidx, buffer, 8);
+#else
+ for (i = 0; i < 8; ++i) {
+ RSTRING_PTR(str)[sidx + i] = buffer[8 - i - 1];
+ }
+#endif
+ }
+
+ return 8;
+}
+
+static int
+unpack_double(mrb_state *mrb, const unsigned char * src, int srclen, mrb_value ary, unsigned int flags)
+{
+ int i;
+ double d;
+ uint8_t *buffer = (uint8_t *)&d;
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+#ifdef MRB_ENDIAN_BIG
+ for (i = 0; i < 8; ++i) {
+ buffer[8 - i - 1] = src[i];
+ }
+#else
+ memcpy(buffer, src, 8);
+#endif
+ } else {
+#ifdef MRB_ENDIAN_BIG
+ memcpy(buffer, src, 8);
+#else
+ for (i = 0; i < 8; ++i) {
+ buffer[8 - i - 1] = src[i];
+ }
+#endif
+ }
+ mrb_ary_push(mrb, ary, mrb_float_value(mrb, d));
+
+ return 8;
+}
+
+static int
+pack_float(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int flags)
+{
+ int i;
+ float f;
+ uint8_t *buffer = (uint8_t *)&f;
+ str = str_len_ensure(mrb, str, sidx + 4);
+ f = mrb_float(o);
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+#ifdef MRB_ENDIAN_BIG
+ for (i = 0; i < 4; ++i) {
+ RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1];
+ }
+#else
+ memcpy(RSTRING_PTR(str) + sidx, buffer, 4);
+#endif
+ } else {
+#ifdef MRB_ENDIAN_BIG
+ memcpy(RSTRING_PTR(str) + sidx, buffer, 4);
+#else
+ for (i = 0; i < 4; ++i) {
+ RSTRING_PTR(str)[sidx + i] = buffer[4 - i - 1];
+ }
+#endif
+ }
+
+ return 4;
+}
+
+static int
+unpack_float(mrb_state *mrb, const unsigned char * src, int srclen, mrb_value ary, unsigned int flags)
+{
+ int i;
+ float f;
+ uint8_t *buffer = (uint8_t *)&f;
+
+ if (flags & PACK_FLAG_LITTLEENDIAN) {
+#ifdef MRB_ENDIAN_BIG
+ for (i = 0; i < 4; ++i) {
+ buffer[4 - i - 1] = src[i];
+ }
+#else
+ memcpy(buffer, src, 4);
+#endif
+ } else {
+#ifdef MRB_ENDIAN_BIG
+ memcpy(buffer, src, 4);
+#else
+ for (i = 0; i < 4; ++i) {
+ buffer[4 - i - 1] = src[i];
+ }
+#endif
+ }
+ mrb_ary_push(mrb, ary, mrb_float_value(mrb, f));
+
+ return 4;
+}
+
+static int
+pack_utf8(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, long count, unsigned int flags)
+{
+ char utf8[4];
+ int len;
+
+ unsigned long c = mrb_fixnum(o);
+
+ /* Unicode character */
+ /* from mruby-compiler gem */
+ if (c < 0x80) {
+ utf8[0] = (char)c;
+ len = 1;
+ }
+ else if (c < 0x800) {
+ utf8[0] = (char)(0xC0 | (c >> 6));
+ utf8[1] = (char)(0x80 | (c & 0x3F));
+ len = 2;
+ }
+ else if (c < 0x10000) {
+ utf8[0] = (char)(0xE0 | (c >> 12) );
+ utf8[1] = (char)(0x80 | ((c >> 6) & 0x3F));
+ utf8[2] = (char)(0x80 | ( c & 0x3F));
+ len = 3;
+ }
+ else {
+ utf8[0] = (char)(0xF0 | (c >> 18) );
+ utf8[1] = (char)(0x80 | ((c >> 12) & 0x3F));
+ utf8[2] = (char)(0x80 | ((c >> 6) & 0x3F));
+ utf8[3] = (char)(0x80 | ( c & 0x3F));
+ len = 4;
+ }
+
+ str = str_len_ensure(mrb, str, sidx + len);
+ memcpy(RSTRING_PTR(str) + sidx, utf8, len);
+
+ return len;
+}
+
+static int
+pack_a(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags)
+{
+ int copylen, slen, padlen;
+ char *dptr, *dptr0, pad, *sptr;
+
+ sptr = RSTRING_PTR(src);
+ slen = RSTRING_LEN(src);
+
+ if ((flags & PACK_FLAG_a) || (flags & PACK_FLAG_Z))
+ pad = '\0';
+ else
+ pad = ' ';
+
+ if (count == 0) {
+ return 0;
+ } else if (count == -1) {
+ copylen = slen;
+ padlen = (flags & PACK_FLAG_Z) ? 1 : 0;
+ } else if (count < slen) {
+ copylen = count;
+ padlen = 0;
+ } else {
+ copylen = slen;
+ padlen = count - slen;
+ }
+
+ dst = str_len_ensure(mrb, dst, didx + copylen + padlen);
+ dptr0 = dptr = RSTRING_PTR(dst) + didx;
+ memcpy(dptr, sptr, copylen);
+ dptr += copylen;
+ while (padlen-- > 0) {
+ *dptr++ = pad;
+ }
+
+ return dptr - dptr0;
+}
+
+static int
+unpack_a(mrb_state *mrb, const void *src, int slen, mrb_value ary, long count, unsigned int flags)
+{
+ mrb_value dst;
+ const char *cp, *sptr;
+ long copylen;
+
+ sptr = (const char *)src;
+ if (count != -1 && count < slen) {
+ slen = count;
+ }
+ copylen = slen;
+
+ if (flags & PACK_FLAG_Z) { /* "Z" */
+ if ((cp = (const char *)memchr(sptr, '\0', slen)) != NULL) {
+ copylen = cp - sptr;
+ if (count == -1) {
+ slen = copylen + 1;
+ }
+ }
+ } else if (!(flags & PACK_FLAG_a)) { /* "A" */
+ while (copylen > 0 && (sptr[copylen - 1] == '\0' || isspace(sptr[copylen - 1]))) {
+ copylen--;
+ }
+ }
+
+ dst = mrb_str_new(mrb, sptr, copylen);
+ mrb_ary_push(mrb, ary, dst);
+ return slen;
+}
+
+
+static int
+pack_h(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags)
+{
+ unsigned int a, ashift, b, bshift;
+ int slen;
+ char *dptr, *dptr0, *sptr;
+
+ sptr = RSTRING_PTR(src);
+ slen = RSTRING_LEN(src);
+
+ if (flags & PACK_FLAG_LSB) {
+ ashift = 0;
+ bshift = 4;
+ } else {
+ ashift = 4;
+ bshift = 0;
+ }
+
+ if (count == -1) {
+ count = slen;
+ } else if (slen > count) {
+ slen = count;
+ }
+
+ dst = str_len_ensure(mrb, dst, didx + count);
+ dptr = RSTRING_PTR(dst) + didx;
+
+ dptr0 = dptr;
+ for (; count > 0; count -= 2) {
+ a = b = 0;
+ if (slen > 0) {
+ a = hex2int(*sptr++);
+ slen--;
+ }
+ if (slen > 0) {
+ b = hex2int(*sptr++);
+ slen--;
+ }
+ *dptr++ = (a << ashift) + (b << bshift);
+ }
+
+ return dptr - dptr0;
+}
+
+static int
+unpack_h(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, unsigned int flags)
+{
+ mrb_value dst;
+ int a, ashift, b, bshift;
+ const char *sptr, *sptr0;
+ char *dptr, *dptr0;
+ const char hexadecimal[] = "0123456789abcdef";
+
+ if (flags & PACK_FLAG_LSB) {
+ ashift = 0;
+ bshift = 4;
+ } else {
+ ashift = 4;
+ bshift = 0;
+ }
+
+ sptr = (const char *)src;
+
+ if (count == -1)
+ count = slen * 2;
+
+ dst = mrb_str_new(mrb, NULL, count);
+ dptr = RSTRING_PTR(dst);
+
+ sptr0 = sptr;
+ dptr0 = dptr;
+ while (slen > 0 && count > 0) {
+ a = (*sptr >> ashift) & 0x0f;
+ b = (*sptr >> bshift) & 0x0f;
+ sptr++;
+ slen--;
+
+ *dptr++ = hexadecimal[a];
+ count--;
+
+ if (count > 0) {
+ *dptr++ = hexadecimal[b];
+ count--;
+ }
+ }
+
+ dst = mrb_str_resize(mrb, dst, dptr - dptr0);
+ mrb_ary_push(mrb, ary, dst);
+ return sptr - sptr0;
+}
+
+
+static int
+pack_m(mrb_state *mrb, mrb_value src, mrb_value dst, mrb_int didx, long count, unsigned int flags)
+{
+ mrb_int dstlen;
+ unsigned long l;
+ int column, srclen;
+ char *srcptr, *dstptr, *dstptr0;
+
+ srcptr = RSTRING_PTR(src);
+ srclen = RSTRING_LEN(src);
+
+ if (srclen == 0) /* easy case */
+ return 0;
+
+ if (count != 0 && count < 3) { /* -1, 1 or 2 */
+ count = 45;
+ } else if (count >= 3) {
+ count -= count % 3;
+ }
+
+ dstlen = srclen / 3 * 4;
+ if (count > 0) {
+ dstlen += (srclen / count) + ((srclen % count) == 0 ? 0 : 1);
+ }
+ dst = str_len_ensure(mrb, dst, didx + dstlen);
+ dstptr = RSTRING_PTR(dst) + didx;
+
+ dstptr0 = dstptr;
+ for (column = 3; srclen >= 3; srclen -= 3, column += 3) {
+ l = (unsigned char)*srcptr++ << 16;
+ l += (unsigned char)*srcptr++ << 8;
+ l += (unsigned char)*srcptr++;
+
+ *dstptr++ = base64chars[(l >> 18) & 0x3f];
+ *dstptr++ = base64chars[(l >> 12) & 0x3f];
+ *dstptr++ = base64chars[(l >> 6) & 0x3f];
+ *dstptr++ = base64chars[ l & 0x3f];
+
+ if (column == count) {
+ *dstptr++ = '\n';
+ column = 0;
+ }
+ }
+ if (srclen == 1) {
+ l = (unsigned char)*srcptr++ << 16;
+ *dstptr++ = base64chars[(l >> 18) & 0x3f];
+ *dstptr++ = base64chars[(l >> 12) & 0x3f];
+ *dstptr++ = '=';
+ *dstptr++ = '=';
+ column += 3;
+ } else if (srclen == 2) {
+ l = (unsigned char)*srcptr++ << 16;
+ l += (unsigned char)*srcptr++ << 8;
+ *dstptr++ = base64chars[(l >> 18) & 0x3f];
+ *dstptr++ = base64chars[(l >> 12) & 0x3f];
+ *dstptr++ = base64chars[(l >> 6) & 0x3f];
+ *dstptr++ = '=';
+ column += 3;
+ }
+ if (column > 0 && count > 0) {
+ *dstptr++ = '\n';
+ }
+
+ return dstptr - dstptr0;
+}
+
+static int
+unpack_m(mrb_state *mrb, const void *src, int slen, mrb_value ary, unsigned int flags)
+{
+ mrb_value dst;
+ int dlen;
+ unsigned long l;
+ int i, padding;
+ unsigned char c, ch[4];
+ const char *sptr, *sptr0;
+ char *dptr, *dptr0;
+
+ sptr0 = sptr = (const char *)src;
+
+ dlen = slen / 4 * 3; /* an estimated value - may be shorter */
+ dst = mrb_str_new(mrb, NULL, dlen);
+ dptr0 = dptr = RSTRING_PTR(dst);
+
+ padding = 0;
+ while (slen >= 4) {
+ for (i = 0; i < 4; i++) {
+ do {
+ if (slen-- == 0)
+ goto done;
+ c = *sptr++;
+ if (c >= sizeof(base64_dec_tab))
+ continue;
+ ch[i] = base64_dec_tab[c];
+ if (ch[i] == PACK_BASE64_PADDING) {
+ ch[i] = 0;
+ padding++;
+ }
+ } while (ch[i] == PACK_BASE64_IGNORE);
+ }
+
+ l = (ch[0] << 18) + (ch[1] << 12) + (ch[2] << 6) + ch[3];
+
+ if (padding == 0) {
+ *dptr++ = (l >> 16) & 0xff;
+ *dptr++ = (l >> 8) & 0xff;
+ *dptr++ = l & 0xff;
+ } else if (padding == 1) {
+ *dptr++ = (l >> 16) & 0xff;
+ *dptr++ = (l >> 8) & 0xff;
+ break;
+ } else {
+ *dptr++ = (l >> 16) & 0xff;
+ break;
+ }
+ }
+
+done:
+ dst = mrb_str_resize(mrb, dst, dptr - dptr0);
+ mrb_ary_push(mrb, ary, dst);
+ return sptr - sptr0;
+}
+
+
+static void
+prepare_tmpl(mrb_state *mrb, struct tmpl *tmpl)
+{
+ mrb_get_args(mrb, "S", &tmpl->str);
+ tmpl->idx = 0;
+}
+
+static int
+has_tmpl(const struct tmpl *tmpl)
+{
+ return (tmpl->idx < RSTRING_LEN(tmpl->str));
+}
+
+static void
+read_tmpl(mrb_state *mrb, struct tmpl *tmpl, int *dirp, int *typep, int *sizep, long *countp, unsigned int *flagsp)
+{
+ int ch, dir, t, tlen, type;
+ int size = 0;
+ long count = 1;
+ unsigned int flags = 0;
+ const char *tptr;
+
+ tptr = RSTRING_PTR(tmpl->str);
+ tlen = RSTRING_LEN(tmpl->str);
+
+ t = tptr[tmpl->idx++];
+alias:
+ switch (t) {
+ case 'A':
+ dir = PACK_DIR_STR;
+ type = PACK_TYPE_STRING;
+ flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2;
+ break;
+ case 'a':
+ dir = PACK_DIR_STR;
+ type = PACK_TYPE_STRING;
+ flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2 | PACK_FLAG_a;
+ break;
+ case 'C':
+ dir = PACK_DIR_CHAR;
+ type = PACK_TYPE_INTEGER;
+ size = 1;
+ break;
+ case 'c':
+ dir = PACK_DIR_CHAR;
+ type = PACK_TYPE_INTEGER;
+ size = 1;
+ flags |= PACK_FLAG_SIGNED;
+ break;
+ case 'D': case 'd':
+ dir = PACK_DIR_DOUBLE;
+ type = PACK_TYPE_FLOAT;
+ size = 8;
+ flags |= PACK_FLAG_SIGNED;
+ break;
+ case 'F': case 'f':
+ dir = PACK_DIR_FLOAT;
+ type = PACK_TYPE_FLOAT;
+ size = 4;
+ flags |= PACK_FLAG_SIGNED;
+ break;
+ case 'E':
+ dir = PACK_DIR_DOUBLE;
+ type = PACK_TYPE_FLOAT;
+ size = 8;
+ flags |= PACK_FLAG_SIGNED | PACK_FLAG_LT;
+ break;
+ case 'e':
+ dir = PACK_DIR_FLOAT;
+ type = PACK_TYPE_FLOAT;
+ size = 4;
+ flags |= PACK_FLAG_SIGNED | PACK_FLAG_LT;
+ break;
+ case 'G':
+ dir = PACK_DIR_DOUBLE;
+ type = PACK_TYPE_FLOAT;
+ size = 8;
+ flags |= PACK_FLAG_SIGNED | PACK_FLAG_GT;
+ break;
+ case 'g':
+ dir = PACK_DIR_FLOAT;
+ type = PACK_TYPE_FLOAT;
+ size = 4;
+ flags |= PACK_FLAG_SIGNED | PACK_FLAG_GT;
+ break;
+ case 'H':
+ dir = PACK_DIR_HEX;
+ type = PACK_TYPE_STRING;
+ flags |= PACK_FLAG_COUNT2;
+ break;
+ case 'h':
+ dir = PACK_DIR_HEX;
+ type = PACK_TYPE_STRING;
+ flags |= PACK_FLAG_COUNT2 | PACK_FLAG_LSB;
+ break;
+ case 'I':
+ switch (sizeof(int)) {
+ case 2: t = 'S'; goto alias;
+ case 4: t = 'L'; goto alias;
+ case 8: t = 'Q'; goto alias;
+ default:
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "mruby-pack does not support sizeof(int) == %S", mrb_fixnum_value(sizeof(int)));
+ }
+ break;
+ case 'i':
+ switch (sizeof(int)) {
+ case 2: t = 's'; goto alias;
+ case 4: t = 'l'; goto alias;
+ case 8: t = 'q'; goto alias;
+ default:
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "mruby-pack does not support sizeof(int) == %S", mrb_fixnum_value(sizeof(int)));
+ }
+ break;
+ case 'L':
+ dir = PACK_DIR_LONG;
+ type = PACK_TYPE_INTEGER;
+ size = 4;
+ break;
+ case 'l':
+ dir = PACK_DIR_LONG;
+ type = PACK_TYPE_INTEGER;
+ size = 4;
+ flags |= PACK_FLAG_SIGNED;
+ break;
+ case 'm':
+ dir = PACK_DIR_BASE64;
+ type = PACK_TYPE_STRING;
+ flags |= PACK_FLAG_WIDTH;
+ break;
+ case 'N': /* = "L>" */
+ dir = PACK_DIR_LONG;
+ type = PACK_TYPE_INTEGER;
+ size = 4;
+ flags |= PACK_FLAG_GT;
+ break;
+ case 'n': /* = "S>" */
+ dir = PACK_DIR_SHORT;
+ type = PACK_TYPE_INTEGER;
+ size = 2;
+ flags |= PACK_FLAG_GT;
+ break;
+ case 'Q':
+ dir = PACK_DIR_QUAD;
+ type = PACK_TYPE_INTEGER;
+ size = 8;
+ break;
+ case 'q':
+ dir = PACK_DIR_QUAD;
+ type = PACK_TYPE_INTEGER;
+ size = 8;
+ flags |= PACK_FLAG_SIGNED;
+ break;
+ case 'S':
+ dir = PACK_DIR_SHORT;
+ type = PACK_TYPE_INTEGER;
+ size = 2;
+ break;
+ case 's':
+ dir = PACK_DIR_SHORT;
+ type = PACK_TYPE_INTEGER;
+ size = 2;
+ flags |= PACK_FLAG_SIGNED;
+ break;
+ case 'U':
+ dir = PACK_DIR_UTF8;
+ type = PACK_TYPE_INTEGER;
+ break;
+ case 'V': /* = "L<" */
+ dir = PACK_DIR_LONG;
+ type = PACK_TYPE_INTEGER;
+ size = 4;
+ flags |= PACK_FLAG_LT;
+ break;
+ case 'v': /* = "S<" */
+ dir = PACK_DIR_SHORT;
+ type = PACK_TYPE_INTEGER;
+ size = 2;
+ flags |= PACK_FLAG_LT;
+ break;
+ case 'Z':
+ dir = PACK_DIR_STR;
+ type = PACK_TYPE_STRING;
+ flags |= PACK_FLAG_WIDTH | PACK_FLAG_COUNT2 | PACK_FLAG_Z;
+ break;
+ default:
+ dir = PACK_DIR_INVALID;
+ type = PACK_TYPE_NONE;
+ break;
+ }
+
+ /* read suffix [0-9*_!<>] */
+ while (tmpl->idx < tlen) {
+ ch = tptr[tmpl->idx++];
+ if (isdigit(ch)) {
+ count = ch - '0';
+ while (tmpl->idx < tlen && isdigit(tptr[tmpl->idx])) {
+ count = count * 10 + (tptr[tmpl->idx++] - '0');
+ }
+ continue; /* special case */
+ } else if (ch == '*') {
+ count = -1;
+ } else if (ch == '_' || ch == '!' || ch == '<' || ch == '>') {
+ if (strchr("sSiIlLqQ", t) == NULL) {
+ char ch_str = ch;
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "'%S' allowed only after types sSiIlLqQ", mrb_str_new(mrb, &ch_str, 1));
+ }
+ if (ch == '_' || ch == '!') {
+ flags |= PACK_FLAG_s;
+ } else if (ch == '<') {
+ flags |= PACK_FLAG_LT;
+ } else if (ch == '>') {
+ flags |= PACK_FLAG_GT;
+ }
+ } else {
+ tmpl->idx--;
+ break;
+ }
+ }
+
+ if ((flags & PACK_FLAG_LT) || (!(flags & PACK_FLAG_GT) && littleendian)) {
+ flags |= PACK_FLAG_LITTLEENDIAN;
+ }
+
+ *dirp = dir;
+ *typep = type;
+ *sizep = size;
+ *countp = count;
+ *flagsp = flags;
+}
+
+static mrb_value
+mrb_pack_pack(mrb_state *mrb, mrb_value ary)
+{
+ mrb_value o, result;
+ mrb_int aidx;
+ struct tmpl tmpl;
+ long count;
+ unsigned int flags;
+ int dir, ridx, size, type;
+
+ prepare_tmpl(mrb, &tmpl);
+
+ result = mrb_str_new(mrb, NULL, 128); /* allocate initial buffer */
+ aidx = 0;
+ ridx = 0;
+ while (has_tmpl(&tmpl)) {
+ read_tmpl(mrb, &tmpl, &dir, &type, &size, &count, &flags);
+
+ if (dir == PACK_DIR_INVALID)
+ continue;
+
+ for (; aidx < RARRAY_LEN(ary); aidx++) {
+ if (count == 0 && !(flags & PACK_FLAG_WIDTH))
+ break;
+
+ o = mrb_ary_ref(mrb, ary, aidx);
+ if (type == PACK_TYPE_INTEGER) {
+ if (mrb_float_p(o)) {
+ o = mrb_funcall(mrb, o, "to_i", 0);
+ } else if (!mrb_fixnum_p(o)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into Integer", mrb_class_path(mrb, mrb_obj_class(mrb, o)));
+ }
+ } else if (type == PACK_TYPE_FLOAT) {
+ if (!mrb_float_p(o)) {
+ o = mrb_funcall(mrb, o, "to_f", 0);
+ }
+ } else if (type == PACK_TYPE_STRING) {
+ if (!mrb_string_p(o)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into String", mrb_class_path(mrb, mrb_obj_class(mrb, o)));
+ }
+ }
+
+ switch (dir) {
+ case PACK_DIR_CHAR:
+ ridx += pack_c(mrb, o, result, ridx, flags);
+ break;
+ case PACK_DIR_SHORT:
+ ridx += pack_s(mrb, o, result, ridx, flags);
+ break;
+ case PACK_DIR_LONG:
+ ridx += pack_l(mrb, o, result, ridx, flags);
+ break;
+ case PACK_DIR_QUAD:
+ ridx += pack_q(mrb, o, result, ridx, flags);
+ break;
+ case PACK_DIR_BASE64:
+ ridx += pack_m(mrb, o, result, ridx, count, flags);
+ break;
+ case PACK_DIR_HEX:
+ ridx += pack_h(mrb, o, result, ridx, count, flags);
+ break;
+ case PACK_DIR_STR:
+ ridx += pack_a(mrb, o, result, ridx, count, flags);
+ break;
+ case PACK_DIR_DOUBLE:
+ ridx += pack_double(mrb, o, result, ridx, flags);
+ break;
+ case PACK_DIR_FLOAT:
+ ridx += pack_float(mrb, o, result, ridx, flags);
+ break;
+ case PACK_DIR_UTF8:
+ ridx += pack_utf8(mrb, o, result, ridx, count, flags);
+ break;
+ default:
+ break;
+ }
+ if (dir == PACK_DIR_STR) { /* always consumes 1 entry */
+ aidx++;
+ break;
+ }
+ if (count > 0) {
+ count--;
+ }
+ }
+ }
+
+ mrb_str_resize(mrb, result, ridx);
+ return result;
+}
+
+static mrb_value
+mrb_pack_unpack(mrb_state *mrb, mrb_value str)
+{
+ mrb_value result;
+ struct tmpl tmpl;
+ long count;
+ unsigned int flags;
+ int dir, size, srcidx, srclen, type;
+ const unsigned char *sptr;
+
+ prepare_tmpl(mrb, &tmpl);
+
+ srcidx = 0;
+ srclen = RSTRING_LEN(str);
+
+ result = mrb_ary_new(mrb);
+ while (has_tmpl(&tmpl)) {
+ read_tmpl(mrb, &tmpl, &dir, &type, &size, &count, &flags);
+
+ if (dir == PACK_DIR_INVALID)
+ continue;
+
+ if (flags & PACK_FLAG_COUNT2) {
+ sptr = (const unsigned char *)RSTRING_PTR(str) + srcidx;
+ switch (dir) {
+ case PACK_DIR_HEX:
+ srcidx += unpack_h(mrb, sptr, srclen - srcidx, result, count, flags);
+ break;
+ case PACK_DIR_STR:
+ srcidx += unpack_a(mrb, sptr, srclen - srcidx, result, count, flags);
+ break;
+ }
+ continue;
+ }
+
+ while (count != 0) {
+ if (srclen - srcidx < size) {
+ while (count-- > 0) {
+ mrb_ary_push(mrb, result, mrb_nil_value());
+ }
+ break;
+ }
+
+ sptr = (const unsigned char *)RSTRING_PTR(str) + srcidx;
+ switch (dir) {
+ case PACK_DIR_CHAR:
+ srcidx += unpack_c(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ case PACK_DIR_SHORT:
+ srcidx += unpack_s(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ case PACK_DIR_LONG:
+ srcidx += unpack_l(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ case PACK_DIR_QUAD:
+ srcidx += unpack_q(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ case PACK_DIR_BASE64:
+ srcidx += unpack_m(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ case PACK_DIR_FLOAT:
+ srcidx += unpack_float(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ case PACK_DIR_DOUBLE:
+ srcidx += unpack_double(mrb, sptr, srclen - srcidx, result, flags);
+ break;
+ }
+ if (count > 0) {
+ count--;
+ }
+ }
+ }
+
+ return result;
+}
+
+void
+mrb_mruby_pack_gem_init(mrb_state *mrb)
+{
+ littleendian = check_little_endian();
+ make_base64_dec_tab();
+
+ mrb_define_method(mrb, mrb->array_class, "pack", mrb_pack_pack, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mrb->string_class, "unpack", mrb_pack_unpack, MRB_ARGS_REQ(1));
+}
+
+void
+mrb_mruby_pack_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-pack/test/pack.rb b/web/server/h2o/libh2o/deps/mruby-pack/test/pack.rb
new file mode 100644
index 00000000..5e9932f4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-pack/test/pack.rb
@@ -0,0 +1,147 @@
+# pack & unpack 'm' (base64)
+assert('[""].pack("m")') do
+ ary = ""
+ str = ""
+ [ary].pack("m") == str and
+ str.unpack("m") == [ary]
+end
+
+assert('["\0"].pack("m")') do
+ ary = "\0"
+ str = "AA==\n"
+ [ary].pack("m") == str and
+ str.unpack("m") == [ary]
+end
+
+assert('["\0\0"].pack("m")') do
+ ary = "\0\0"
+ str = "AAA=\n"
+ [ary].pack("m") == str and
+ str.unpack("m") == [ary]
+end
+
+assert('["\0\0\0"].pack("m")') do
+ ary = "\0\0\0"
+ str = "AAAA\n"
+ [ary].pack("m") == str and
+ str.unpack("m") == [ary]
+end
+
+assert('["abc..xyzABC..XYZ"].pack("m")') do
+ ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"].pack("m") == "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n"
+end
+
+assert('"YWJ...".unpack("m") should "abc..xyzABC..XYZ"') do
+ str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n".unpack("m") == [str] and
+ "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWg==\n".unpack("m") == [str]
+end
+
+# pack & unpack 'H'
+assert('["3031"].pack("H*")') do
+ ary = "3031"
+ str = "01"
+ [ary].pack("H*") == str and
+ str.unpack("H*") == [ary]
+end
+
+assert('["10"].pack("H*")') do
+ ary = "10"
+ str = "\020"
+ [ary].pack("H*") == str and
+ str.unpack("H*") == [ary]
+end
+
+assert('[0,1,127,128,255].pack("C*")') do
+ ary = [ 0, 1, 127, 128, 255 ]
+ str = "\x00\x01\x7F\x80\xFF"
+ ary.pack("C*") == str and str.unpack("C*") == ary
+end
+
+# pack "a"
+assert('["abc"].pack("a")') do
+ ["abc"].pack("a") == "a" and
+ ["abc"].pack("a*") == "abc" and
+ ["abc"].pack("a4") == "abc\0"
+end
+
+# upack "a"
+assert('["abc"].pack("a")') do
+ "abc\0".unpack("a4") == ["abc\0"] and
+ "abc ".unpack("a4") == ["abc "]
+end
+
+# pack "A"
+assert('["abc"].pack("A")') do
+ ["abc"].pack("A") == "a" and
+ ["abc"].pack("A*") == "abc" and
+ ["abc"].pack("A4") == "abc "
+end
+
+# upack "A"
+assert('["abc"].pack("A")') do
+ "abc\0".unpack("A4") == ["abc"] and
+ "abc ".unpack("A4") == ["abc"]
+end
+
+# regression tests
+assert('issue #1') do
+ [1, 2].pack("nn") == "\000\001\000\002"
+end
+
+def assert_pack tmpl, packed, unpacked
+ assert_equal packed, unpacked.pack(tmpl)
+ assert_equal unpacked, packed.unpack(tmpl)
+end
+
+PACK_IS_LITTLE_ENDIAN = "\x01\00".unpack('S')[0] == 0x01
+
+assert 'pack float' do
+ assert_pack 'e', "\x00\x00@@", [3.0]
+ assert_pack 'g', "@@\x00\x00", [3.0]
+
+ if PACK_IS_LITTLE_ENDIAN
+ assert_pack 'f', "\x00\x00@@", [3.0]
+ assert_pack 'F', "\x00\x00@@", [3.0]
+ else
+ assert_pack 'f', "@@\x00\x00", [3.0]
+ assert_pack 'F', "@@\x00\x00", [3.0]
+ end
+end
+
+assert 'pack double' do
+ assert_pack 'E', "\x00\x00\x00\x00\x00\x00\b@", [3.0]
+ assert_pack 'G', "@\b\x00\x00\x00\x00\x00\x00", [3.0]
+
+ if PACK_IS_LITTLE_ENDIAN
+ assert_pack 'd', "\x00\x00\x00\x00\x00\x00\b@", [3.0]
+ assert_pack 'D', "\x00\x00\x00\x00\x00\x00\b@", [3.0]
+ else
+ assert_pack 'd', "@\b\x00\x00\x00\x00\x00\x00", [3.0]
+ assert_pack 'D', "@\b\x00\x00\x00\x00\x00\x00", [3.0]
+ end
+end
+
+assert 'pack/unpack "i"' do
+ int_size = [0].pack('i').size
+ raise "pack('i').size is too small (#{int_size})" if int_size < 2
+
+ if PACK_IS_LITTLE_ENDIAN
+ str = "\xC7\xCF" + "\xFF" * (int_size-2)
+ else
+ str = "\xFF" * (int_size-2) + "\xC7\xCF"
+ end
+ assert_pack 'i', str, [-12345]
+end
+
+assert 'pack/unpack "I"' do
+ uint_size = [0].pack('I').size
+ raise "pack('I').size is too small (#{uint_size})" if uint_size < 2
+
+ if PACK_IS_LITTLE_ENDIAN
+ str = "\x39\x30" + "\0" * (uint_size-2)
+ else
+ str = "\0" * (uint_size-2) + "\x39\x30"
+ end
+ assert_pack 'I', str, [12345]
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-require/.gitignore b/web/server/h2o/libh2o/deps/mruby-require/.gitignore
new file mode 100644
index 00000000..ceeb05b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/.gitignore
@@ -0,0 +1 @@
+/tmp
diff --git a/web/server/h2o/libh2o/deps/mruby-require/.travis.yml b/web/server/h2o/libh2o/deps/mruby-require/.travis.yml
new file mode 100644
index 00000000..ffe22728
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/.travis.yml
@@ -0,0 +1,2 @@
+script:
+ - "ruby run_test.rb all test"
diff --git a/web/server/h2o/libh2o/deps/mruby-require/README.md b/web/server/h2o/libh2o/deps/mruby-require/README.md
new file mode 100644
index 00000000..70818ffb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/README.md
@@ -0,0 +1,59 @@
+mruby-require
+=============
+
+"mruby-require" is a mrbgem, provides
+[require](http://docs.ruby-lang.org/ja/2.0.0/class/Kernel.html#M_REQUIRE) and
+[load](http://docs.ruby-lang.org/ja/2.0.0/class/Kernel.html#M_LOAD) for mruby.
+
+### Example:
+
+```Ruby
+# a.rb
+
+require "b"
+
+b = Bclass.new
+p b.method
+```
+```Ruby
+# b.rb
+
+class Bclass
+ def method
+ "BBB"
+ end
+end
+```
+```sh
+% mruby a.rb
+"BBB"
+```
+
+
+### To run the tests:
+
+ ruby run_test.rb
+
+
+## License
+
+Copyright (c) 2013 Internet Initiative Japan Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/web/server/h2o/libh2o/deps/mruby-require/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby-require/mrbgem.rake
new file mode 100644
index 00000000..e95cdb8c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/mrbgem.rake
@@ -0,0 +1,15 @@
+MRuby::Gem::Specification.new('mruby-require') do |spec|
+ spec.license = 'MIT'
+ spec.authors = 'Internet Initiative Japan Inc.'
+
+ spec.add_dependency 'mruby-array-ext'
+ spec.add_dependency 'mruby-dir'
+ spec.add_dependency 'mruby-io'
+# only used for testing?
+# spec.add_dependency 'mruby-tempfile'
+ spec.add_dependency 'mruby-time'
+ spec.add_dependency 'mruby-eval'
+
+ spec.cc.include_paths << "#{build.root}/src"
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby-require/mrblib/require.rb b/web/server/h2o/libh2o/deps/mruby-require/mrblib/require.rb
new file mode 100644
index 00000000..cdf25ace
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/mrblib/require.rb
@@ -0,0 +1,97 @@
+class LoadError < ScriptError; end
+
+begin
+ eval "1", nil
+ def _require_eval_load(*args)
+ self.eval(*args)
+ end
+rescue ArgumentError
+ def _require_eval_load(*args)
+ self.eval(args[0])
+ end
+end
+
+module Kernel
+ def load(path)
+ raise TypeError unless path.class == String
+
+ if File.exist?(path) && File.extname(path) == ".mrb"
+ _load_mrb_file path
+ elsif File.exist?(path)
+ # _load_rb_str File.open(path).read.to_s, path
+ _require_eval_load File.open(path).read.to_s, nil, path
+ else
+ raise LoadError.new "File not found -- #{path}"
+ end
+
+ true
+ end
+
+ def require(path)
+ raise TypeError unless path.class == String
+
+ # require method can load .rb, .mrb or without-ext filename only.
+ unless ["", ".rb", ".mrb"].include? File.extname(path)
+ raise LoadError.new "cannot load such file -- #{path}"
+ end
+
+ filenames = []
+ if File.extname(path).size == 0
+ filenames << "#{path}.rb"
+ filenames << "#{path}.mrb"
+ else
+ filenames << path
+ end
+
+ dir = nil
+ filename = nil
+ if ['/', '.'].include? path[0]
+ path0 = filenames.find do |fname|
+ File.file?(fname) && File.exist?(fname)
+ end
+ else
+ dir = ($LOAD_PATH || []).find do |dir0|
+ filename = filenames.find do |fname|
+ path0 = File.join dir0, fname
+ File.file?(path0) && File.exist?(path0)
+ end
+ end
+ path0 = dir && filename ? File.join(dir, filename) : nil
+ end
+
+ if path0 && File.exist?(path0) && File.file?(path0)
+ __require__ path0
+ else
+ raise LoadError.new "cannot load such file -- #{path}"
+ end
+ end
+
+ def __require__(realpath)
+ raise LoadError.new "File not found -- #{realpath}" unless File.exist? realpath
+ $" ||= []
+ $__mruby_loading_files__ ||= []
+
+ # already required
+ return false if ($" + $__mruby_loading_files__).include?(realpath)
+
+ $__mruby_loading_files__ << realpath
+ load realpath
+ $" << realpath
+ $__mruby_loading_files__.delete realpath
+
+ true
+ end
+end
+
+
+$LOAD_PATH ||= []
+$LOAD_PATH << '.'
+
+if Object.const_defined?(:ENV)
+ $LOAD_PATH.unshift(*ENV['MRBLIB'].split(':')) unless ENV['MRBLIB'].nil?
+end
+
+$LOAD_PATH.uniq!
+
+$" ||= []
+$__mruby_loading_files__ ||= []
diff --git a/web/server/h2o/libh2o/deps/mruby-require/run_test.rb b/web/server/h2o/libh2o/deps/mruby-require/run_test.rb
new file mode 100644
index 00000000..2a99a9dd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/run_test.rb
@@ -0,0 +1,29 @@
+#!/usr/bin/env ruby
+#
+# mrbgems test runner
+#
+
+if __FILE__ == $0
+ repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
+
+ build_args = ARGV
+
+ Dir.mkdir 'tmp' unless File.exist?('tmp')
+ unless File.exist?(dir)
+ system "git clone #{repository} #{dir}"
+ end
+
+ exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+
+ conf.gem :core => 'mruby-eval'
+ conf.gem :git => 'https://github.com/iij/mruby-io.git'
+ conf.gem :git => 'https://github.com/iij/mruby-dir.git'
+ conf.gem :git => 'https://github.com/iij/mruby-tempfile.git'
+
+ conf.gem File.expand_path(File.dirname(__FILE__))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-require/src/require.c b/web/server/h2o/libh2o/deps/mruby-require/src/require.c
new file mode 100644
index 00000000..0f48c037
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/src/require.c
@@ -0,0 +1,208 @@
+#if !(defined(_WIN32) || defined(_WIN64))
+#include <err.h>
+#endif
+#include <fcntl.h>
+#include <setjmp.h>
+#include <unistd.h>
+
+#include "mruby.h"
+#include "mruby/compile.h"
+#include "mruby/dump.h"
+#include "mruby/string.h"
+#include "mruby/proc.h"
+
+#include "opcode.h"
+#include "error.h"
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define E_LOAD_ERROR (mrb_class_get(mrb, "LoadError"))
+
+#if MRUBY_RELEASE_NO < 10000
+mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);
+#define mrb_yield_with_class mrb_yield_internal
+#endif
+
+#if defined(_WIN32) || defined(_WIN64)
+ #include <windows.h>
+ int mkstemp(char *template)
+ {
+ DWORD pathSize;
+ char pathBuffer[1000];
+ char tempFilename[MAX_PATH];
+ UINT uniqueNum;
+ pathSize = GetTempPath(1000, pathBuffer);
+ if (pathSize < 1000) { pathBuffer[pathSize] = 0; }
+ else { pathBuffer[0] = 0; }
+ uniqueNum = GetTempFileName(pathBuffer, template, 0, tempFilename);
+ if (uniqueNum == 0) return -1;
+ strncpy(template, tempFilename, MAX_PATH);
+ return open(tempFilename, _O_RDWR|_O_BINARY);
+ }
+#endif
+
+static void
+replace_stop_with_return(mrb_state *mrb, mrb_irep *irep)
+{
+ if (irep->iseq[irep->ilen - 1] == MKOP_A(OP_STOP, 0)) {
+ irep->iseq = mrb_realloc(mrb, irep->iseq, (irep->ilen + 1) * sizeof(mrb_code));
+ irep->iseq[irep->ilen - 1] = MKOP_A(OP_LOADNIL, 0);
+ irep->iseq[irep->ilen] = MKOP_AB(OP_RETURN, 0, OP_R_NORMAL);
+ irep->ilen++;
+ }
+}
+
+static int
+compile_rb2mrb(mrb_state *mrb0, const char *code, int code_len, const char *path, FILE* tmpfp)
+{
+ mrb_state *mrb = mrb_open();
+ mrb_value result;
+ mrbc_context *c;
+ int ret = -1;
+ int debuginfo = 1;
+ mrb_irep *irep;
+
+ c = mrbc_context_new(mrb);
+ c->no_exec = 1;
+ if (path != NULL) {
+ mrbc_filename(mrb, c, path);
+ }
+
+ result = mrb_load_nstring_cxt(mrb, code, code_len, c);
+ if (mrb_undef_p(result)) {
+ mrbc_context_free(mrb, c);
+ mrb_close(mrb);
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
+
+ irep = mrb_proc_ptr(result)->body.irep;
+ ret = mrb_dump_irep_binary(mrb, irep, debuginfo, tmpfp);
+
+ mrbc_context_free(mrb, c);
+ mrb_close(mrb);
+
+ return ret;
+}
+
+static void
+eval_load_irep(mrb_state *mrb, mrb_irep *irep)
+{
+ int ai;
+ struct RProc *proc;
+
+ replace_stop_with_return(mrb, irep);
+ proc = mrb_proc_new(mrb, irep);
+ proc->target_class = mrb->object_class;
+
+ ai = mrb_gc_arena_save(mrb);
+ mrb_yield_with_class(mrb, mrb_obj_value(proc), 0, NULL, mrb_top_self(mrb), mrb->object_class);
+ mrb_gc_arena_restore(mrb, ai);
+}
+
+static mrb_value
+mrb_require_load_rb_str(mrb_state *mrb, mrb_value self)
+{
+ char *path_ptr = NULL;
+#if defined(_WIN32) || defined(_WIN64)
+ char tmpname[MAX_PATH] = "tmp.XXXXXXXX";
+#else
+ char tmpname[] = "tmp.XXXXXXXX";
+#endif
+ mode_t mask;
+ FILE *tmpfp = NULL;
+ int fd = -1, ret;
+ mrb_irep *irep;
+ mrb_value code, path = mrb_nil_value();
+
+ mrb_get_args(mrb, "S|S", &code, &path);
+ if (!mrb_string_p(path)) {
+ path = mrb_str_new_cstr(mrb, "-");
+ }
+ path_ptr = mrb_str_to_cstr(mrb, path);
+
+ mask = umask(077);
+ fd = mkstemp(tmpname);
+ if (fd == -1) {
+ mrb_sys_fail(mrb, "can't create mkstemp() at mrb_require_load_rb_str");
+ }
+ umask(mask);
+
+ tmpfp = fdopen(fd, "r+");
+ if (tmpfp == NULL) {
+ close(fd);
+ mrb_sys_fail(mrb, "can't open temporay file at mrb_require_load_rb_str");
+ }
+
+ ret = compile_rb2mrb(mrb, RSTRING_PTR(code), RSTRING_LEN(code), path_ptr, tmpfp);
+ if (ret != MRB_DUMP_OK) {
+ fclose(tmpfp);
+ remove(tmpname);
+ mrb_raisef(mrb, E_LOAD_ERROR, "can't load file -- %S", path);
+ return mrb_nil_value();
+ }
+
+ rewind(tmpfp);
+ irep = mrb_read_irep_file(mrb, tmpfp);
+ fclose(tmpfp);
+ remove(tmpname);
+
+ if (irep) {
+ eval_load_irep(mrb, irep);
+ } else if (mrb->exc) {
+ // fail to load
+ longjmp(*(jmp_buf*)mrb->jmp, 1);
+ } else {
+ mrb_raisef(mrb, E_LOAD_ERROR, "can't load file -- %S", path);
+ return mrb_nil_value();
+ }
+
+ return mrb_true_value();
+}
+
+static mrb_value
+mrb_require_load_mrb_file(mrb_state *mrb, mrb_value self)
+{
+ char *path_ptr = NULL;
+ FILE *fp = NULL;
+ mrb_irep *irep;
+ mrb_value path;
+
+ mrb_get_args(mrb, "S", &path);
+ path_ptr = mrb_str_to_cstr(mrb, path);
+
+ fp = fopen(path_ptr, "rb");
+ if (fp == NULL) {
+ mrb_raisef(mrb, E_LOAD_ERROR, "can't open file -- %S", path);
+ }
+
+ irep = mrb_read_irep_file(mrb, fp);
+ fclose(fp);
+
+ if (irep) {
+ eval_load_irep(mrb, irep);
+ } else if (mrb->exc) {
+ // fail to load
+ longjmp(*(jmp_buf*)mrb->jmp, 1);
+ } else {
+ mrb_raisef(mrb, E_LOAD_ERROR, "can't load file -- %S", path);
+ return mrb_nil_value();
+ }
+
+ return mrb_true_value();
+}
+
+void
+mrb_mruby_require_gem_init(mrb_state *mrb)
+{
+ struct RClass *krn;
+ krn = mrb->kernel_module;
+
+ mrb_define_method(mrb, krn, "_load_rb_str", mrb_require_load_rb_str, MRB_ARGS_ANY());
+ mrb_define_method(mrb, krn, "_load_mrb_file", mrb_require_load_mrb_file, MRB_ARGS_REQ(1));
+}
+
+void
+mrb_mruby_require_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby-require/test/d/required.rb b/web/server/h2o/libh2o/deps/mruby-require/test/d/required.rb
new file mode 100644
index 00000000..d6218cd0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/test/d/required.rb
@@ -0,0 +1,19 @@
+# global variables
+$gvar0 = 1
+$gvar1 = 1
+
+# toplevel local variables
+lvar0 = 1
+lvar1 = 1
+
+# define a procedure
+def proc0
+ :proc0
+end
+
+# define a new method of an existing class.
+class MrubyRequireClass
+ def foo
+ :foo
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-require/test/require.rb b/web/server/h2o/libh2o/deps/mruby-require/test/require.rb
new file mode 100644
index 00000000..95e1ef02
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/test/require.rb
@@ -0,0 +1,28 @@
+assert("Kernel.require") do
+ # see d/required.rb
+ $gvar1 = 0
+ lvar1 = 0
+ class MrubyRequireClass; end
+
+ assert_true require(File.join(File.dirname(__FILE__), "d", "required.rb"))
+
+ # Kernel.require can create a global variable
+ assert_equal 1, $gvar0
+
+ # Kernel.require can change value of a global variable
+ assert_equal 1, $gvar1
+
+ # Kernel.require cannot create a local variable
+ assert_raise(NoMethodError) do
+ lvar0
+ end
+
+ # Kernel.require cannot change value of a local variable
+ assert_equal 0, lvar1
+
+ # Kernel.require can define a toplevel procedure
+ assert_equal :proc0, proc0
+
+ # Kernel.require can add a method to an existing class
+ assert_equal :foo, MrubyRequireClass.new.foo
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-require/test/test.rb b/web/server/h2o/libh2o/deps/mruby-require/test/test.rb
new file mode 100644
index 00000000..0886cabe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/test/test.rb
@@ -0,0 +1,34 @@
+$" = [] # init
+
+assert "Kernel#_load_rb_str" do
+ assert_equal true, self.methods.include?(:_load_rb_str)
+ assert_equal false, Object.const_defined?(:LOAD_RB_STR_TEST)
+ _load_rb_str("LOAD_RB_STR_TEST = 1")
+ assert_equal true, Object.const_defined?(:LOAD_RB_STR_TEST)
+end
+
+assert "$LOAD_PATH check" do
+ assert_equal Array, $LOAD_PATH.class
+end
+
+assert '$" check' do
+ assert_equal [], $"
+end
+
+assert('load - error check') do
+ assert_raise TypeError, "load(nil) should raise TypeError" do
+ load nil
+ end
+ assert_raise LoadError, "load('notfound') should raise LoadError" do
+ load 'notfound'
+ end
+end
+
+assert('require - error check') do
+ assert_raise TypeError, "require(nil) should raise TypeError" do
+ require nil
+ end
+ assert_raise LoadError, "require('notfound') should raise LoadError" do
+ require "notfound"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby-require/test/test2.rb b/web/server/h2o/libh2o/deps/mruby-require/test/test2.rb
new file mode 100644
index 00000000..b66b9fdf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/test/test2.rb
@@ -0,0 +1,139 @@
+$dir = File.join(Dir.tmpdir, "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}")
+
+def test_setup
+ Dir.mkdir($dir) unless File.exist?($dir)
+
+ File.open(File.join($dir, "test.rb"), "w") do |fp|
+ fp.puts "$require_test_variable = 123"
+ end
+
+ File.open(File.join($dir, "test_dir.rb"), "w") do |fp|
+ fp.puts "$test_dir = 'test_dir'"
+ end
+ Dir.mkdir(File.join($dir, "test_dir"))
+ File.open(File.join($dir, "test_dir", "test_dir.rb"), "w") do |fp|
+ fp.puts "$test_dir2 = 'test_dir/test_dir'"
+ end
+
+ File.open(File.join($dir, "test_conf.conf"), "w") do |fp|
+ fp.puts "$test_conf = 'test_conf'"
+ end
+
+ File.open(File.join($dir, "empty.rb"), "w")
+
+ test_reset
+end
+
+def test_reset
+ $require_test_variable = nil
+ $test_dir = nil
+ $test_dir2 = nil
+ $test_conf = nil
+ $LOAD_PATH = [$dir]
+ $" = []
+end
+
+def remove_file_recursive(path)
+ if File.directory? path
+ Dir.entries(path).each do |entry|
+ next if ['.', '..'].include?(entry)
+ remove_file_recursive File.join(path, entry)
+ end
+ Dir.unlink path
+ else
+ File.unlink path
+ end
+end
+
+def test_cleanup
+ if $dir && File.exist?($dir)
+ remove_file_recursive $dir
+ end
+end
+
+#####
+test_setup
+#####
+
+assert("require 'test' should be success") do
+ test_reset
+
+ assert_true require("test"), "require returns true when success"
+ assert_equal [File.join($dir, "test.rb")], $"
+ assert_equal 123, $require_test_variable
+ $require_test_variable = 789
+ assert_false require("test"), "2nd require should returns false"
+ assert_equal 789, $require_test_variable
+
+ test_reset
+
+ assert_true require("test.rb"), "require should be success with '.rb'"
+ assert_equal [File.join($dir, "test.rb")], $"
+end
+
+assert("require with absolute path should be success") do
+ test_reset
+ assert_true require(File.join($dir, "test"))
+ assert_equal [File.join($dir, "test.rb")], $"
+
+ test_reset
+ assert_true require(File.join($dir, "test.rb"))
+ assert_equal [File.join($dir, "test.rb")], $"
+end
+
+assert("require with absolute path && empty load_path") do
+ test_reset
+ $LOAD_PATH = []
+
+ assert_raise LoadError, "cannot load test.rb" do
+ require "test"
+ end
+ assert_equal true, require(File.join($dir, "test"))
+end
+
+assert("require 'test_dir' should be success") do
+ test_reset
+
+ assert_true require("test_dir"), "require 'test_dir' should be load 'test_dir.rb'"
+ assert_equal [File.join($dir, "test_dir.rb")], $"
+ assert_true require("test_dir/test_dir"), "require 'test_dir/test_dir' should be success"
+ assert_equal 'test_dir/test_dir', $test_dir2
+end
+
+assert("require 'test_conf' should be fail") do
+ test_reset
+
+ assert_raise LoadError, "require 'test_conf.conf' should be fail" do
+ require("test_conf.conf")
+ end
+ assert_raise LoadError, "require method can't load *.conf" do
+ require File.join($dir, "test_conf.conf")
+ end
+end
+
+assert("require 'empty' should be success") do
+ test_reset
+
+ assert_true require("empty")
+ assert_equal 0, File.size(File.join($dir, "empty.rb"))
+end
+
+assert("load 'test.rb' should be success") do
+ test_reset
+
+ assert_true load(File.join($dir, "test.rb"))
+ assert_equal 123, $require_test_variable
+ assert_true $".empty?
+end
+
+assert("load 'test_conf.conf' should be success") do
+ test_reset
+
+ assert_equal true, load(File.join($dir, "test_conf.conf"))
+ assert_equal "test_conf", $test_conf
+end
+
+
+#####
+test_cleanup
+#####
diff --git a/web/server/h2o/libh2o/deps/mruby-require/test/test_context.rb b/web/server/h2o/libh2o/deps/mruby-require/test/test_context.rb
new file mode 100644
index 00000000..00117474
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/test/test_context.rb
@@ -0,0 +1,33 @@
+$dir = File.join(Dir.tmpdir, "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}")
+
+def test_setup
+ Dir.mkdir($dir) unless File.exist?($dir)
+
+ File.open(File.join($dir, "foo.rb"), "w") do |f|
+ f.puts "$require_context = self"
+ end
+end
+
+def test_cleanup
+ if $dir && File.exist?($dir)
+ Dir.entries($dir).each do |e|
+ next if ['.', '..'].include? e
+ File.unlink File.join($dir,e)
+ end
+ Dir.unlink $dir
+ end
+end
+
+
+#####
+test_setup
+#####
+
+assert("require context") do
+ require File.join($dir, 'foo.rb')
+ assert_equal self, $require_context
+end
+
+#####
+test_cleanup
+#####
diff --git a/web/server/h2o/libh2o/deps/mruby-require/test/test_nest_loop.rb b/web/server/h2o/libh2o/deps/mruby-require/test/test_nest_loop.rb
new file mode 100644
index 00000000..c5a4b18b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-require/test/test_nest_loop.rb
@@ -0,0 +1,58 @@
+$dir = File.join(Dir.tmpdir, "mruby-require-test-#{Time.now.to_i}.#{Time.now.usec}")
+
+def test_setup
+ Dir.mkdir($dir)
+
+ File.open(File.join($dir, "loop1.rb"), "w") do |fp|
+ fp.puts "require 'loop2.rb'"
+ fp.puts "$loop1 = 'loop1'"
+ end
+ File.open(File.join($dir, "loop2.rb"), "w") do |fp|
+ fp.puts "require 'loop1.rb'"
+ fp.puts "$loop2 = 'loop2'"
+ end
+
+ $require_test_count = 10
+ (1..$require_test_count-1).each do |i|
+ File.open(File.join($dir, "#{i+1}.rb"), "w") do |fp|
+ fp.puts "require '#{i}'"
+ fp.puts "s = 0"
+ (0..100).each{|num| fp.puts "s += #{num}" }
+ end
+ end
+ File.open(File.join($dir, "1.rb"), "w") do |fp|
+ fp.puts "$require_test_0 = 123"
+ end
+
+ $LOAD_PATH = [$dir]
+end
+
+def test_cleanup
+ if $dir && File.exist?($dir)
+ Dir.entries($dir).each do |e|
+ next if ['.', '..'].include? e
+ File.unlink File.join($dir,e)
+ end
+ Dir.unlink $dir
+ end
+end
+
+#####
+test_setup
+#####
+
+assert("require loop check") do
+ require 'loop1'
+ assert_equal 'loop1', $loop1
+ assert_equal 'loop2', $loop2
+end
+
+assert("require nest") do
+ before = $".size
+ require "#{$require_test_count}"
+ assert_equal before + $require_test_count, $".size
+end
+
+#####
+test_cleanup
+#####
diff --git a/web/server/h2o/libh2o/deps/mruby/.gitignore b/web/server/h2o/libh2o/deps/mruby/.gitignore
new file mode 100644
index 00000000..4af3005e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/.gitignore
@@ -0,0 +1,26 @@
+# /
+*.bak
+*.d
+*.o
+/benchmark/**/*.dat
+/benchmark/*.pdf
+/benchmark/*.png
+*.orig
+*.pdb
+*.rej
+*.sav
+*.swp
+*.tmp
+*~
+.DS_Store
+.ccmalloc
+.svn
+/.git
+cscope.out
+tags
+/src/y.tab.c
+/bin
+/build
+/mruby-source-*.gem
+doc/api
+.yardoc
diff --git a/web/server/h2o/libh2o/deps/mruby/.gitlab-ci.yml b/web/server/h2o/libh2o/deps/mruby/.gitlab-ci.yml
new file mode 100644
index 00000000..8f417923
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/.gitlab-ci.yml
@@ -0,0 +1,3214 @@
+---
+stages:
+- pretest
+- test
+pretest:
+ stage: pretest
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.1
+ tags:
+ - linux
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ script: "./minirake all test"
+Test gcc-4.7 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.7 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc47_0.7
+ variables:
+ CC: gcc-4.7
+ CXX: g++-4.7
+ LD: gcc-4.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.8 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc48_0.7
+ variables:
+ CC: gcc-4.8
+ CXX: g++-4.8
+ LD: gcc-4.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-4.9 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc49_0.7
+ variables:
+ CC: gcc-4.9
+ CXX: g++-4.9
+ LD: gcc-4.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-5 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc5_0.7
+ variables:
+ CC: gcc-5
+ CXX: g++-5
+ LD: gcc-5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test gcc-6 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:gcc6_0.7
+ variables:
+ CC: gcc-6
+ CXX: g++-6
+ LD: gcc-6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.5 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang35_0.7
+ variables:
+ CC: clang-3.5
+ CXX: clang++-3.5
+ LD: clang-3.5
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.6 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang36_0.7
+ variables:
+ CC: clang-3.6
+ CXX: clang++-3.6
+ LD: clang-3.6
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.7 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang37_0.7
+ variables:
+ CC: clang-3.7
+ CXX: clang++-3.7
+ LD: clang-3.7
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.8 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang38_0.7
+ variables:
+ CC: clang-3.8
+ CXX: clang++-3.8
+ LD: clang-3.8
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 32bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-m32 -DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: "-m32"
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_int16_nan:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_int16_nan_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_INT16=1 -DMRB_NAN_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_float:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_float_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_float_int16:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_float_int16_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT16=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_float_int64:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
+Test clang-3.9 64bit_float_int64_utf8:
+ stage: test
+ image: registry.gitlab.com/dabroz/mruby:clang39_0.7
+ variables:
+ CC: clang-3.9
+ CXX: clang++-3.9
+ LD: clang-3.9
+ CFLAGS: "-DMRB_USE_FLOAT=1 -DMRB_INT64=1 -DMRB_WORD_BOXING=1 -DMRB_UTF8_STRING=1"
+ LDFLAGS: ''
+ script: env; ./minirake --verbose all test
diff --git a/web/server/h2o/libh2o/deps/mruby/.travis.yml b/web/server/h2o/libh2o/deps/mruby/.travis.yml
new file mode 100644
index 00000000..8d201515
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/.travis.yml
@@ -0,0 +1,18 @@
+language: c
+
+sudo: false
+
+matrix:
+ include:
+ - os: linux
+ sudo: 9000
+ - os: osx
+ osx_image: xcode7.1
+
+addons:
+ apt:
+ packages:
+ - gperf
+
+env: MRUBY_CONFIG=travis_config.rb
+script: "./minirake all test"
diff --git a/web/server/h2o/libh2o/deps/mruby/.yardopts b/web/server/h2o/libh2o/deps/mruby/.yardopts
new file mode 100644
index 00000000..27f6d59a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/.yardopts
@@ -0,0 +1,17 @@
+--markup markdown
+--plugin mruby
+--plugin coderay
+--output-dir doc/api
+
+src/**/*.c
+mrblib/**/*.rb
+include/**/*.h
+
+mrbgems/*/src/**/*.c
+mrbgems/*/mrblib/**/*.rb
+mrbgems/*/include/**/*.h
+-
+AUTHORS
+MITL
+CONTRIBUTING.md
+doc/guides/*.md
diff --git a/web/server/h2o/libh2o/deps/mruby/AUTHORS b/web/server/h2o/libh2o/deps/mruby/AUTHORS
new file mode 100644
index 00000000..a918ecda
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/AUTHORS
@@ -0,0 +1,39 @@
+Original Authors "mruby developers" are:
+ Yukihiro Matsumoto
+ SCSK KYUSHU CORPORATION
+ Kyushu Institute of Technology
+ Network Applied Communication Laboratory, Inc.
+ Daniel Bovensiepen
+ Jon Maken
+ Bjorn De Meyer
+ Yuichiro MASUI
+ Masamitsu MURASE
+ Masaki Muranaka
+ Internet Initiative Japan Inc.
+ Tadashi FUKUZAWA
+ MATSUMOTO Ryosuke
+ Yasuhiro Matsumoto
+ Koji Yoshioka
+ Jun Hiroe
+ Narihiro Nakamura
+ Yuichi Nishiwaki
+ Tatsuhiko Kubo
+ Takeshi Watanabe
+ Yuki Kurihara
+ specified non-profit corporation mruby Forum
+ Kazuaki Tanaka
+ Hiromasa Ishii
+ Hiroshi Mimaki
+ Satoshi Odawara
+ Mitsubishi Electric Micro-Computer Application Software Co.,Ltd.
+ Ralph Desir(Mav7)
+ Hiroyuki Matsuzaki
+ Yuhei Okazaki
+ Manycolors, Inc.
+ Shota Nakano
+ Yuichi Osawa
+ Terence Lee
+ Zachary Scott
+ Tomasz Dąbrowski
+ Christopher Aue
+ Masahiro Wakame
diff --git a/web/server/h2o/libh2o/deps/mruby/CONTRIBUTING.md b/web/server/h2o/libh2o/deps/mruby/CONTRIBUTING.md
new file mode 100644
index 00000000..6bababb8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/CONTRIBUTING.md
@@ -0,0 +1,68 @@
+# How to contribute
+
+mruby is an open-source project which is looking forward to each contribution.
+
+## Your Pull Request
+
+To make it easy to review and understand your change please keep the following
+things in mind before submitting your pull request:
+
+* Work on the latest possible state of **mruby/master**
+* Create a branch which is dedicated to your change
+* Test your changes before creating a pull request (```./minirake test```)
+* If possible write a test case which confirms your change
+* Don't mix several features or bug-fixes in one pull request
+* Create a meaningful commit message
+* Explain your change (i.e. with a link to the issue you are fixing)
+* Use mrbgem to provide non ISO features (classes, modules and methods) unless
+ you have a special reason to implement them in the core
+
+## Coding conventions
+
+How to style your C and Ruby code which you want to submit.
+
+### C code
+
+The core part (parser, bytecode-interpreter, core-lib, etc.) of mruby is
+written in the C programming language. Please note the following hints for your
+C code:
+
+#### Comply with C99 (ISO/IEC 9899:1999)
+
+mruby should be highly portable to other systems and compilers. For this it is
+recommended to keep your code as close as possible to the C99 standard
+(http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf).
+
+Although we target C99, Visual C++ is also an important target for mruby. For
+this reason a declaration of a local variable has to be at the beginning of a
+scope block.
+
+#### Reduce library dependencies to a minimum
+
+The dependencies to libraries should be kept to an absolute minimum. This
+increases the portability but makes it also easier to cut away parts of mruby
+on-demand.
+
+#### Don't use C++ style comments
+
+ /* This is the preferred comment style */
+
+Use C++ style comments only for temporary comment e.g. commenting out some code lines.
+
+#### Insert a break after the method return value:
+
+ int
+ main(void)
+ {
+ ...
+ }
+
+### Ruby code
+
+Parts of the standard library of mruby are written in the Ruby programming
+language itself. Please note the following hints for your Ruby code:
+
+#### Comply with the Ruby standard (ISO/IEC 30170:2012)
+
+mruby is currently targeting to execute Ruby code which complies to ISO/IEC
+30170:2012 (http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579).
diff --git a/web/server/h2o/libh2o/deps/mruby/LEGAL b/web/server/h2o/libh2o/deps/mruby/LEGAL
new file mode 100644
index 00000000..84929998
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/LEGAL
@@ -0,0 +1,6 @@
+LEGAL NOTICE INFORMATION
+------------------------
+
+All the files in this distribution are covered under the MIT license
+(see the file MITL) except some files mentioned below:
+
diff --git a/web/server/h2o/libh2o/deps/mruby/MITL b/web/server/h2o/libh2o/deps/mruby/MITL
new file mode 100644
index 00000000..d02b8fe1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/MITL
@@ -0,0 +1,20 @@
+Copyright (c) 2017 mruby developers
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
diff --git a/web/server/h2o/libh2o/deps/mruby/Makefile b/web/server/h2o/libh2o/deps/mruby/Makefile
new file mode 100644
index 00000000..4912f17e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/Makefile
@@ -0,0 +1,17 @@
+# mruby is using Rake (http://rake.rubyforge.org) as a build tool.
+# We provide a minimalistic version called minirake inside of our
+# codebase.
+
+RAKE = ruby ./minirake
+
+all :
+ $(RAKE)
+.PHONY : all
+
+test : all
+ $(RAKE) test
+.PHONY : test
+
+clean :
+ $(RAKE) clean
+.PHONY : clean
diff --git a/web/server/h2o/libh2o/deps/mruby/NEWS b/web/server/h2o/libh2o/deps/mruby/NEWS
new file mode 100644
index 00000000..5c252382
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/NEWS
@@ -0,0 +1,13 @@
+* NEWS
+
+This document is a list of user visible feature changes made between
+releases except for bug fixes.
+
+Note that each entry is kept so brief that no reason behind or
+reference information is supplied with. For a full list of changes
+with all sufficient information, see the ChangeLog file.
+
+
+** Information about first release v1.0.0
+
+
diff --git a/web/server/h2o/libh2o/deps/mruby/README.md b/web/server/h2o/libh2o/deps/mruby/README.md
new file mode 100644
index 00000000..9d0c611b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/README.md
@@ -0,0 +1,92 @@
+[![Build Status][build-status-img]][travis-ci]
+
+## What is mruby
+
+mruby is the lightweight implementation of the Ruby language complying to (part
+of) the [ISO standard][ISO-standard]. Its syntax is Ruby 1.9 compatible.
+
+mruby can be linked and embedded within your application. We provide the
+interpreter program "mruby" and the interactive mruby shell "mirb" as examples.
+You can also compile Ruby programs into compiled byte code using the mruby
+compiler "mrbc". All those tools reside in the "bin" directory. "mrbc" is
+also able to generate compiled byte code in a C source file, see the "mrbtest"
+program under the "test" directory for an example.
+
+This achievement was sponsored by the Regional Innovation Creation R&D Programs
+of the Ministry of Economy, Trade and Industry of Japan.
+
+## How to get mruby
+
+The stable version 1.3.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.3.0.zip](https://github.com/mruby/mruby/archive/1.3.0.zip)
+
+The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
+
+The trunk of the mruby source tree can be checked out with the
+following command:
+
+ $ git clone https://github.com/mruby/mruby.git
+
+You can also install and compile mruby using [ruby-install](https://github.com/postmodern/ruby-install), [ruby-build](https://github.com/rbenv/ruby-build) or [rvm](https://github.com/rvm/rvm).
+
+## mruby home-page
+
+The URL of the mruby home-page is: [http://www.mruby.org](http://www.mruby.org).
+
+## Mailing list
+
+We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby).
+
+## How to compile and install (mruby and gems)
+
+See the [doc/guides/compile.md](doc/guides/compile.md) file.
+
+## Running Tests
+
+To run the tests, execute the following from the project's root directory.
+
+ $ make test
+
+Or
+
+ $ ruby ./minirake test
+
+## How to customize mruby (mrbgems)
+
+mruby contains a package manager called *mrbgems*. To create extensions
+in C and/or Ruby you should create a *GEM*. For a documentation of how to
+use mrbgems consult the file [doc/guides/mrbgems.md](doc/guides/mrbgems.md). For example code of
+how to use mrbgems look into the folder *examples/mrbgems/*.
+
+## License
+
+mruby is released under the [MIT License](MITL).
+
+## Note for License
+
+mruby has chosen a MIT License due to its permissive license allowing
+developers to target various environments such as embedded systems.
+However, the license requires the display of the copyright notice and license
+information in manuals for instance. Doing so for big projects can be
+complicated or troublesome. This is why mruby has decided to display "mruby
+developers" as the copyright name to make it simple conventionally.
+In the future, mruby might ask you to distribute your new code
+(that you will commit,) under the MIT License as a member of
+"mruby developers" but contributors will keep their copyright.
+(We did not intend for contributors to transfer or waive their copyrights,
+Actual copyright holder name (contributors) will be listed in the AUTHORS
+file.)
+
+Please ask us if you want to distribute your code under another license.
+
+## How to Contribute
+
+See the [contribution guidelines][contribution-guidelines], and then send a pull
+request to <http://github.com/mruby/mruby>. We consider you have granted
+non-exclusive right to your contributed code under MIT license. If you want to
+be named as one of mruby developers, please include an update to the AUTHORS
+file in your pull request.
+
+[ISO-standard]: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579
+[build-status-img]: https://travis-ci.org/mruby/mruby.svg?branch=master
+[contribution-guidelines]: CONTRIBUTING.md
+[travis-ci]: https://travis-ci.org/mruby/mruby
diff --git a/web/server/h2o/libh2o/deps/mruby/Rakefile b/web/server/h2o/libh2o/deps/mruby/Rakefile
new file mode 100644
index 00000000..2f6fa056
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/Rakefile
@@ -0,0 +1,152 @@
+# encoding: utf-8
+# Build description.
+# basic build file for mruby
+MRUBY_ROOT = File.dirname(File.expand_path(__FILE__))
+MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
+MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd')
+
+$LOAD_PATH << File.join(MRUBY_ROOT, "lib")
+
+# load build systems
+require "mruby-core-ext"
+require "mruby/build"
+require "mruby/gem"
+
+# load configuration file
+MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
+load MRUBY_CONFIG
+
+# load basic rules
+MRuby.each_target do |build|
+ build.define_rules
+end
+
+# load custom rules
+load "#{MRUBY_ROOT}/src/mruby_core.rake"
+load "#{MRUBY_ROOT}/mrblib/mrblib.rake"
+
+load "#{MRUBY_ROOT}/tasks/mrbgems.rake"
+load "#{MRUBY_ROOT}/tasks/libmruby.rake"
+
+load "#{MRUBY_ROOT}/tasks/benchmark.rake"
+
+load "#{MRUBY_ROOT}/tasks/gitlab.rake"
+
+##############################
+# generic build targets, rules
+task :default => :all
+
+bin_path = ENV['INSTALL_DIR'] || "#{MRUBY_ROOT}/bin"
+FileUtils.mkdir_p bin_path, { :verbose => $verbose }
+
+depfiles = MRuby.targets['host'].bins.map do |bin|
+ install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}")
+ source_path = MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/#{bin}")
+
+ file install_path => source_path do |t|
+ FileUtils.rm_f t.name, { :verbose => $verbose }
+ FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose }
+ end
+
+ install_path
+end
+
+MRuby.each_target do |target|
+ gems.map do |gem|
+ current_dir = gem.dir.relative_path_from(Dir.pwd)
+ relative_from_root = gem.dir.relative_path_from(MRUBY_ROOT)
+ current_build_dir = File.expand_path "#{build_dir}/#{relative_from_root}"
+
+ if current_build_dir !~ /^#{build_dir}/
+ current_build_dir = "#{build_dir}/mrbgems/#{gem.name}"
+ end
+
+ gem.bins.each do |bin|
+ exec = exefile("#{build_dir}/bin/#{bin}")
+ objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) }
+
+ file exec => objs + [libfile("#{build_dir}/lib/libmruby")] do |t|
+ gem_flags = gems.map { |g| g.linker.flags }
+ gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
+ gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries }
+ gem_libraries = gems.map { |g| g.linker.libraries }
+ gem_library_paths = gems.map { |g| g.linker.library_paths }
+ linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries, gem_flags_after_libraries
+ end
+
+ if target == MRuby.targets['host']
+ install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}")
+
+ file install_path => exec do |t|
+ FileUtils.rm_f t.name, { :verbose => $verbose }
+ FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose }
+ end
+ depfiles += [ install_path ]
+ elsif target == MRuby.targets['host-debug']
+ unless MRuby.targets['host'].gems.map {|g| g.bins}.include?([bin])
+ install_path = MRuby.targets['host-debug'].exefile("#{bin_path}/#{bin}")
+
+ file install_path => exec do |t|
+ FileUtils.rm_f t.name, { :verbose => $verbose }
+ FileUtils.cp t.prerequisites.first, t.name, { :verbose => $verbose }
+ end
+ depfiles += [ install_path ]
+ end
+ else
+ depfiles += [ exec ]
+ end
+ end
+ end
+end
+
+depfiles += MRuby.targets.map { |n, t|
+ [t.libfile("#{t.build_dir}/lib/libmruby")]
+}.flatten
+
+depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t|
+ t.bins.map { |bin| t.exefile("#{t.build_dir}/bin/#{bin}") }
+}.flatten
+
+desc "build all targets, install (locally) in-repo"
+task :all => depfiles do
+ puts
+ puts "Build summary:"
+ puts
+ MRuby.each_target do
+ print_build_summary
+ end
+end
+
+desc "run all mruby tests"
+task :test => ["all"] do
+ MRuby.each_target do
+ run_test if test_enabled?
+ end
+end
+
+desc "clean all built and in-repo installed artifacts"
+task :clean do
+ MRuby.each_target do |t|
+ FileUtils.rm_rf t.build_dir, { :verbose => $verbose }
+ end
+ FileUtils.rm_f depfiles, { :verbose => $verbose }
+ puts "Cleaned up target build folder"
+end
+
+desc "clean everything!"
+task :deep_clean => ["clean"] do
+ MRuby.each_target do |t|
+ FileUtils.rm_rf t.gem_clone_dir, { :verbose => $verbose }
+ end
+ puts "Cleaned up mrbgems build folder"
+end
+
+desc 'generate document'
+task :doc do
+ begin
+ sh "mrbdoc"
+ rescue
+ puts "ERROR: To generate documents, you should install yard-mruby gem."
+ puts " $ gem install yard-mruby"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/TODO b/web/server/h2o/libh2o/deps/mruby/TODO
new file mode 100644
index 00000000..3e195f99
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/TODO
@@ -0,0 +1,10 @@
+Things to do (Things that are not done yet)
+
+* special variables ($1,$2..)
+* super in aliased methods
+* multi-assignment decomposing
+* keyword arguments in def statement
+
+Things to improve (Done but things to fix)
+
+* Make additions as they are noticed.
diff --git a/web/server/h2o/libh2o/deps/mruby/appveyor.yml b/web/server/h2o/libh2o/deps/mruby/appveyor.yml
new file mode 100644
index 00000000..c62b1357
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/appveyor.yml
@@ -0,0 +1,27 @@
+version: "{build}"
+
+os: Visual Studio 2015
+
+clone_depth: 50
+
+
+environment:
+ matrix:
+ # Visual Studio 2015 64bit
+ - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
+ machine: amd64
+
+ # Visual Studio 2013 64bit
+ - visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
+ machine: amd64
+
+
+init:
+ - call "%visualcpp%" %machine%
+ # For using bison.exe
+ - set PATH=%PATH%;C:\cygwin\bin;
+
+
+build_script:
+ - set MRUBY_CONFIG=appveyor_config.rb
+ - ruby .\minirake test
diff --git a/web/server/h2o/libh2o/deps/mruby/appveyor_config.rb b/web/server/h2o/libh2o/deps/mruby/appveyor_config.rb
new file mode 100644
index 00000000..57e10330
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/appveyor_config.rb
@@ -0,0 +1,50 @@
+MRuby::Build.new('debug') do |conf|
+ toolchain :visualcpp
+ enable_debug
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA)
+ end
+
+ build_mrbc_exec
+end
+
+MRuby::Build.new('full-debug') do |conf|
+ toolchain :visualcpp
+ enable_debug
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
+
+ conf.enable_test
+end
+
+MRuby::Build.new do |conf|
+ toolchain :visualcpp
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_GC_FIXED_ARENA)
+ end
+ conf.enable_bintest
+ conf.enable_test
+end
+
+MRuby::Build.new('cxx_abi') do |conf|
+ toolchain :visualcpp
+
+ conf.gembox 'full-core'
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_GC_FIXED_ARENA)
+ end
+ conf.enable_bintest
+ conf.enable_test
+
+ enable_cxx_abi
+
+ build_mrbc_exec
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/bm_ao_render.rb b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_ao_render.rb
new file mode 100644
index 00000000..8212c3a1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_ao_render.rb
@@ -0,0 +1,314 @@
+# AO render benchmark
+# Original program (C) Syoyo Fujita in Javascript (and other languages)
+# https://code.google.com/p/aobench/
+# Ruby(yarv2llvm) version by Hideki Miura
+# mruby version by Hideki Miura
+#
+
+IMAGE_WIDTH = 64
+IMAGE_HEIGHT = 64
+NSUBSAMPLES = 2
+NAO_SAMPLES = 8
+
+module Rand
+ # Use xorshift
+ @@x = 123456789
+ @@y = 362436069
+ @@z = 521288629
+ @@w = 88675123
+ BNUM = 1 << 29
+ BNUMF = BNUM.to_f
+ def self.rand
+ x = @@x
+ t = x ^ ((x & 0xfffff) << 11)
+ w = @@w
+ @@x, @@y, @@z = @@y, @@z, w
+ w = @@w = (w ^ (w >> 19) ^ (t ^ (t >> 8)))
+ (w % BNUM) / BNUMF
+ end
+end
+
+class Vec
+ def initialize(x, y, z)
+ @x = x
+ @y = y
+ @z = z
+ end
+
+ def x=(v); @x = v; end
+ def y=(v); @y = v; end
+ def z=(v); @z = v; end
+ def x; @x; end
+ def y; @y; end
+ def z; @z; end
+
+ def vadd(b)
+ Vec.new(@x + b.x, @y + b.y, @z + b.z)
+ end
+
+ def vsub(b)
+ Vec.new(@x - b.x, @y - b.y, @z - b.z)
+ end
+
+ def vcross(b)
+ Vec.new(@y * b.z - @z * b.y,
+ @z * b.x - @x * b.z,
+ @x * b.y - @y * b.x)
+ end
+
+ def vdot(b)
+ r = @x * b.x + @y * b.y + @z * b.z
+ r
+ end
+
+ def vlength
+ Math.sqrt(@x * @x + @y * @y + @z * @z)
+ end
+
+ def vnormalize
+ len = vlength
+ v = Vec.new(@x, @y, @z)
+ if len > 1.0e-17 then
+ v.x = v.x / len
+ v.y = v.y / len
+ v.z = v.z / len
+ end
+ v
+ end
+end
+
+
+class Sphere
+ def initialize(center, radius)
+ @center = center
+ @radius = radius
+ end
+
+ def center; @center; end
+ def radius; @radius; end
+
+ def intersect(ray, isect)
+ rs = ray.org.vsub(@center)
+ b = rs.vdot(ray.dir)
+ c = rs.vdot(rs) - (@radius * @radius)
+ d = b * b - c
+ if d > 0.0 then
+ t = - b - Math.sqrt(d)
+
+ if t > 0.0 and t < isect.t then
+ isect.t = t
+ isect.hit = true
+ isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
+ ray.org.y + ray.dir.y * t,
+ ray.org.z + ray.dir.z * t)
+ n = isect.pl.vsub(@center)
+ isect.n = n.vnormalize
+ end
+ end
+ end
+end
+
+class Plane
+ def initialize(p, n)
+ @p = p
+ @n = n
+ end
+
+ def intersect(ray, isect)
+ d = -@p.vdot(@n)
+ v = ray.dir.vdot(@n)
+ v0 = v
+ if v < 0.0 then
+ v0 = -v
+ end
+ if v0 < 1.0e-17 then
+ return
+ end
+
+ t = -(ray.org.vdot(@n) + d) / v
+
+ if t > 0.0 and t < isect.t then
+ isect.hit = true
+ isect.t = t
+ isect.n = @n
+ isect.pl = Vec.new(ray.org.x + t * ray.dir.x,
+ ray.org.y + t * ray.dir.y,
+ ray.org.z + t * ray.dir.z)
+ end
+ end
+end
+
+class Ray
+ def initialize(org, dir)
+ @org = org
+ @dir = dir
+ end
+
+ def org; @org; end
+ def org=(v); @org = v; end
+ def dir; @dir; end
+ def dir=(v); @dir = v; end
+end
+
+class Isect
+ def initialize
+ @t = 10000000.0
+ @hit = false
+ @pl = Vec.new(0.0, 0.0, 0.0)
+ @n = Vec.new(0.0, 0.0, 0.0)
+ end
+
+ def t; @t; end
+ def t=(v); @t = v; end
+ def hit; @hit; end
+ def hit=(v); @hit = v; end
+ def pl; @pl; end
+ def pl=(v); @pl = v; end
+ def n; @n; end
+ def n=(v); @n = v; end
+end
+
+def clamp(f)
+ i = f * 255.5
+ if i > 255.0 then
+ i = 255.0
+ end
+ if i < 0.0 then
+ i = 0.0
+ end
+ i.to_i
+end
+
+def otherBasis(basis, n)
+ basis[2] = Vec.new(n.x, n.y, n.z)
+ basis[1] = Vec.new(0.0, 0.0, 0.0)
+
+ if n.x < 0.6 and n.x > -0.6 then
+ basis[1].x = 1.0
+ elsif n.y < 0.6 and n.y > -0.6 then
+ basis[1].y = 1.0
+ elsif n.z < 0.6 and n.z > -0.6 then
+ basis[1].z = 1.0
+ else
+ basis[1].x = 1.0
+ end
+
+ basis[0] = basis[1].vcross(basis[2])
+ basis[0] = basis[0].vnormalize
+
+ basis[1] = basis[2].vcross(basis[0])
+ basis[1] = basis[1].vnormalize
+end
+
+class Scene
+ def initialize
+ @spheres = Array.new
+ @spheres[0] = Sphere.new(Vec.new(-2.0, 0.0, -3.5), 0.5)
+ @spheres[1] = Sphere.new(Vec.new(-0.5, 0.0, -3.0), 0.5)
+ @spheres[2] = Sphere.new(Vec.new(1.0, 0.0, -2.2), 0.5)
+ @plane = Plane.new(Vec.new(0.0, -0.5, 0.0), Vec.new(0.0, 1.0, 0.0))
+ end
+
+ def ambient_occlusion(isect)
+ basis = Array.new(3)
+ otherBasis(basis, isect.n)
+
+ ntheta = NAO_SAMPLES
+ nphi = NAO_SAMPLES
+ eps = 0.0001
+ occlusion = 0.0
+
+ p0 = Vec.new(isect.pl.x + eps * isect.n.x,
+ isect.pl.y + eps * isect.n.y,
+ isect.pl.z + eps * isect.n.z)
+ nphi.times do |j|
+ ntheta.times do |i|
+ r = Rand::rand
+ phi = 2.0 * 3.14159265 * Rand::rand
+ x = Math.cos(phi) * Math.sqrt(1.0 - r)
+ y = Math.sin(phi) * Math.sqrt(1.0 - r)
+ z = Math.sqrt(r)
+
+ rx = x * basis[0].x + y * basis[1].x + z * basis[2].x
+ ry = x * basis[0].y + y * basis[1].y + z * basis[2].y
+ rz = x * basis[0].z + y * basis[1].z + z * basis[2].z
+
+ raydir = Vec.new(rx, ry, rz)
+ ray = Ray.new(p0, raydir)
+
+ occisect = Isect.new
+ @spheres[0].intersect(ray, occisect)
+ @spheres[1].intersect(ray, occisect)
+ @spheres[2].intersect(ray, occisect)
+ @plane.intersect(ray, occisect)
+ if occisect.hit then
+ occlusion = occlusion + 1.0
+ else
+ 0.0
+ end
+ end
+ end
+
+ occlusion = (ntheta.to_f * nphi.to_f - occlusion) / (ntheta.to_f * nphi.to_f)
+ Vec.new(occlusion, occlusion, occlusion)
+ end
+
+ def render(w, h, nsubsamples)
+ cnt = 0
+ nsf = nsubsamples.to_f
+ h.times do |y|
+ w.times do |x|
+ rad = Vec.new(0.0, 0.0, 0.0)
+
+ # Subsmpling
+ nsubsamples.times do |v|
+ nsubsamples.times do |u|
+ cnt = cnt + 1
+ wf = w.to_f
+ hf = h.to_f
+ xf = x.to_f
+ yf = y.to_f
+ uf = u.to_f
+ vf = v.to_f
+
+ px = (xf + (uf / nsf) - (wf / 2.0)) / (wf / 2.0)
+ py = -(yf + (vf / nsf) - (hf / 2.0)) / (hf / 2.0)
+
+ eye = Vec.new(px, py, -1.0).vnormalize
+
+ ray = Ray.new(Vec.new(0.0, 0.0, 0.0), eye)
+
+ isect = Isect.new
+ @spheres[0].intersect(ray, isect)
+ @spheres[1].intersect(ray, isect)
+ @spheres[2].intersect(ray, isect)
+ @plane.intersect(ray, isect)
+ if isect.hit then
+ col = ambient_occlusion(isect)
+ rad.x = rad.x + col.x
+ rad.y = rad.y + col.y
+ rad.z = rad.z + col.z
+ else
+ 0.0
+ end
+ end
+ end
+
+ r = rad.x / (nsf * nsf)
+ g = rad.y / (nsf * nsf)
+ b = rad.z / (nsf * nsf)
+ printf("%c", clamp(r))
+ printf("%c", clamp(g))
+ printf("%c", clamp(b))
+ end
+ end
+ end
+end
+
+# File.open("ao.ppm", "w") do |fp|
+ printf("P6\n")
+ printf("%d %d\n", IMAGE_WIDTH, IMAGE_HEIGHT)
+ printf("255\n", IMAGE_WIDTH, IMAGE_HEIGHT)
+ Scene.new.render(IMAGE_WIDTH, IMAGE_HEIGHT, NSUBSAMPLES)
+# Scene.new.render(256, 256, 2)
+# end
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/bm_app_lc_fizzbuzz.rb b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_app_lc_fizzbuzz.rb
new file mode 100644
index 00000000..26283cc3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_app_lc_fizzbuzz.rb
@@ -0,0 +1,52 @@
+#
+# FizzBuzz program using only lambda calculus
+#
+# This program is quoted from
+# "Understanding Computation" by Tom Stuart
+# http://computationbook.com/
+#
+# You can understand why this program works fine by reading this book.
+#
+
+solution = -> k { -> f { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][k][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> l { -> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[l][f[x]] } }] } }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[m][n]][-> x { -> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[f[-> n { -> p { -> x { p[n[p][x]] } } }[m]][n]][m][x] }][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]] } } }][-> p { -> x { p[x] } }][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] } }]][-> n { -> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[p[p[p[p[p[p[p[p[p[p[x]]]]]]]]]]]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[x]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> b { b }[-> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]]][-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> n { -> p { -> x { p[n[p][x]] } } }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]]]][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> n { -> l { -> x { -> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> l { -> x { -> g { -> b { b }[-> p { p[-> x { -> y { x } }] }[l]][x][-> y { g[f[-> l { -> p { p[-> x { -> y { y } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][x][g]][-> l { -> p { p[-> x { -> y { x } }] }[-> p { p[-> x { -> y { y } }] }[l]] }[l]][y] }] } } } }][l][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }[-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][x]][-> l { -> x { -> x { -> y { -> f { f[x][y] } } }[-> x { -> y { y } }][-> x { -> y { -> f { f[x][y] } } }[x][l]] } }] } }[-> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }[-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]]][-> x { -> y { -> f { f[x][y] } } }[-> x { -> y { x } }][-> x { -> y { x } }]][-> x { f[-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { -> n { -> p { -> x { p[n[p][x]] } } }[f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n]][x] }][-> p { -> x { x } }] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]][x] }]][-> f { -> x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }[-> f { -> m { -> n { -> b { b }[-> m { -> n { -> n { n[-> x { -> x { -> y { y } } }][-> x { -> y { x } }] }[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]] } }[n][m]][-> x { f[-> m { -> n { n[-> n { -> p { p[-> x { -> y { x } }] }[n[-> p { -> x { -> y { -> f { f[x][y] } } }[-> p { p[-> x { -> y { y } }] }[p]][-> n { -> p { -> x { p[n[p][x]] } } }[-> p { p[-> x { -> y { y } }] }[p]]] }][-> x { -> y { -> f { f[x][y] } } }[-> p { -> x { x } }][-> p { -> x { x } }]]] }][m] } }[m][n]][n][x] }][m] } } }][n][-> m { -> n { n[-> m { -> n { n[-> n { -> p { -> x { p[n[p][x]] } } }][m] } }[m]][-> p { -> x { x } }] } }[-> p { -> x { p[p[x]] } }][-> p { -> x { p[p[p[p[p[x]]]]] } }]]] } }][n]]]] }]
+
+FIRST = -> l { LEFT[RIGHT[l]] }
+IF = -> b { b }
+LEFT = -> p { p[-> x { -> y { x } } ] }
+RIGHT = -> p { p[-> x { -> y { y } } ] }
+IS_EMPTY = LEFT
+REST = -> l { RIGHT[RIGHT[l]] }
+
+def to_integer(proc)
+ proc[-> n { n + 1 }][0]
+end
+
+def to_boolean(proc)
+ IF[proc][true][false]
+end
+
+def to_array(proc)
+ array = []
+
+ until to_boolean(IS_EMPTY[proc])
+ array.push(FIRST[proc])
+ proc = REST[proc]
+ end
+
+ array
+end
+
+def to_char(c)
+ '0123456789BFiuz'.slice(to_integer(c))
+end
+
+def to_string(s)
+ to_array(s).map { |c| to_char(c) }.join
+end
+
+answer = to_array(solution).map do |p|
+ to_string(p)
+end
+
+answer_str = answer.to_a
+# puts answer_str
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/bm_fib.rb b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_fib.rb
new file mode 100644
index 00000000..4b395f9c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_fib.rb
@@ -0,0 +1,7 @@
+
+def fib n
+ return n if n < 2
+ fib(n-2) + fib(n-1)
+end
+
+puts fib(37)
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/bm_so_lists.rb b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_so_lists.rb
new file mode 100644
index 00000000..e8f4a2a5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/bm_so_lists.rb
@@ -0,0 +1,47 @@
+#from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby
+
+NUM = 300
+SIZE = 10000
+
+def test_lists()
+ # create a list of integers (Li1) from 1 to SIZE
+ li1 = (1..SIZE).to_a
+ # copy the list to li2 (not by individual items)
+ li2 = li1.dup
+ # remove each individual item from left side of li2 and
+ # append to right side of li3 (preserving order)
+ li3 = Array.new
+ while (not li2.empty?)
+ li3.push(li2.shift)
+ end
+ # li2 must now be empty
+ # remove each individual item from right side of li3 and
+ # append to right side of li2 (reversing list)
+ while (not li3.empty?)
+ li2.push(li3.pop)
+ end
+ # li3 must now be empty
+ # reverse li1 in place
+ li1.reverse!
+ # check that first item is now SIZE
+ if li1[0] != SIZE then
+ p "not SIZE"
+ 0
+ else
+ # compare li1 and li2 for equality
+ if li1 != li2 then
+ return(0)
+ else
+ # return the length of the list
+ li1.length
+ end
+ end
+end
+
+i = 0
+while i<NUM
+ i += 1
+ result = test_lists()
+end
+
+result
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/build_config_boxing.rb b/web/server/h2o/libh2o/deps/mruby/benchmark/build_config_boxing.rb
new file mode 100644
index 00000000..b478c900
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/build_config_boxing.rb
@@ -0,0 +1,28 @@
+MRuby::Build.new do |conf|
+ toolchain :gcc
+end
+
+MRuby::Build.new('no_boxing') do |conf|
+ toolchain :gcc
+
+ conf.gembox 'default'
+end
+
+MRuby::Build.new('word_boxing') do |conf|
+ toolchain :gcc
+
+ conf.gembox 'default'
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_WORD_BOXING)
+ end
+end
+
+MRuby::Build.new('nan_boxing') do |conf|
+ toolchain :gcc
+
+ conf.gembox 'default'
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_NAN_BOXING)
+ end
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/build_config_cc.rb b/web/server/h2o/libh2o/deps/mruby/benchmark/build_config_cc.rb
new file mode 100644
index 00000000..56d725bc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/build_config_cc.rb
@@ -0,0 +1,13 @@
+MRuby::Build.new do |conf|
+ toolchain :gcc
+end
+
+MRuby::Build.new('gcc') do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+end
+
+MRuby::Build.new('clang') do |conf|
+ toolchain :clang
+ conf.gembox 'default'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/benchmark/plot.gpl b/web/server/h2o/libh2o/deps/mruby/benchmark/plot.gpl
new file mode 100644
index 00000000..725e2ec1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/benchmark/plot.gpl
@@ -0,0 +1,5 @@
+set yrange [0:]
+set terminal pngcairo font 'Sans, 8' lw 1 size 1400,1024
+set xtics rotate by -45
+set style histogram errorbars gap 2 lw 1
+set style fill solid border -1
diff --git a/web/server/h2o/libh2o/deps/mruby/bin/.gitkeep b/web/server/h2o/libh2o/deps/mruby/bin/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/bin/.gitkeep
diff --git a/web/server/h2o/libh2o/deps/mruby/build_config.rb b/web/server/h2o/libh2o/deps/mruby/build_config.rb
new file mode 100644
index 00000000..8293092a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/build_config.rb
@@ -0,0 +1,152 @@
+MRuby::Build.new do |conf|
+ # load specific toolchain settings
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # Use mrbgems
+ # conf.gem 'examples/mrbgems/ruby_extension_example'
+ # conf.gem 'examples/mrbgems/c_extension_example' do |g|
+ # g.cc.flags << '-g' # append cflags in this gem
+ # end
+ # conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
+ # conf.gem :core => 'mruby-eval'
+ # conf.gem :mgem => 'mruby-io'
+ # conf.gem :github => 'iij/mruby-io'
+ # conf.gem :git => 'git@github.com:iij/mruby-io.git', :branch => 'master', :options => '-v'
+
+ # include the default GEMs
+ conf.gembox 'default'
+ # C compiler settings
+ # conf.cc do |cc|
+ # cc.command = ENV['CC'] || 'gcc'
+ # cc.flags = [ENV['CFLAGS'] || %w()]
+ # cc.include_paths = ["#{root}/include"]
+ # cc.defines = %w(DISABLE_GEMS)
+ # cc.option_include_path = '-I%s'
+ # cc.option_define = '-D%s'
+ # cc.compile_options = "%{flags} -MMD -o %{outfile} -c %{infile}"
+ # end
+
+ # mrbc settings
+ # conf.mrbc do |mrbc|
+ # mrbc.compile_options = "-g -B%{funcname} -o-" # The -g option is required for line numbers
+ # end
+
+ # Linker settings
+ # conf.linker do |linker|
+ # linker.command = ENV['LD'] || 'gcc'
+ # linker.flags = [ENV['LDFLAGS'] || []]
+ # linker.flags_before_libraries = []
+ # linker.libraries = %w()
+ # linker.flags_after_libraries = []
+ # linker.library_paths = []
+ # linker.option_library = '-l%s'
+ # linker.option_library_path = '-L%s'
+ # linker.link_options = "%{flags} -o %{outfile} %{objs} %{libs}"
+ # end
+
+ # Archiver settings
+ # conf.archiver do |archiver|
+ # archiver.command = ENV['AR'] || 'ar'
+ # archiver.archive_options = 'rs %{outfile} %{objs}'
+ # end
+
+ # Parser generator settings
+ # conf.yacc do |yacc|
+ # yacc.command = ENV['YACC'] || 'bison'
+ # yacc.compile_options = '-o %{outfile} %{infile}'
+ # end
+
+ # gperf settings
+ # conf.gperf do |gperf|
+ # gperf.command = 'gperf'
+ # gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}'
+ # end
+
+ # file extensions
+ # conf.exts do |exts|
+ # exts.object = '.o'
+ # exts.executable = '' # '.exe' if Windows
+ # exts.library = '.a'
+ # end
+
+ # file separetor
+ # conf.file_separator = '/'
+
+ # bintest
+ # conf.enable_bintest
+end
+
+MRuby::Build.new('host-debug') do |conf|
+ # load specific toolchain settings
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+ # C compiler settings
+ conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
+
+ # Generate mruby debugger command (require mruby-eval)
+ conf.gem :core => "mruby-bin-debugger"
+
+ # bintest
+ # conf.enable_bintest
+end
+
+MRuby::Build.new('test') do |conf|
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+ conf.enable_bintest
+ conf.enable_test
+
+ conf.gembox 'default'
+end
+
+MRuby::Build.new('bench') do |conf|
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ conf.cc.flags << '-O3'
+ end
+
+ conf.gembox 'default'
+end
+
+# Define cross build settings
+# MRuby::CrossBuild.new('32bit') do |conf|
+# toolchain :gcc
+#
+# conf.cc.flags << "-m32"
+# conf.linker.flags << "-m32"
+#
+# conf.build_mrbtest_lib_only
+#
+# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
+#
+# conf.test_runner.command = 'env'
+#
+# end
diff --git a/web/server/h2o/libh2o/deps/mruby/doc/guides/compile.md b/web/server/h2o/libh2o/deps/mruby/doc/guides/compile.md
new file mode 100644
index 00000000..2aaf6f1f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/doc/guides/compile.md
@@ -0,0 +1,488 @@
+# Compile
+
+mruby uses Rake to compile and cross-compile all libraries and
+binaries.
+
+## Prerequisites
+
+To compile mruby out of the source code you need the following tools:
+* C Compiler (i.e. ```gcc```)
+* Linker (i.e. ```gcc```)
+* Archive utility (i.e. ```ar```)
+* Parser generator (i.e. ```bison```)
+* Ruby 1.8 or 1.9 (i.e. ```ruby``` or ```jruby```)
+
+Optional:
+* GIT (to update mruby source and integrate mrbgems easier)
+* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
+* Assembler (to use GEMs which include \*.asm)
+
+## Usage
+
+Inside of the root directory of the mruby source a file exists
+called *build_config.rb*. This file contains the build configuration
+of mruby and looks like this for example:
+```ruby
+MRuby::Build.new do |conf|
+ toolchain :gcc
+end
+```
+
+All tools necessary to compile mruby can be set or modified here. In case
+you want to maintain an additional *build_config.rb* you can define a
+customized path using the *$MRUBY_CONFIG* environment variable.
+
+To compile just call ```./minirake``` inside of the mruby source root. To
+generate and execute the test tools call ```./minirake test```. To clean
+all build files call ```./minirake clean```. To see full command line on
+build, call ```./minirake -v```.
+
+## Build Configuration
+
+Inside of the *build_config.rb* the following options can be configured
+based on your environment.
+
+### Toolchains
+
+The mruby build system already contains a set of toolchain templates which
+configure the build environment for specific compiler infrastructures.
+
+#### GCC
+
+Toolchain configuration for the GNU C Compiler.
+```ruby
+toolchain :gcc
+```
+
+#### clang
+
+Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the
+GCC toolchain.
+```ruby
+toolchain :clang
+```
+
+#### Visual Studio 2010, 2012 and 2013
+
+Toolchain configuration for Visual Studio on Windows. If you use the
+[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx),
+you normally do not have to specify this manually, since it gets automatically detected by our build process.
+```ruby
+toolchain :visualcpp
+```
+
+#### Android
+
+Toolchain configuration for Android.
+```ruby
+toolchain :android
+```
+
+Requires the custom standalone Android NDK and the toolchain path
+in ```ANDROID_STANDALONE_TOOLCHAIN```.
+
+### Binaries
+
+It is possible to select which tools should be compiled during the compilation
+process. The following tools can be selected:
+* mruby (mruby interpreter)
+* mirb (mruby interactive shell)
+
+To select them declare conf.gem as follows:
+```ruby
+conf.gem "#{root}/mrbgems/mruby-bin-mruby"
+conf.gem "#{root}/mrbgems/mruby-bin-mirb"
+```
+
+### File Separator
+
+Some environments require a different file separator character. It is possible to
+set the character via ```conf.file_separator```.
+```ruby
+conf.file_separator = '/'
+```
+
+### C Compiler
+
+Configuration of the C compiler binary, flags and include paths.
+```ruby
+conf.cc do |cc|
+ cc.command = ...
+ cc.flags = ...
+ cc.include_paths = ...
+ cc.defines = ...
+ cc.option_include_path = ...
+ cc.option_define = ...
+ cc.compile_options = ...
+end
+```
+
+C Compiler has header searcher to detect installed library.
+
+If you need a include path of header file use ```search_header_path```:
+```ruby
+# Searches ```iconv.h```.
+# If found it will return include path of the header file.
+# Otherwise it will return nil .
+fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h'
+```
+
+If you need a full file name of header file use ```search_header```:
+```ruby
+# Searches ```iconv.h```.
+# If found it will return full path of the header file.
+# Otherwise it will return nil .
+iconv_h = conf.cc.search_header 'iconv.h'
+print "iconv.h found: #{iconv_h}\n"
+```
+
+Header searcher uses compiler's ```include_paths``` by default.
+When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain)
+it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```)
+
+If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler:
+```ruby
+def conf.cc.header_search_paths
+ ['/opt/local/include'] + include_paths
+end
+```
+
+### Linker
+
+Configuration of the Linker binary, flags and library paths.
+```ruby
+conf.linker do |linker|
+ linker.command = ...
+ linker.flags = ...
+ linker.flags_before_libraries = ...
+ linker.libraries = ...
+ linker.flags_after_libraries = ...
+ linker.library_paths = ....
+ linker.option_library = ...
+ linker.option_library_path = ...
+ linker.link_options = ...
+end
+```
+
+### Archiver
+
+Configuration of the Archiver binary and flags.
+```ruby
+conf.archiver do |archiver|
+ archiver.command = ...
+ archiver.archive_options = ...
+end
+```
+
+### Parser Generator
+
+Configuration of the Parser Generator binary and flags.
+```ruby
+conf.yacc do |yacc|
+ yacc.command = ...
+ yacc.compile_options = ...
+end
+```
+
+### GPerf
+
+Configuration of the GPerf binary and flags.
+```ruby
+conf.gperf do |gperf|
+ gperf.command = ...
+ gperf.compile_options = ...
+end
+```
+
+### File Extensions
+```ruby
+conf.exts do |exts|
+ exts.object = ...
+ exts.executable = ...
+ exts.library = ...
+end
+```
+
+### Mrbgems
+
+Integrate GEMs in the build process.
+```ruby
+# Integrate GEM with additional configuration
+conf.gem 'path/to/gem' do |g|
+ g.cc.flags << ...
+end
+
+# Integrate GEM without additional configuration
+conf.gem 'path/to/another/gem'
+```
+
+See doc/mrbgems/README.md for more option about mrbgems.
+
+### Mrbtest
+
+Configuration Mrbtest build process.
+
+If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only```
+```ruby
+conf.build_mrbtest_lib_only
+```
+
+### Bintest
+
+Tests for mrbgem tools using CRuby.
+To have bintests place \*.rb scripts to ```bintest/``` directory of mrbgems.
+See ```mruby-bin-*/bintest/*.rb``` if you need examples.
+If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```.
+
+You can enable it with following:
+```ruby
+conf.enable_bintest
+```
+
+### C++ ABI
+
+By default, mruby uses setjmp/longjmp to implement its
+exceptions. But it doesn't release C++ stack object
+correctly. To support mrbgems written in C++, mruby can be
+configured to use C++ exception.
+
+There are two levels of C++ exception handling. The one is
+```enable_cxx_exception``` that enables C++ exception, but
+uses C ABI. The other is ```enable_cxx_abi``` where all
+files are compiled by C++ compiler.
+
+When you mix C++ code, C++ exception would be enabled automatically.
+If you need to enable C++ exception explicitly add the following:
+```ruby
+conf.enable_cxx_exception
+```
+
+#### C++ exception disabling.
+
+If your compiler does not support C++ and you want to ensure
+you don't use mrbgem written in C++, you can explicitly disable
+C++ exception, add following:
+```ruby
+conf.disable_cxx_exception
+```
+and you will get an error when you try to use C++ gem.
+Note that it must be called before ```enable_cxx_exception``` or ```gem``` method.
+
+### Debugging mode
+
+To enable debugging mode add the following:
+```ruby
+conf.enable_debug
+```
+
+When debugging mode is enabled
+* Macro ```MRB_DEBUG``` would be defined.
+ * Which means ```mrb_assert()``` macro is enabled.
+* Debug information of irep would be generated by ```mrbc```.
+ * Because ```-g``` flag would be added to ```mrbc``` runner.
+ * You can have better backtrace of mruby scripts with this.
+
+## Cross-Compilation
+
+mruby can also be cross-compiled from one platform to another. To
+achieve this the *build_config.rb* needs to contain an instance of
+```MRuby::CrossBuild```. This instance defines the compilation
+tools and flags for the target platform. An example could look
+like this:
+```ruby
+MRuby::CrossBuild.new('32bit') do |conf|
+ toolchain :gcc
+
+ conf.cc.flags << "-m32"
+ conf.linker.flags << "-m32"
+end
+```
+
+All configuration options of ```MRuby::Build``` can also be used
+in ```MRuby::CrossBuild```.
+
+### Mrbtest in Cross-Compilation
+
+In cross compilation, you can run ```mrbtest``` on emulator if
+you have it by changing configuration of test runner.
+```ruby
+conf.test_runner do |t|
+ t.command = ... # set emulator. this value must be non nil or false
+ t.flags = ... # set flags of emulator
+
+ def t.run(bin) # override `run` if you need to change the behavior of it
+ ... # `bin` is the full path of mrbtest
+ end
+end
+```
+
+## Build process
+
+During the build process the directory *build* will be created in the
+root directory. The structure of this directory will look like this:
+
+ +- build
+ |
+ +- host
+ |
+ +- bin <- Binaries (mirb, mrbc and mruby)
+ |
+ +- lib <- Libraries (libmruby.a and libmruby_core.a)
+ |
+ +- mrblib
+ |
+ +- src
+ |
+ +- test <- mrbtest tool
+ |
+ +- tools
+ |
+ +- mirb
+ |
+ +- mrbc
+ |
+ +- mruby
+
+The compilation workflow will look like this:
+* compile all files under *src* (object files will be stored
+in *build/host/src*)
+* generate parser grammar out of *src/parse.y* (generated
+result will be stored in *build/host/src/y.tab.c*)
+* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o*
+* create *build/host/lib/libmruby_core.a* out of all object files (C only)
+* create ```build/host/bin/mrbc``` by compiling *tools/mrbc/mrbc.c* and
+linking with *build/host/lib/libmruby_core.a*
+* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files
+under *mrblib* with ```build/host/bin/mrbc```
+* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
+* create *build/host/lib/libmruby.a* out of all object files (C and Ruby)
+* create ```build/host/bin/mruby``` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
+linking with *build/host/lib/libmruby.a*
+* create ```build/host/bin/mirb``` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
+linking with *build/host/lib/libmruby.a*
+
+```
+ _____ _____ ______ ____ ____ _____ _____ ____
+| CC |->|GEN |->|AR |->|CC |->|CC |->|AR |->|CC |->|CC |
+| *.c | |y.tab| |core.a| |mrbc| |*.rb| |lib.a| |mruby| |mirb|
+ ----- ----- ------ ---- ---- ----- ----- ----
+```
+
+### Cross-Compilation
+
+In case of a cross-compilation to *i386* the *build* directory structure looks
+like this:
+
+ +- build
+ |
+ +- host
+ | |
+ | +- bin <- Native Binaries
+ | |
+ | +- lib <- Native Libraries
+ | |
+ | +- mrblib
+ | |
+ | +- src
+ | |
+ | +- test <- Native mrbtest tool
+ | |
+ | +- tools
+ | |
+ | +- mirb
+ | |
+ | +- mrbc
+ | |
+ | +- mruby
+ +- i386
+ |
+ +- bin <- Cross-compiled Binaries
+ |
+ +- lib <- Cross-compiled Libraries
+ |
+ +- mrblib
+ |
+ +- src
+ |
+ +- test <- Cross-compiled mrbtest tool
+ |
+ +- tools
+ |
+ +- mirb
+ |
+ +- mrbc
+ |
+ +- mruby
+
+An extra directory is created for the target platform. In case you
+compile for *i386* a directory called *i386* is created under the
+build directory.
+
+The cross compilation workflow starts in the same way as the normal
+compilation by compiling all *native* libraries and binaries.
+Afterwards the cross compilation process proceeds like this:
+* cross-compile all files under *src* (object files will be stored
+in *build/i386/src*)
+* generate parser grammar out of *src/parse.y* (generated
+result will be stored in *build/i386/src/y.tab.c*)
+* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o*
+* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files
+under *mrblib* with the native ```build/host/bin/mrbc```
+* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
+* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby)
+* create ```build/i386/bin/mruby``` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
+linking with *build/i386/lib/libmruby.a*
+* create ```build/i386/bin/mirb``` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
+linking with *build/i386/lib/libmruby.a*
+* create *build/i386/lib/libmruby_core.a* out of all object files (C only)
+* create ```build/i386/bin/mrbc``` by cross-compiling *tools/mrbc/mrbc.c* and
+linking with *build/i386/lib/libmruby_core.a*
+
+```
+ _______________________________________________________________
+| Native Compilation for Host System |
+| _____ ______ _____ ____ ____ _____ |
+| | CC | -> |AR | -> |GEN | -> |CC | -> |CC | -> |AR | |
+| | *.c | |core.a| |y.tab| |mrbc| |*.rb| |lib.a| |
+| ----- ------ ----- ---- ---- ----- |
+ ---------------------------------------------------------------
+ ||
+ \||/
+ \/
+ ________________________________________________________________
+| Cross Compilation for Target System |
+| _____ _____ _____ ____ ______ _____ |
+| | CC | -> |AR | -> |CC | -> |CC | -> |AR | -> |CC | |
+| | *.c | |lib.a| |mruby| |mirb| |core.a| |mrbc | |
+| ----- ----- ----- ---- ------ ----- |
+ ----------------------------------------------------------------
+```
+
+## Build Configuration Examples
+
+### Minimal Library
+
+To build a minimal mruby library you need to use the Cross Compiling
+feature due to the reason that there are functions (i.e. stdio) which
+can't be disabled for the main build.
+
+```ruby
+MRuby::CrossBuild.new('Minimal') do |conf|
+ toolchain :gcc
+
+ conf.cc.defines = %w(MRB_DISABLE_STDIO)
+ conf.bins = []
+end
+```
+
+This configuration defines a cross compile build called 'Minimal' which
+is using the GCC and compiles for the host machine. It also disables
+all usages of stdio and doesn't compile any binaries (i.e. mrbc).
+
+## Test Environment
+
+mruby's build process includes a test environment. In case you start the testing
+of mruby, a native binary called ```mrbtest``` will be generated and executed.
+This binary contains all test cases which are defined under *test/t*. In case
+of a cross-compilation an additional cross-compiled *mrbtest* binary is
+generated. You can copy this binary and run on your target system.
diff --git a/web/server/h2o/libh2o/deps/mruby/doc/guides/debugger.md b/web/server/h2o/libh2o/deps/mruby/doc/guides/debugger.md
new file mode 100644
index 00000000..72f2c2b3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/doc/guides/debugger.md
@@ -0,0 +1,370 @@
+# How to Use the mruby Debugger
+
+copyright (c) 2014 Specified Non-Profit Corporation mruby Forum
+
+## 1. Summary
+
+This file documents the mruby debugger ('mrdb') methods.
+
+## 2 Debugging with mrdb
+
+## 2.1 Building mrdb
+
+The trunk of the mruby source tree, with the most recent mrdb, can be checked out with the following command:
+
+```bash
+$ git clone https://github.com/mruby/mruby.git
+```
+
+To run the `make` command:
+
+```bash
+$ cd mruby
+$ make
+```
+
+By default, the `make` command will install the debugger files into mruby/bin.
+
+You can add the path for mrdb on your host environment with the following command:
+
+```bash
+$ echo "export PATH=\$PATH:MRUBY_ROOT/bin" >> ~/.bashrc
+$ source ~/.bashrc
+```
+
+`*MRUBY_ROOT` is the directory in which mruby source code will be installed.
+
+To confirm mrdb was installed properly, run mrdb with the `--version` option:
+
+```bash
+$ mrdb --version
+mruby 1.3.0 (2017-7-4)
+```
+
+## 2.2 Basic Operation
+
+### 2.2.1 Debugging mruby Script Files (rb file) with mrdb
+
+To invoke the mruby debugger, just type `mrdb`.
+
+To specify the script file:
+
+```bash
+$ mrdb [option] file name
+```
+
+For example: Debugging sample.rb
+
+```bash
+$ mrdb sample.rb
+```
+
+You can execute the shell commands listed below:
+
+|command|description|
+|:-:|:--|
+|run|execute programs|
+|step|execute stepping|
+|continue|execute continuing program|
+|break|configure the breaking point|
+|delete|deleting the breaking points|
+|disable|disabling the breaking points|
+|enable|enabling the breaking points|
+|info breakpoints|showing list of the breaking points|
+|print|evaluating and printing the values of the mruby expressions in the script|
+|list|displaying the source cords|
+|help|showing help|
+|quit|terminating the mruby debugger|
+
+### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb
+
+You can debug the mruby binary files.
+
+#### 2.2.2.1 Debugging the binary files
+
+* notice
+To debug mruby binary files, you need to compile mruby files with option `-g`.
+
+```bash
+$ mrbc -g sample.rb
+```
+
+You can debug the mruby binary files with following command and the option `-b`.
+
+```bash
+$ mrdb -b sample.mrb
+```
+
+Then you can execute all debugger shell commands.
+
+#### Break Command
+
+You can use any breakpoint to stop the program by specifying the line number and method name.
+The breakpoint list will be displayed after you have set the breakpoint successfully.
+
+Usage:
+
+```
+break [file:]linenum
+b [file:]linenum
+break [class:]method
+b [class:]method
+```
+
+The breakpoint will be ordered in serial from 1.
+The number, which was given to the deleted breakpoint, will never be given to another breakpoint again.
+
+You can give multiple breakpoints to specified the line number and method.
+Be ware that breakpoint command will not check the validity of the class name and method name.
+
+You can get the current breakpoint information by the following options.
+
+breakpoint breakpoint number : file name. line number
+
+breakpoint breakpoint number : [class name,] method name
+
+#### Continue Command
+
+Usage:
+
+```
+continue [N]
+c [N]
+```
+
+N: the next breakpoint number
+
+When resuming the program, it will stop at breakpoint N (N-1 breakpoint will be ignored).
+
+When you run the `continue` command without specifying N, the program will be stopped at the next breakpoint.
+
+Example:
+
+```
+(foo.rb:1) continue 3
+```
+
+This will resume the program and stop it at the third breakpoint.
+
+#### Delete Command
+
+This will delete the specified breakpoint.
+
+Usage:
+
+```
+delete [breakpoint-no]
+d [breakpoint-no]
+```
+
+breakpoint-no: breakpoint number
+
+Example:
+
+```
+(foo.rb:1) delete
+```
+
+This will delete all of the breakpoints.
+
+```
+(foo.rb:1) delete 1 3
+```
+
+This will delete the breakpoint at 1 and 3.
+
+#### Disable Command
+
+This will disable the specified breakpoint.
+
+Usage:
+
+```
+disable [breakpoint-no]
+dis [breakpoint-no]
+```
+
+reappointing: breakpoint number
+
+Example:
+
+```
+(foo.rb:1) disable
+```
+
+Use `disable` if you would like to disable all of the breakpoints.
+
+```
+(foo.rb:1) disable 1 3
+```
+
+This will disable the breakpoints at 1 and 3.
+
+#### Enable Command
+
+This will enable the specified breakpoints.
+
+Usage:
+
+```
+enable [breakpoint-no]
+e [breakpoint-no]
+```
+
+breakpoint-no: breakpoint number
+
+Example:
+
+```
+(foo.rb:1) enable
+```
+
+Enabling all breakpoints
+```
+(foo.rb:1) enable 1 3
+```
+
+Enabling the breakpoint 1 and 3
+
+#### eval command
+
+Evaluating the string as source code and printing the value.
+
+Same as print command, please see print command.
+
+#### help command
+
+Displaying the help message.
+
+Usage:
+
+```
+help [command]
+h [command]
+```
+
+Typing `help` without any options will display the command list.
+
+#### Info Breakpoints Command
+
+Displaying the specified breakpoint information.
+
+Usage:
+
+```
+info breakpoints [breakpoint-no]
+i b [breakpoint-no]
+```
+
+breakpoint-no: breakpoint number
+
+Typing "info breakpoints" without ant option will display all breakpoint information.
+Example:
+
+```
+(sample.rb:1) info breakpoints
+Num Type Enb What
+1 breakpoint y at sample.rb:3 -> file name,line number
+2 breakpoint n in Sample_class:sample_class_method -> [class:]method name
+3 breakpoint y in sample_global_method
+```
+
+Displaying the specified breakpoint number:
+
+```
+(foo.rb:1) info breakpoints 1 3
+Num Type Enb What
+1 breakpoint y at sample.rb:3
+3 breakpoint y in sample_global_method
+```
+
+#### List Command
+
+To display the code of the source file.
+
+Usage:
+
+```
+list [filename:]first[,last]
+l [filename]:first[,last]
+```
+
+first: the opening row number
+last : the closing row number
+
+When you specify the `first`, but not the `last` option, you will receive 10 rows.
+When you do not specify both the `first` and `last` options, you will receive the next 10 rows.
+
+Example:
+
+```
+Specifying file name and first row number
+sample.rb:1) list sample2.rb:5
+```
+
+Specifying the file name and the first and last row number:
+
+```
+(sample.rb:1) list sample2.rb:6,7
+```
+
+#### Print Command
+
+Evaluating the string as source code and printing the value.
+
+Usage:
+
+```
+print [expr]
+p [expr]
+```
+
+expr: expression
+
+The expression is mandatory.
+The displayed expressions will be serially ordered from 1.
+If an exception occurs, the exception information will be displayed and the debugging will be continued.
+
+Example:
+
+```
+(sample.rb:1) print 1+2
+$1 = 3
+(sample.rb:1) print self
+$2 = main
+```
+
+Below is the case of the exception:
+
+```
+(sample.rb:1) print (1+2
+$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')'
+```
+
+#### Quit Command
+
+Quitting the debugger.
+
+Usage:
+
+```
+quit
+q
+```
+
+#### Run Command
+
+Running the program and stopping at the first breakpoint.
+
+Usage:
+
+```
+run
+r
+```
+
+#### Step Command
+
+This will run the program step by step.
+When the method and the block are invoked, the program will be stop at the first row.
+The program, which is developed in C, will be ignored.
diff --git a/web/server/h2o/libh2o/deps/mruby/doc/guides/gc-arena-howto.md b/web/server/h2o/libh2o/deps/mruby/doc/guides/gc-arena-howto.md
new file mode 100644
index 00000000..aff7360e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/doc/guides/gc-arena-howto.md
@@ -0,0 +1,177 @@
+# How to use `mrb_gc_arena_save()`/`mrb_gc_arena_restore()`/`mrb_gc_protect()`
+
+_This is an English translation of [Matz's blog post][matz blog post]
+written in Japanese._
+_Some parts are updated to reflect recent changes._
+[matz blog post]: http://www.rubyist.net/~matz/20130731.html
+
+When you are extending mruby using C language, you may encounter
+mysterious "arena overflow error" or memory leak or very slow
+execution speed. This is an error indicating overflow of "GC arena"
+implementing "conservative GC".
+
+GC (garbage collector) must ensure that object is "alive", in other
+words, that it is referenced by somewhere from program. This can be
+determined by checking if the object can be directly or indirectly
+referenced by root. The local variables, global variables and
+constants etc are root.
+
+If program execution is performed inside mruby VM, there is nothing to
+worry about because GC can access all roots owned by VM.
+
+The problem arises when executing C functions. The object referenced
+by C variable is also "alive", but mruby GC cannot aware of this, so
+it might mistakenly recognize the objects referenced by only C
+variables as dead.
+
+This can be a fatal bug if the GC tries to collect a live object.
+
+In CRuby, we scan C stack area, and use C variable as root to check
+whether object is alive or not. Of course, because we are accessing C
+stack just as memory region, we never know it is an integer or a
+pointer. We workaround this by assuming that if it looks like a
+pointer, then assume it as a pointer. We call it "conservative".
+
+By the way, CRuby's "conservative GC" has some problems.
+
+The biggest problem is we have no way to access to the stack area in
+portable way. Therefore, we cannot use this method if we'd like to
+implement highly portable runtime, like mruby.
+
+So we came up with an another plan to implement "conservative GC" in mruby.
+
+Again, the problem is when an object which was created in C function, becomes
+no longer referenced in the Ruby world, and cannot be treated as garbage.
+
+In mruby, we recognize all objects created in C function are alive.
+Then we have no problem such as confusing a live object as dead.
+
+This means that because we cannot collect truly dead object, we may
+lose efficiency, but as a trade-off the GC itself is highly portable.
+We can say goodbye to the problem that GC deletes live objects due to
+optimization which sometimes occurs in CRuby.
+
+According to this idea, we have a table, called "GC arena", which
+remembers objects created in C function.
+
+The arena is stack structure, when C function execution is returned to mruby
+VM, all objects registered in the arena are popped.
+
+This works very well, but can cause another problem: "arena overflow error" or
+memory leak.
+
+As of this writing, mruby automatically extend arena to remember
+objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in
+doc/guides/mrbconf.md).
+
+If you create many objects in C functions, memory usage will increase, since
+GC never kick in. This memory usage may look like memory leak, but will also
+make execution slower as more memory will need to be allocated.
+
+With the build time configuration, you can limit the maximum size of
+arena (e.g., 100). Then if you create many objects, arena overflows,
+thus you will get an "arena overflow error".
+
+To workaround these problems, we have `mrb_gc_arena_save()` and
+`mrb_gc_arena_restore()` functions.
+
+`int mrb_gc_arena_save(mrb)` returns the current position of the stack
+top of GC arena, and `void mrb_gc_arena_restore(mrb, idx)` sets the
+stack top position to back to given `idx`.
+
+We can use them like this:
+
+```c
+int arena_idx = mrb_gc_arena_save(mrb);
+
+// ...create objects...
+mrb_gc_arena_restore(mrb, arena_idx);
+
+```
+
+In mruby, C function calls are surrounded by this save/restore, but we
+can further optimize memory usage by surrounding save/restore, and can
+avoid creating arena overflow bugs.
+
+Let's take a real example. Here is the source code of `Array#inspect`:
+
+```c
+static mrb_value
+inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
+{
+ mrb_int i;
+ mrb_value s, arystr;
+ char head[] = { '[' };
+ char sep[] = { ',', ' ' };
+ char tail[] = { ']' };
+
+ /* check recursive */
+ for(i=0; i<RARRAY_LEN(list); i++) {
+ if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
+ return mrb_str_new(mrb, "[...]", 5);
+ }
+ }
+
+ mrb_ary_push(mrb, list, ary);
+
+ arystr = mrb_str_new_capa(mrb, 64);
+ mrb_str_cat(mrb, arystr, head, sizeof(head));
+
+ for(i=0; i<RARRAY_LEN(ary); i++) {
+ int ai = mrb_gc_arena_save(mrb);
+
+ if (i > 0) {
+ mrb_str_cat(mrb, arystr, sep, sizeof(sep));
+ }
+ if (mrb_array_p(RARRAY_PTR(ary)[i])) {
+ s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
+ }
+ else {
+ s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
+ }
+ mrb_str_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ mrb_str_cat(mrb, arystr, tail, sizeof(tail));
+ mrb_ary_pop(mrb, list);
+
+ return arystr;
+}
+```
+
+This is a real example, so a little bit complicated, but bear with me.
+The essence of `Array#inspect` is that after stringifying each element
+of array using `inspect` method, we join them together so that we can
+get `inspect` representation of the entire array.
+
+After the `inspect` representation is created, we no longer require the
+individual string representation. This means that we don't have to register
+these temporal objects into GC arena.
+
+Therefore, in order to keep the arena size small; the `ary_inspect()` function
+will do the following:
+
+* save the position of the stack top using `mrb_gc_arena_save()`.
+* get `inspect` representation of each element.
+* append it to the constructing entire `inspect` representation of array.
+* restore stack top position using `mrb_gc_arena_restore()`.
+
+Please note that the final `inspect` representation of entire array
+was created before the call of `mrb_gc_arena_restore()`. Otherwise,
+required temporal object may be deleted by GC.
+
+We may have a usecase where after creating many temporal objects, we'd
+like to keep some of them. In this case, we cannot use the same idea
+in `ary_inspect()` like appending objects to existing one.
+Instead, after `mrb_gc_arena_restore()`, we must re-register the objects we
+want to keep in the arena using `mrb_gc_protect(mrb, obj)`.
+Use `mrb_gc_protect()` with caution because it could also lead to an "arena
+overflow error".
+
+We must also mention that when `mrb_funcall` is called in top level, the return
+value is also registered to GC arena, so repeated use of `mrb_funcall` may
+eventually lead to an "arena overflow error".
+
+Use `mrb_gc_arena_save()` and `mrb_gc_arena_restore()` or possible use of
+`mrb_gc_protect()` to workaround this.
diff --git a/web/server/h2o/libh2o/deps/mruby/doc/guides/mrbconf.md b/web/server/h2o/libh2o/deps/mruby/doc/guides/mrbconf.md
new file mode 100644
index 00000000..f957f8ce
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/doc/guides/mrbconf.md
@@ -0,0 +1,146 @@
+# mruby configuration macros.
+
+## How to use these macros.
+You can use mrbconfs with following ways:
+* Write them in `mrbconf.h`.
+ * Using compiler flags is preferred when building a cross binaries or multiple mruby binaries
+ since it's easier to use different mrbconf per each `MRuby::Build`.
+ * Most flags can be enabled by just commenting in.
+* Pass them as compiler flags.
+ * Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`)
+ changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed.
+
+## stdio setting.
+`MRB_DISABLE_STDIO`
+* When defined `<stdio.h>` functions won't be used.
+* Some features will be disabled when this is enabled:
+ * `mrb_irep` load/dump from/to file.
+ * Compiling mruby script from file.
+ * Printing features in **src/print.c**.
+
+## Debug macros.
+`MRB_ENABLE_DEBUG_HOOK`
+* When defined code fetch hook and debug OP hook will be enabled.
+* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`.
+* Fetch hook will be called before any OP.
+* Debug OP hook will be called when dispatching `OP_DEBUG`.
+
+`MRB_DEBUG`
+* When defined `mrb_assert*` macro will be defined with macros from `<assert.h>`.
+* Could be enabled via `enable_debug` method of `MRuby::Build`.
+
+## Stack configuration
+
+`MRB_STACK_EXTEND_DOUBLING`
+* If defined doubles the stack size when extending it.
+* Else extends stack with `MRB_STACK_GROWTH`.
+
+`MRB_STACK_GROWTH`
+* Default value is `128`.
+* Used in stack extending.
+* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined.
+
+`MRB_STACK_MAX`
+* Default value is `0x40000 - MRB_STACK_GROWTH`.
+* Raises `RuntimeError` when stack size exceeds this value.
+
+## Primitive type configuration.
+
+`MRB_USE_FLOAT`
+* When defined single precision floating point type(C type `float`) is used as `mrb_float`.
+* Else double precision floating point type(C type `double`) is used as `mrb_float`.
+
+`MRB_INT16`
+* When defined `int16_t` will be defined as `mrb_int`.
+* Conflicts with `MRB_INT64`.
+
+`MRB_INT64`
+* When defined `int64_t` will be defined as `mrb_int`.
+* Conflicts with `MRB_INT16`.
+* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer)
+will be defined as `mrb_int`.
+
+## Garbage collector configuration.
+
+`MRB_GC_STRESS`
+* When defined full GC is emitted per each `RBasic` allocation.
+* Mainly used in memory manager debugging.
+
+`MRB_GC_TURN_OFF_GENERATIONAL`
+* When defined turns generational GC by default.
+
+`MRB_GC_FIXED_ARENA`
+* When defined used fixed size GC arena.
+* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`.
+* Useful tracking unnecessary mruby object allocation.
+
+`MRB_GC_ARENA_SIZE`
+* Default value is `100`.
+* Ignored when `MRB_GC_FIXED_ARENA` isn't defined.
+* Defines fixed GC arena size.
+
+`MRB_HEAP_PAGE_SIZE`
+* Defines value is `1024`.
+* Specifies number of `RBasic` per each heap page.
+
+## Memory pool configuration.
+
+`POOL_ALIGNMENT`
+* Default value is `4`.
+* If you're allocating data types that requires alignment more than default value define the
+largest value of required alignment.
+
+`POOL_PAGE_SIZE`
+* Default value is `16000`.
+* Specifies page size of pool page.
+* Smaller the value is increases memory overhead.
+
+## State atexit configuration.
+
+`MRB_FIXED_STATE_ATEXIT_STACK`
+* If defined enables fixed size `mrb_state` atexit stack.
+* Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds
+`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value.
+
+`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`
+* Default value is `5`.
+* If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored.
+
+## `mrb_value` configuration.
+
+`MRB_ENDIAN_BIG`
+* If defined compiles mruby for big endian machines.
+* Used in `MRB_NAN_BOXING`.
+* Some mrbgem use this mrbconf.
+
+`MRB_NAN_BOXING`
+* If defined represent `mrb_value` in boxed `double`.
+* Conflicts with `MRB_USE_FLOAT`.
+
+`MRB_WORD_BOXING`
+* If defined represent `mrb_value` as a word.
+* If defined `Float` will be a mruby object with `RBasic`.
+
+## Instance variable configuration.
+`MRB_IV_SEGMENT_SIZE`
+* Default value is `4`.
+* Specifies size of each segment in segment list.
+
+## Other configuration.
+`MRB_UTF8_STRING`
+* Adds UTF-8 encoding support to character-oriented String instance methods.
+* If it isn't defined, they only support the US-ASCII encoding.
+
+`MRB_FUNCALL_ARGC_MAX`
+* Default value is `16`.
+* Specifies 4th argument(`argc`) max value of `mrb_funcall`.
+* Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`.
+
+`KHASH_DEFAULT_SIZE`
+* Default value is `32`.
+* Specifies default size of khash table bucket.
+* Used in `kh_init_ ## name` function.
+
+`MRB_STR_BUF_MIN_SIZE`
+* Default value is `128`.
+* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function..
diff --git a/web/server/h2o/libh2o/deps/mruby/doc/guides/mrbgems.md b/web/server/h2o/libh2o/deps/mruby/doc/guides/mrbgems.md
new file mode 100644
index 00000000..258f405b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/doc/guides/mrbgems.md
@@ -0,0 +1,340 @@
+# mrbgems
+
+mrbgems is a library manager to integrate C and Ruby extension in an easy and
+standardised way into mruby.
+
+## Usage
+
+By default mrbgems is currently deactivated. As soon as you add a GEM to your
+build configuration (i.e. *build_config.rb*), mrbgems will be activated and the
+extension integrated.
+
+To add a GEM into the *build_config.rb* add the following line for example:
+```ruby
+conf.gem '/path/to/your/gem/dir'
+```
+
+You can also use a relative path which would be relative from the mruby root:
+```ruby
+conf.gem 'examples/mrbgems/ruby_extension_example'
+```
+
+A remote GIT repository location for a GEM is also supported:
+```ruby
+conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master'
+conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
+conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
+```
+
+To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option:
+```ruby
+conf.gem :mgem => 'mruby-yaml'
+conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted
+```
+
+If there is missing dependencies, mrbgem dependencies solver will reference
+mrbgem from core or mgem-list.
+
+To pull all gems from remote GIT repository on build, call ```./minirake -p```,
+or ```./minirake --pull-gems```.
+
+NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version.
+
+## GemBox
+
+There are instances when you wish to add a collection of mrbgems into mruby at
+once, or be able to substitute mrbgems based on configuration, without having to
+add each gem to the *build_config.rb* file. A packaged collection of mrbgems
+is called a GemBox. A GemBox is a file that contains a list of mrbgems to load
+into mruby, in the same format as if you were adding them to *build_config.rb*
+via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are
+loaded into mruby via `config.gembox 'boxname'`.
+
+Below we have created a GemBox containing *mruby-time* and *mrbgems-example*:
+```ruby
+MRuby::GemBox.new do |conf|
+ conf.gem "#{root}/mrbgems/mruby-time"
+ conf.gem :github => 'masuidrive/mrbgems-example'
+end
+```
+
+As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox
+must be saved with a *.gembox* extension inside the *mrbgems* directory to to be
+picked up by mruby.
+
+To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems*
+directory in mruby, and add the following to our *build_config.rb* file inside
+the build block:
+```ruby
+conf.gembox 'custom'
+```
+This will cause the *custom* GemBox to be read in during the build process,
+adding *mruby-time* and *mrbgems-example* to the build.
+
+If you want, you can put GemBox outside of mruby directory. In that case you must
+specify an absolute path like below.
+```ruby
+conf.gembox "#{ENV["HOME"]}/mygemboxes/custom"
+```
+
+There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox)
+and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox
+contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox)
+contains every gem found in the *mrbgems* directory.
+
+## GEM Structure
+
+The maximal GEM structure looks like this:
+
+ +- GEM_NAME <- Name of GEM
+ |
+ +- include/ <- Header for Ruby extension (will exported)
+ |
+ +- mrblib/ <- Source for Ruby extension
+ |
+ +- src/ <- Source for C extension
+ |
+ +- test/ <- Test code (Ruby)
+ |
+ +- mrbgem.rake <- GEM Specification
+ |
+ +- README.md <- Readme for GEM
+
+The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src*
+contains C/C++ files to extend mruby. The folder *include* contains C/C++ header
+files. The folder *test* contains C/C++ and pure Ruby files for testing purposes
+which will be used by `mrbtest`. *mrbgem.rake* contains the specification
+to compile C and Ruby files. *README.md* is a short description of your GEM.
+
+## Build process
+
+mrbgems expects a specification file called *mrbgem.rake* inside of your
+GEM directory. A typical GEM specification could look like this for example:
+```ruby
+MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Example mrbgem using C and ruby'
+end
+```
+
+The mrbgems build process will use this specification to compile Object and Ruby
+files. The compilation results will be added to *lib/libmruby.a*. This file exposes
+the GEM functionality to tools like `mruby` and `mirb`.
+
+The following properties can be set inside of your `MRuby::Gem::Specification` for
+information purpose:
+
+* `spec.license` or `spec.licenses` (A single license or a list of them under which this GEM is licensed)
+* `spec.author` or `spec.authors` (Developer name or a list of them)
+* `spec.version` (Current version)
+* `spec.description` (Detailed description)
+* `spec.summary`
+ * One line short description of mrbgem.
+ * Printed in build summary of rake when set.
+* `spec.homepage` (Homepage)
+* `spec.requirements` (External requirements as information for user)
+
+The `license` and `author` properties are required in every GEM!
+
+In case your GEM is depending on other GEMs please use
+`spec.add_dependency(gem, *requirements[, default_get_info])` like:
+```ruby
+MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+
+ # Add GEM dependency mruby-parser.
+ # The version must be between 1.0.0 and 1.5.2 .
+ spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2')
+
+ # Use any version of mruby-uv from github.
+ spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv')
+
+ # Use latest mruby-onig-regexp from github. (version requirements can be omitted)
+ spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp')
+
+ # You can add extra mgems active only on test
+ spec.add_test_dependency('mruby-process', :github => 'iij/mruby-process')
+end
+```
+
+The version requirements and default gem information are optional.
+
+Version requirement supports following operators:
+* '=': is equal
+* '!=': is not equal
+* '>': is greater
+* '<': is lesser
+* '>=': is equal or greater
+* '<=': is equal or lesser
+* '~>': is equal or greater and is lesser than the next major version
+ * example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0'
+ * example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0'
+
+When more than one version requirements is passed, the dependency must satisfy all of it.
+
+You can have default gem to use as depedency when it's not defined in *build_config.rb*.
+When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information.
+Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location.
+
+When a special version of depedency is required,
+use `MRuby::Build#gem` in *build_config.rb* to override default gem.
+
+If you have conflicting GEMs use the following method:
+* `spec.add_conflict(gem, *requirements)`
+ * The `requirements` argument is same as in `add_dependency` method.
+
+like following code:
+```ruby
+MRuby::Gem::Specification.new 'some-regexp-binding' do |spec|
+ spec.license = 'BSD'
+ spec.author = 'John Doe'
+
+ spec.add_conflict 'mruby-onig-regexp', '> 0.0.0'
+ spec.add_conflict 'mruby-hs-regexp'
+ spec.add_conflict 'mruby-pcre-regexp'
+ spec.add_conflict 'mruby-regexp-pcre'
+end
+```
+
+In case your GEM has more complex build requirements you can use
+the following options additionally inside of your GEM specification:
+
+* `spec.cc.flags` (C compiler flags)
+* `spec.cc.defines` (C compiler defines)
+* `spec.cc.include_paths` (C compiler include paths)
+* `spec.linker.flags` (Linker flags)
+* `spec.linker.libraries` (Linker libraries)
+* `spec.linker.library_paths` (Linker additional library path)
+* `spec.bins` (Generate binary file)
+* `spec.rbfiles` (Ruby files to compile)
+* `spec.objs` (Object files to compile)
+* `spec.test_rbfiles` (Ruby test files for integration into mrbtest)
+* `spec.test_objs` (Object test files for integration into mrbtest)
+* `spec.test_preload` (Initialization files for mrbtest)
+
+You also can use `spec.mruby.cc` and `spec.mruby.linker` to add extra global parameters for compiler and linker.
+
+### include_paths and dependency
+
+Your GEM can export include paths to another GEMs that depends on your GEM.
+By default, `/...absolute path.../{GEM_NAME}/include` will be exported.
+So it is recommended not to put GEM's local header files on include/.
+
+These exports are retroactive.
+For example: when B depends to C and A depends to B, A will get include paths exported by C.
+
+Exported include_paths are automatically appended to GEM local include_paths by Minirake.
+You can use `spec.export_include_paths` accessor if you want more complex build.
+
+
+## C Extension
+
+mruby can be extended with C. This is possible by using the C API to
+integrate C libraries into mruby.
+
+### Preconditions
+
+mrbgems expects that you have implemented a C method called
+`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced
+by the name of your GEM. If you call your GEM *c_extension_example*, your
+initialisation method could look like this:
+```C
+void
+mrb_c_extension_example_gem_init(mrb_state* mrb) {
+ struct RClass *class_cextension = mrb_define_module(mrb, "CExtension");
+ mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
+}
+```
+
+### Finalize
+
+mrbgems expects that you have implemented a C method called
+`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced
+by the name of your GEM. If you call your GEM *c_extension_example*, your
+finalizer method could look like this:
+
+```C
+void
+mrb_c_extension_example_gem_final(mrb_state* mrb) {
+ free(someone);
+}
+```
+
+### Example
+
+ +- c_extension_example/
+ |
+ +- src/
+ | |
+ | +- example.c <- C extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for C extension
+ |
+ +- mrbgem.rake <- GEM specification
+ |
+ +- README.md
+
+## Ruby Extension
+
+mruby can be extended with pure Ruby. It is possible to override existing
+classes or add new ones in this way. Put all Ruby files into the *mrblib*
+folder.
+
+
+### Pre-Conditions
+
+none
+
+### Example
+
+ +- ruby_extension_example/
+ |
+ +- mrblib/
+ | |
+ | +- example.rb <- Ruby extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for Ruby extension
+ |
+ +- mrbgem.rake <- GEM specification
+ |
+ +- README.md
+
+## C and Ruby Extension
+
+mruby can be extended with C and Ruby at the same time. It is possible to
+override existing classes or add new ones in this way. Put all Ruby files
+into the *mrblib* folder and all C files into the *src* folder.
+
+mruby codes under *mrblib* directory would be executed after gem init C
+function is called. Make sure *mruby script* depends on *C code* and
+*C code* doesn't depend on *mruby script*.
+
+### Pre-Conditions
+
+See C and Ruby example.
+
+### Example
+
+ +- c_and_ruby_extension_example/
+ |
+ +- mrblib/
+ | |
+ | +- example.rb <- Ruby extension source
+ |
+ +- src/
+ | |
+ | +- example.c <- C extension source
+ |
+ +- test/
+ | |
+ | +- example.rb <- Test code for C and Ruby extension
+ |
+ +- mrbgem.rake <- GEM specification
+ |
+ +- README.md
diff --git a/web/server/h2o/libh2o/deps/mruby/doc/limitations.md b/web/server/h2o/libh2o/deps/mruby/doc/limitations.md
new file mode 100644
index 00000000..db8db9a5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/doc/limitations.md
@@ -0,0 +1,208 @@
+# Limitations and Differences
+
+The philosophy of mruby is to be a lightweight implementation of
+the Ruby ISO standard. These two objectives are partially contradicting.
+Ruby is an expressive language with complex implementation details which
+are difficult to implement in a lightweight manner. To cope with this,
+limitations to the "Ruby Compatibility" are defined.
+
+This document is collecting these limitations.
+
+## Integrity
+
+This document does not contain a complete list of limitations.
+Please help to improve it by submitting your findings.
+
+
+## ```1/2``` gives ```0.5```
+
+Since mruby does not have ```Bignum```, bigger integers are represented
+by ```Float``` numbers. To enhance interoperability between ```Fixnum```
+and ```Float```, mruby provides ```Float#upto``` and other iterating
+methods for the ```Float``` class. As a side effect, ```1/2``` gives ```0.5```
+not ```0```.
+
+## ```Array``` passed to ```puts```
+
+Passing an Array to ```puts``` results in different output.
+
+```ruby
+puts [1,2,3]
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+```
+1
+2
+3
+```
+
+#### mruby [1.3.0 (2017-7-4)]
+
+```
+[1, 2, 3]
+```
+
+## ```Kernel.raise``` in rescue clause
+
+```Kernel.raise``` without arguments does not raise the current exception within
+a rescue clause.
+
+```ruby
+begin
+ 1 / 0
+rescue
+ raise
+end
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+```ZeroDivisionError``` is raised.
+
+#### mruby [1.3.0 (2017-7-4)]
+
+No exception is raised.
+
+## Check of infinite recursion
+
+mruby does not check infinite recursion across C extensions.
+
+```ruby
+def test; eval 'test'; end; test
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+```SystemStackError``` is raised.
+
+#### mruby [1.3.0 (2017-7-4)]
+
+Segmentation fault.
+
+## Fiber execution can't cross C function boundary
+
+mruby's ```Fiber``` is implemented in a similar way to Lua's co-routine. This
+results in the consequence that you can't switch context within C functions.
+Only exception is ```mrb_fiber_yield``` at return.
+
+## ```Array``` does not support instance variables
+
+To reduce memory consumption ```Array``` does not support instance variables.
+
+```ruby
+class Liste < Array
+ def initialize(str = nil)
+ @feld = str
+ end
+end
+
+p Liste.new "foobar"
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+``` [] ```
+
+#### mruby [1.3.0 (2017-7-4)]
+
+```ArgumentError``` is raised.
+
+## Method visibility
+
+For simplicity reasons no method visibility (public/private/protected) is
+supported.
+
+```ruby
+class VisibleTest
+
+ def public_method; end
+
+ private
+ def private_method; end
+
+end
+
+p VisibleTest.new.respond_to?(:private_method, false)
+p VisibleTest.new.respond_to?(:private_method, true)
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+```
+false
+true
+```
+
+#### mruby [1.3.0 (2017-7-4)]
+
+```
+true
+true
+```
+
+## defined?
+
+The ```defined?``` keyword is considered too complex to be fully
+implemented. It is recommended to use ```const_defined?``` and
+other reflection methods instead.
+
+```ruby
+defined?(Foo)
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+```
+nil
+```
+
+#### mruby [1.3.0 (2017-7-4)]
+
+```NameError``` is raised.
+
+## ```alias``` on global variables
+
+Aliasing a global variable works in CRuby but is not part
+of the ISO standard.
+
+```ruby
+alias $a $__a__
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+``` nil ```
+
+#### mruby [1.3.0 (2017-7-4)]
+
+Syntax error
+
+## Operator modification
+
+An operator can't be overwritten by the user.
+
+```ruby
+class String
+ def +
+ end
+end
+
+'a' + 'b'
+```
+
+#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
+
+```ArgumentError``` is raised.
+The re-defined ```+``` operator does not accept any arguments.
+
+#### mruby [1.3.0 (2017-7-4)]
+
+``` 'ab' ```
+Behavior of the operator wasn't changed.
+
+## ```Kernel.binding``` missing
+
+```Kernel.binding``` is not implemented as it is not in the
+ISO standard.
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md
new file mode 100644
index 00000000..0b428b0b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/README.md
@@ -0,0 +1,4 @@
+C and Ruby Extension Example
+=========
+
+This is an example gem which implements a C and Ruby extension.
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake
new file mode 100644
index 00000000..6b4595b3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake
@@ -0,0 +1,23 @@
+MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+
+ # Add compile flags
+ # spec.cc.flags << ''
+
+ # Add cflags to all
+ # spec.mruby.cc.flags << '-g'
+
+ # Add libraries
+ # spec.linker.libraries << 'external_lib'
+
+ # Default build files
+ # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
+ # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
+ # spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
+ # spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
+ # spec.test_preload = 'test/assert.rb'
+
+ # Values accessible as TEST_ARGS inside test scripts
+ # spec.test_args = {'tmp_dir' => Dir::tmpdir}
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb
new file mode 100644
index 00000000..d3899c30
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb
@@ -0,0 +1,5 @@
+module CRubyExtension
+ def CRubyExtension.ruby_method
+ puts "A Ruby Extension"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c
new file mode 100644
index 00000000..7b780d01
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c
@@ -0,0 +1,20 @@
+#include <mruby.h>
+#include <stdio.h>
+
+static mrb_value
+mrb_c_method(mrb_state *mrb, mrb_value self)
+{
+ puts("A C Extension");
+ return self;
+}
+
+void
+mrb_c_and_ruby_extension_example_gem_init(mrb_state* mrb) {
+ struct RClass *class_cextension = mrb_define_module(mrb, "CRubyExtension");
+ mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
+}
+
+void
+mrb_c_and_ruby_extension_example_gem_final(mrb_state* mrb) {
+ /* finalizer */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb
new file mode 100644
index 00000000..fffad710
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb
@@ -0,0 +1,7 @@
+assert('C and Ruby Extension Example 1') do
+ CRubyExtension.respond_to? :c_method
+end
+
+assert('C and Ruby Extension Example 2') do
+ CRubyExtension.respond_to? :ruby_method
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/README.md b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/README.md
new file mode 100644
index 00000000..3803c206
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/README.md
@@ -0,0 +1,4 @@
+C Extension Example
+=========
+
+This is an example gem which implements a C extension.
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/mrbgem.rake
new file mode 100644
index 00000000..6e4c5b16
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/mrbgem.rake
@@ -0,0 +1,23 @@
+MRuby::Gem::Specification.new('c_extension_example') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+
+ # Add compile flags
+ # spec.cc.flags << '-g'
+
+ # Add cflags to all
+ # spec.mruby.cc.flags << '-g'
+
+ # Add libraries
+ # spec.linker.libraries << 'external_lib'
+
+ # Default build files
+ # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
+ # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
+ # spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
+ # spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
+ # spec.test_preload = 'test/assert.rb'
+
+ # Values accessible as TEST_ARGS inside test scripts
+ # spec.test_args = {'tmp_dir' => Dir::tmpdir}
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/src/example.c b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/src/example.c
new file mode 100644
index 00000000..e70ee42f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/src/example.c
@@ -0,0 +1,20 @@
+#include <mruby.h>
+#include <stdio.h>
+
+static mrb_value
+mrb_c_method(mrb_state *mrb, mrb_value self)
+{
+ puts("A C Extension");
+ return self;
+}
+
+void
+mrb_c_extension_example_gem_init(mrb_state* mrb) {
+ struct RClass *class_cextension = mrb_define_module(mrb, "CExtension");
+ mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE());
+}
+
+void
+mrb_c_extension_example_gem_final(mrb_state* mrb) {
+ /* finalizer */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.c b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.c
new file mode 100644
index 00000000..ab410333
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.c
@@ -0,0 +1,7 @@
+#include <mruby.h>
+
+void
+mrb_c_extension_example_gem_test(mrb_state *mrb)
+{
+ /* test initializer in C */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.rb b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.rb
new file mode 100644
index 00000000..367d1802
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/c_extension_example/test/example.rb
@@ -0,0 +1,3 @@
+assert('C Extension Example') do
+ CExtension.respond_to? :c_method
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/README.md b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/README.md
new file mode 100644
index 00000000..906a0d8f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/README.md
@@ -0,0 +1,4 @@
+Pure Ruby Extension Example
+=========
+
+This is an example gem which implements a pure Ruby extension.
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake
new file mode 100644
index 00000000..6e5a5b72
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrbgem.rake
@@ -0,0 +1,25 @@
+MRuby::Gem::Specification.new('ruby_extension_example') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+
+ # Add compile flags
+ # spec.cc.flags << ''
+
+ # Add cflags to all
+ # spec.mruby.cc.flags << '-g'
+
+ # Add libraries
+ # spec.linker.libraries << 'external_lib'
+
+ spec.add_dependency('mruby-print', :core => 'mruby-print')
+
+ # Default build files
+ # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb")
+ # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
+ # spec.test_rbfiles = Dir.glob("#{dir}/test/*.rb")
+ # spec.test_objs = Dir.glob("#{dir}/test/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) }
+ # spec.test_preload = 'test/assert.rb'
+
+ # Values accessible as TEST_ARGS inside test scripts
+ # spec.test_args = {'tmp_dir' => Dir::tmpdir}
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb
new file mode 100644
index 00000000..b07a2b58
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb
@@ -0,0 +1,5 @@
+class RubyExtension
+ def RubyExtension.ruby_method
+ puts "A Ruby Extension"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/test/example.rb b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/test/example.rb
new file mode 100644
index 00000000..0c1b6346
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/mrbgems/ruby_extension_example/test/example.rb
@@ -0,0 +1,3 @@
+assert('Ruby Extension Example') do
+ RubyExtension.respond_to? :ruby_method
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_ArduinoDue.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_ArduinoDue.rb
new file mode 100644
index 00000000..527aaa4f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_ArduinoDue.rb
@@ -0,0 +1,90 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
+# Cross Compiling configuration for Arduino Due
+# http://arduino.cc/en/Main/ArduinoBoardDue
+#
+# Requires Arduino IDE >= 1.5
+MRuby::CrossBuild.new("ArduinoDue") do |conf|
+ toolchain :gcc
+
+ # Mac OS X, Arduino IDE <= 1.5.6
+ # ARDUINO_PATH = '/Applications/Arduino.app/Contents/Resources/Java'
+ # Mac OS X, Arduino IDE >= 1.5.7
+ # ARDUINO_PATH = '/Applications/Arduino.app/Contents/Java'
+ # GNU Linux
+ ARDUINO_PATH = '/opt/arduino'
+ # Arduino IDE <= 1.5.6
+ BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/g++_arm_none_eabi/bin"
+ # Arduino IDE >= 1.5.7
+ # BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin"
+ SAM_PATH = "#{ARDUINO_PATH}/hardware/arduino/sam"
+ TARGET_PATH = "#{SAM_PATH}/variants/arduino_due_x"
+
+ conf.cc do |cc|
+ cc.command = "#{BIN_PATH}/arm-none-eabi-gcc"
+ cc.include_paths << ["#{SAM_PATH}/system/libsam", "#{SAM_PATH}/system/CMSIS/CMSIS/Include/",
+ "#{SAM_PATH}/system/CMSIS/Device/ATMEL/",
+ "#{SAM_PATH}/cores/arduino", "#{SAM_PATH}/libraries","#{TARGET_PATH}"]
+ cc.flags = %w(-g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500
+ -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=156 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM
+ -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due")
+ cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
+
+ #configuration for low memory environment
+ cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
+ cc.defines << %w(KHASH_DEFAULT_SIZE=8)
+ cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
+ cc.defines << %w(MRB_GC_STRESS)
+ #cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
+ #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
+ end
+
+ conf.cxx do |cxx|
+ cxx.command = conf.cc.command.dup
+ cxx.include_paths = conf.cc.include_paths.dup
+ cxx.flags = conf.cc.flags.dup
+ cxx.flags << %w(-fno-rtti -fno-exceptions)
+ cxx.defines = conf.cc.defines.dup
+ cxx.compile_options = conf.cc.compile_options.dup
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = "#{BIN_PATH}/arm-none-eabi-ar"
+ archiver.archive_options = 'rcs %{outfile} %{objs}'
+ end
+
+ #no executables
+ conf.bins = []
+
+ #do not build executable test
+ conf.build_mrbtest_lib_only
+
+ #disable C++ exception
+ conf.disable_cxx_exception
+
+ #gems from core
+ conf.gem :core => "mruby-print"
+ conf.gem :core => "mruby-math"
+ conf.gem :core => "mruby-enum-ext"
+
+ #light-weight regular expression
+ conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
+
+ #Arduino API
+ #conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelEdison.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelEdison.rb
new file mode 100644
index 00000000..8fa3aa0c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelEdison.rb
@@ -0,0 +1,69 @@
+# Cross-compiling setup for Intel Edison (poky linux) platform
+# Get SDK from here: https://software.intel.com/en-us/iot/hardware/edison/downloads
+# REMEMBER to check and update the SDK root in the constant POKY_EDISON_PATH
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+ conf.gembox 'default'
+ conf.cc.defines = %w(ENABLE_READLINE)
+ conf.gembox 'default'
+
+ #lightweight regular expression
+ conf.gem :github => "pbosetti/mruby-hs-regexp", :branch => "master"
+
+end
+
+# Define cross build settings
+MRuby::CrossBuild.new('core2-32-poky-linux') do |conf|
+ toolchain :gcc
+
+ # Mac OS X
+ #
+ POKY_EDISON_PATH = '/opt/poky-edison/1.7.2'
+
+ POKY_EDISON_SYSROOT = "#{POKY_EDISON_PATH}/sysroots/core2-32-poky-linux"
+ POKY_EDISON_X86_PATH = "#{POKY_EDISON_PATH}/sysroots/i386-pokysdk-darwin"
+ POKY_EDISON_BIN_PATH = "#{POKY_EDISON_X86_PATH}/usr/bin/i586-poky-linux"
+
+
+ conf.cc do |cc|
+ cc.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-gcc"
+ cc.include_paths << ["#{POKY_EDISON_SYSROOT}/usr/include", "#{POKY_EDISON_X86_PATH}/usr/include"]
+ cc.flags = %w(-m32 -march=core2 -mtune=core2 -msse3 -mfpmath=sse -mstackrealign -fno-omit-frame-pointer)
+ cc.flags << %w(-O2 -pipe -g -feliminate-unused-debug-types)
+ cc.flags << "--sysroot=#{POKY_EDISON_SYSROOT}"
+ cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
+ cc.defines = %w(ENABLE_READLINE)
+ end
+
+ conf.cxx do |cxx|
+ cxx.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-g++"
+ cxx.include_paths = conf.cc.include_paths.dup
+ cxx.include_paths << ["#{POKY_EDISON_SYSROOT}/usr/include/c++/4.9.1"]
+ cxx.flags = conf.cc.flags.dup
+ cxx.defines = conf.cc.defines.dup
+ cxx.compile_options = conf.cc.compile_options.dup
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-ar"
+ archiver.archive_options = 'rcs %{outfile} %{objs}'
+ end
+
+ conf.linker do |linker|
+ linker.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-g++"
+ linker.flags = %w(-m32 -march=i586)
+ linker.flags << "--sysroot=#{POKY_EDISON_SYSROOT}"
+ linker.flags << %w(-O1)
+ linker.libraries = %w(m pthread)
+ end
+
+ #do not build executable test
+ conf.build_mrbtest_lib_only
+
+ conf.gembox 'default'
+
+ #lightweight regular expression
+ conf.gem :github => "pbosetti/mruby-hs-regexp", :branch => "master"
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelGalileo.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelGalileo.rb
new file mode 100644
index 00000000..42f800d9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_IntelGalileo.rb
@@ -0,0 +1,106 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
+
+# Cross Compiling configuration for Intel Galileo on Arduino environment
+# http://arduino.cc/en/ArduinoCertified/IntelGalileo
+#
+# Requires Arduino IDE for Intel Galileo
+MRuby::CrossBuild.new("Galileo") do |conf|
+ toolchain :gcc
+
+ # Mac OS X
+ # Assume you renamed Arduino.app to Arduino_Galileo.app
+ GALILEO_ARDUINO_PATH = '/Applications/Arduino_Galileo.app/Contents/Resources/Java'
+ # GNU Linux
+ #ARDUINO_GALILEO_PATH = '/opt/arduino'
+
+ GALILEO_BIN_PATH = "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i386-pokysdk-darwin/usr/bin/i586-poky-linux-uclibc"
+ GALILEO_SYSROOT = "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc"
+ GALILEO_X86_PATH = "#{GALILEO_ARDUINO_PATH}/hardware/arduino/x86"
+
+
+ conf.cc do |cc|
+ cc.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-gcc"
+ cc.include_paths << ["#{GALILEO_X86_PATH}/cores/arduino", "#{GALILEO_X86_PATH}/variants/galileo_fab_d"]
+ cc.flags = %w(-m32 -march=i586 -c -g -Os -w
+ -ffunction-sections -fdata-sections -MMD -DARDUINO=153)
+ cc.flags << "--sysroot=#{GALILEO_SYSROOT}"
+ cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
+ end
+
+ conf.cxx do |cxx|
+ cxx.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-g++"
+ cxx.include_paths = conf.cc.include_paths.dup
+ cxx.include_paths << "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++"
+ cxx.include_paths << "#{GALILEO_ARDUINO_PATH}/hardware/tools/x86/i586-poky-linux-uclibc/usr/include/c++/i586-poky-linux-uclibc"
+ cxx.flags = conf.cc.flags.dup
+ cxx.defines = conf.cc.defines.dup
+ cxx.compile_options = conf.cc.compile_options.dup
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-ar"
+ archiver.archive_options = 'rcs %{outfile} %{objs}'
+ end
+
+ conf.linker do |linker|
+ linker.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-g++"
+ linker.flags = %w(-m32 -march=i586)
+ linker.flags << "--sysroot=#{GALILEO_SYSROOT}"
+ linker.flags << %w(-Os -Wl,--gc-sections)
+ linker.libraries = %w(m pthread)
+ end
+
+ #no executables
+ conf.bins = []
+
+ #do not build executable test
+ conf.build_mrbtest_lib_only
+
+ #official mrbgems
+ conf.gem :core => "mruby-sprintf"
+ conf.gem :core => "mruby-print"
+ conf.gem :core => "mruby-math"
+ conf.gem :core => "mruby-time"
+ conf.gem :core => "mruby-struct"
+ conf.gem :core => "mruby-enum-ext"
+ conf.gem :core => "mruby-string-ext"
+ conf.gem :core => "mruby-numeric-ext"
+ conf.gem :core => "mruby-array-ext"
+ conf.gem :core => "mruby-hash-ext"
+ conf.gem :core => "mruby-range-ext"
+ conf.gem :core => "mruby-proc-ext"
+ conf.gem :core => "mruby-symbol-ext"
+ conf.gem :core => "mruby-random"
+ conf.gem :core => "mruby-object-ext"
+ conf.gem :core => "mruby-objectspace"
+ conf.gem :core => "mruby-fiber"
+ conf.gem :core => "mruby-toplevel-ext"
+
+ #lightweigh regular expression
+ conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
+
+ #Arduino API
+ #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" do |g|
+ # g.cxx.include_paths << "#{GALILEO_X86_PATH}/libraries/Wire"
+ # g.cxx.include_paths << "#{GALILEO_X86_PATH}/libraries/Servo"
+
+ #enable unsupported Servo class
+ # g.cxx.defines << "MRUBY_ARDUINO_GALILEO_ENABLE_SERVO"
+ #end
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_RX630.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_RX630.rb
new file mode 100644
index 00000000..fd17eae9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_RX630.rb
@@ -0,0 +1,81 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
+# Cross Compiling configuration for RX630
+# http://gadget.renesas.com/
+#
+# Requires gnurx_v14.03
+MRuby::CrossBuild.new("RX630") do |conf|
+ toolchain :gcc
+
+ # Linux
+ BIN_PATH = "/usr/share/gnurx_v14.03_elf-1/bin"
+
+ conf.cc do |cc|
+ cc.command = "#{BIN_PATH}/rx-elf-gcc"
+ cc.flags = "-Wall -g -O2 -flto -mcpu=rx600 -m64bit-doubles"
+ cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
+
+ #configuration for low memory environment
+ cc.defines << %w(MRB_USE_FLOAT)
+ cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
+ cc.defines << %w(KHASH_DEFAULT_SIZE=8)
+ cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
+ cc.defines << %w(MRB_GC_STRESS)
+ cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
+ #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
+ end
+
+ conf.cxx do |cxx|
+ cxx.command = conf.cc.command.dup
+ cxx.include_paths = conf.cc.include_paths.dup
+ cxx.flags = conf.cc.flags.dup
+ cxx.defines = conf.cc.defines.dup
+ cxx.compile_options = conf.cc.compile_options.dup
+ end
+
+ conf.linker do |linker|
+ linker.command="#{BIN_PATH}/rx-elf-ld"
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = "#{BIN_PATH}/rx-elf-ar"
+ archiver.archive_options = 'rcs %{outfile} %{objs}'
+ end
+
+ #no executables
+ conf.bins = []
+
+ #do not build executable test
+ conf.build_mrbtest_lib_only
+
+ #disable C++ exception
+ conf.disable_cxx_exception
+
+ #gems from core
+ conf.gem :core => "mruby-sprintf"
+ conf.gem :core => "mruby-print"
+ conf.gem :core => "mruby-math"
+ conf.gem :core => "mruby-enum-ext"
+ conf.gem :core => "mruby-numeric-ext"
+
+ #light-weight regular expression
+ #conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
+
+ #Arduino API
+ #conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_arm64-v8a.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_arm64-v8a.rb
new file mode 100644
index 00000000..6188c13e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_arm64-v8a.rb
@@ -0,0 +1,26 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+end
+
+# Requires Android NDK r13 or later.
+MRuby::CrossBuild.new('android-arm64-v8a') do |conf|
+ params = {
+ :arch => 'arm64-v8a',
+ :platform => 'android-24',
+ :toolchain => :clang,
+ }
+ toolchain :android, params
+
+ conf.gembox 'default'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi.rb
new file mode 100644
index 00000000..b7eb33a9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi.rb
@@ -0,0 +1,26 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+end
+
+# Requires Android NDK r13 or later.
+MRuby::CrossBuild.new('android-armeabi') do |conf|
+ params = {
+ :arch => 'armeabi',
+ :platform => 'android-24',
+ :toolchain => :clang,
+ }
+ toolchain :android, params
+
+ conf.gembox 'default'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi_v7a_neon_hard.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi_v7a_neon_hard.rb
new file mode 100644
index 00000000..3788bba7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_android_armeabi_v7a_neon_hard.rb
@@ -0,0 +1,28 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+end
+
+# Requires Android NDK r13 or later.
+MRuby::CrossBuild.new('android-armeabi-v7a-neon-hard') do |conf|
+ params = {
+ :arch => 'armeabi-v7a',
+ :mfpu => 'neon',
+ :mfloat_abi => 'hard',
+ :platform => 'android-24',
+ :toolchain => :clang,
+ }
+ toolchain :android, params
+
+ conf.gembox 'default'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_chipKITMax32.rb b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_chipKITMax32.rb
new file mode 100644
index 00000000..951f7148
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/examples/targets/build_config_chipKITMax32.rb
@@ -0,0 +1,86 @@
+MRuby::Build.new do |conf|
+
+ # Gets set by the VS command prompts.
+ if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
+ toolchain :visualcpp
+ else
+ toolchain :gcc
+ end
+
+ enable_debug
+
+ # include the default GEMs
+ conf.gembox 'default'
+
+end
+
+# Cross Compiling configuration for Digilent chipKIT Max32
+# http://www.digilentinc.com/Products/Detail.cfm?Prod=CHIPKIT-MAX32
+#
+# Requires MPIDE (https://github.com/chipKIT32/chipKIT32-MAX)
+#
+# This configuration is based on @kyab's version
+# http://d.hatena.ne.jp/kyab/20130201
+MRuby::CrossBuild.new("chipKITMax32") do |conf|
+ toolchain :gcc
+
+ # Mac OS X
+ # MPIDE_PATH = '/Applications/Mpide.app/Contents/Resources/Java'
+ # GNU Linux
+ MPIDE_PATH = '/opt/mpide-0023-linux-20120903'
+
+ PIC32_PATH = "#{MPIDE_PATH}/hardware/pic32"
+
+ conf.cc do |cc|
+ cc.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-gcc"
+ cc.include_paths << ["#{PIC32_PATH}/cores/pic32",
+ "#{PIC32_PATH}/variants/Max32",
+ "#{PIC32_PATH}/libraries"]
+ cc.flags = %w(-O2 -mno-smart-io -w -ffunction-sections -fdata-sections -g -mdebugger -Wcast-align
+ -fno-short-double -mprocessor=32MX795F512L -DF_CPU=80000000L -DARDUINO=23 -D_BOARD_MEGA_
+ -DMPIDEVER=0x01000202 -DMPIDE=23)
+ cc.compile_options = "%{flags} -o %{outfile} -c %{infile}"
+
+ #configuration for low memory environment
+ cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
+ cc.defines << %w(KHASH_DEFAULT_SIZE=8)
+ cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
+ cc.defines << %w(MRB_GC_STRESS)
+ #cc.defines << %w(MRB_DISABLE_STDIO) #if you dont need stdio.
+ #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval
+ end
+
+ conf.cxx do |cxx|
+ cxx.command = conf.cc.command.dup
+ cxx.include_paths = conf.cc.include_paths.dup
+ cxx.flags = conf.cc.flags.dup
+ cxx.defines = conf.cc.defines.dup
+ cxx.compile_options = conf.cc.compile_options.dup
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-ar"
+ archiver.archive_options = 'rcs %{outfile} %{objs}'
+ end
+
+ #no executables
+ conf.bins = []
+
+ #do not build test executable
+ conf.build_mrbtest_lib_only
+
+ #disable C++ exception
+ conf.disable_cxx_exception
+
+ #gems from core
+ conf.gem :core => "mruby-print"
+ conf.gem :core => "mruby-math"
+ conf.gem :core => "mruby-enum-ext"
+
+ #light-weight regular expression
+ conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master"
+
+ #Arduino API
+ #conf.gem :github =>"kyab/mruby-arduino", :branch => "master"
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mrbconf.h b/web/server/h2o/libh2o/deps/mruby/include/mrbconf.h
new file mode 100644
index 00000000..b8d603e1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mrbconf.h
@@ -0,0 +1,130 @@
+/*
+** mrbconf.h - mruby core configuration
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBYCONF_H
+#define MRUBYCONF_H
+
+#include <limits.h>
+#include <stdint.h>
+
+/* architecture selection: */
+/* specify -DMRB_32BIT or -DMRB_64BIT to override */
+#if !defined(MRB_32BIT) && !defined(MRB_64BIT)
+#if UINT64_MAX == SIZE_MAX
+#define MRB_64BIT
+#else
+#define MRB_32BIT
+#endif
+#endif
+
+#if defined(MRB_32BIT) && defined(MRB_64BIT)
+#error Cannot build for 32 and 64 bit architecture at the same time
+#endif
+
+/* configuration options: */
+/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
+//#define MRB_USE_FLOAT
+
+/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
+//#define MRB_INT16
+
+/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */
+//#define MRB_INT64
+
+/* if no specific integer type is chosen */
+#if !defined(MRB_INT16) && !defined(MRB_INT32) && !defined(MRB_INT64)
+# if defined(MRB_64BIT) && !defined(MRB_NAN_BOXING)
+/* Use 64bit integers on 64bit architecture (without MRB_NAN_BOXING) */
+# define MRB_INT64
+# else
+/* Otherwise use 32bit integers */
+# define MRB_INT32
+# endif
+#endif
+
+/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT */
+//#define MRB_NAN_BOXING
+
+/* define on big endian machines; used by MRB_NAN_BOXING */
+//#define MRB_ENDIAN_BIG
+
+/* represent mrb_value as a word (natural unit of data for the processor) */
+//#define MRB_WORD_BOXING
+
+/* string class to handle UTF-8 encoding */
+//#define MRB_UTF8_STRING
+
+/* argv max size in mrb_funcall */
+//#define MRB_FUNCALL_ARGC_MAX 16
+
+/* number of object per heap page */
+//#define MRB_HEAP_PAGE_SIZE 1024
+
+/* if _etext and _edata available, mruby can reduce memory used by symbols */
+//#define MRB_USE_ETEXT_EDATA
+
+/* do not use __init_array_start to determine readonly data section;
+ effective only when MRB_USE_ETEXT_EDATA is defined */
+//#define MRB_NO_INIT_ARRAY_START
+
+/* turn off generational GC by default */
+//#define MRB_GC_TURN_OFF_GENERATIONAL
+
+/* default size of khash table bucket */
+//#define KHASH_DEFAULT_SIZE 32
+
+/* allocated memory address alignment */
+//#define POOL_ALIGNMENT 4
+
+/* page size of memory pool */
+//#define POOL_PAGE_SIZE 16000
+
+/* initial minimum size for string buffer */
+//#define MRB_STR_BUF_MIN_SIZE 128
+
+/* arena size */
+//#define MRB_GC_ARENA_SIZE 100
+
+/* fixed size GC arena */
+//#define MRB_GC_FIXED_ARENA
+
+/* state atexit stack size */
+//#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
+
+/* fixed size state atexit stack */
+//#define MRB_FIXED_STATE_ATEXIT_STACK
+
+/* -DMRB_DISABLE_XXXX to drop following features */
+//#define MRB_DISABLE_STDIO /* use of stdio */
+
+/* -DMRB_ENABLE_XXXX to enable following features */
+//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
+
+/* end of configuration */
+
+/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */
+#ifdef DISABLE_STDIO
+#define MRB_DISABLE_STDIO
+#endif
+
+/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */
+#ifdef ENABLE_DEBUG
+#define MRB_ENABLE_DEBUG_HOOK
+#endif
+
+#ifndef MRB_DISABLE_STDIO
+# include <stdio.h>
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#endif /* MRUBYCONF_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby.h b/web/server/h2o/libh2o/deps/mruby/include/mruby.h
new file mode 100644
index 00000000..ced9c104
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby.h
@@ -0,0 +1,1257 @@
+/*
+** mruby - An embeddable Ruby implementation
+**
+** Copyright (c) mruby developers 2010-2017
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+*/
+
+#ifndef MRUBY_H
+#define MRUBY_H
+
+#ifdef __cplusplus
+#define __STDC_LIMIT_MACROS
+#define __STDC_CONSTANT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
+
+#ifdef __cplusplus
+#ifndef SIZE_MAX
+#ifdef __SIZE_MAX__
+#define SIZE_MAX __SIZE_MAX__
+#else
+#define SIZE_MAX std::numeric_limits<size_t>::max()
+#endif
+#endif
+#endif
+
+#ifdef MRB_DEBUG
+#include <assert.h>
+#define mrb_assert(p) assert(p)
+#define mrb_assert_int_fit(t1,n,t2,max) assert((n)>=0 && ((sizeof(n)<=sizeof(t2))||(n<=(t1)(max))))
+#else
+#define mrb_assert(p) ((void)0)
+#define mrb_assert_int_fit(t1,n,t2,max) ((void)0)
+#endif
+
+#if __STDC_VERSION__ >= 201112L
+#define mrb_static_assert(exp, str) _Static_assert(exp, str)
+#else
+#define mrb_static_assert(exp, str) mrb_assert(exp)
+#endif
+
+#include "mrbconf.h"
+
+#ifndef FLT_EPSILON
+#define FLT_EPSILON (1.19209290e-07f)
+#endif
+#ifndef DBL_EPSILON
+#define DBL_EPSILON ((double)2.22044604925031308085e-16L)
+#endif
+#ifndef LDBL_EPSILON
+#define LDBL_EPSILON (1.08420217248550443401e-19L)
+#endif
+
+#ifdef MRB_USE_FLOAT
+#define MRB_FLOAT_EPSILON FLT_EPSILON
+#else
+#define MRB_FLOAT_EPSILON DBL_EPSILON
+#endif
+
+#include "mruby/common.h"
+#include <mruby/value.h>
+#include <mruby/gc.h>
+#include <mruby/version.h>
+
+/**
+ * MRuby C API entry point
+ */
+MRB_BEGIN_DECL
+
+typedef uint32_t mrb_code;
+
+/**
+ * Required arguments signature type.
+ */
+typedef uint32_t mrb_aspec;
+
+
+struct mrb_irep;
+struct mrb_state;
+
+/**
+ * Function pointer type of custom allocator used in @see mrb_open_allocf.
+ *
+ * The function pointing it must behave similarly as realloc except:
+ * - If ptr is NULL it must allocate new space.
+ * - If s is NULL, ptr must be freed.
+ *
+ * See @see mrb_default_allocf for the default implementation.
+ */
+typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud);
+
+#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE
+#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
+#endif
+
+typedef struct {
+ mrb_sym mid;
+ struct RProc *proc;
+ mrb_value *stackent;
+ int nregs;
+ int ridx;
+ int epos;
+ struct REnv *env;
+ mrb_code *pc; /* return address */
+ mrb_code *err; /* error position */
+ int argc;
+ int acc;
+ struct RClass *target_class;
+} mrb_callinfo;
+
+enum mrb_fiber_state {
+ MRB_FIBER_CREATED = 0,
+ MRB_FIBER_RUNNING,
+ MRB_FIBER_RESUMED,
+ MRB_FIBER_SUSPENDED,
+ MRB_FIBER_TRANSFERRED,
+ MRB_FIBER_TERMINATED,
+};
+
+struct mrb_context {
+ struct mrb_context *prev;
+
+ mrb_value *stack; /* stack of virtual machine */
+ mrb_value *stbase, *stend;
+
+ mrb_callinfo *ci;
+ mrb_callinfo *cibase, *ciend;
+
+ mrb_code **rescue; /* exception handler stack */
+ int rsize;
+ struct RProc **ensure; /* ensure handler stack */
+ int esize, eidx;
+
+ enum mrb_fiber_state status;
+ mrb_bool vmexec;
+ struct RFiber *fib;
+};
+
+#ifdef MRB_METHOD_CACHE_SIZE
+# define MRB_METHOD_CACHE
+#else
+/* default method cache size: 128 */
+/* cache size needs to be power of 2 */
+# define MRB_METHOD_CACHE_SIZE (1<<7)
+#endif
+
+#ifdef MRB_METHOD_CACHE
+struct mrb_cache_entry {
+ struct RClass *c;
+ mrb_sym mid;
+ struct RProc *m;
+};
+#endif
+
+struct mrb_jmpbuf;
+
+typedef void (*mrb_atexit_func)(struct mrb_state*);
+
+#define MRB_STATE_NO_REGEXP 1
+#define MRB_STATE_REGEXP 2
+
+typedef struct mrb_state {
+ struct mrb_jmpbuf *jmp;
+
+ uint32_t flags;
+ mrb_allocf allocf; /* memory allocation function */
+ void *allocf_ud; /* auxiliary data of allocf */
+
+ struct mrb_context *c;
+ struct mrb_context *root_c;
+ struct iv_tbl *globals; /* global variable table */
+
+ struct RObject *exc; /* exception */
+
+ struct RObject *top_self;
+ struct RClass *object_class; /* Object class */
+ struct RClass *class_class;
+ struct RClass *module_class;
+ struct RClass *proc_class;
+ struct RClass *string_class;
+ struct RClass *array_class;
+ struct RClass *hash_class;
+ struct RClass *range_class;
+
+ struct RClass *float_class;
+ struct RClass *fixnum_class;
+ struct RClass *true_class;
+ struct RClass *false_class;
+ struct RClass *nil_class;
+ struct RClass *symbol_class;
+ struct RClass *kernel_module;
+
+ struct alloca_header *mems;
+ mrb_gc gc;
+
+#ifdef MRB_METHOD_CACHE
+ struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE];
+#endif
+
+ mrb_sym symidx;
+ struct kh_n2s *name2sym; /* symbol hash */
+ struct symbol_name *symtbl; /* symbol table */
+ size_t symcapa;
+
+#ifdef MRB_ENABLE_DEBUG_HOOK
+ void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
+ void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs);
+#endif
+
+#ifdef MRB_BYTECODE_DECODE_OPTION
+ mrb_code (*bytecode_decoder)(struct mrb_state* mrb, mrb_code code);
+#endif
+
+ struct RClass *eException_class;
+ struct RClass *eStandardError_class;
+ struct RObject *nomem_err; /* pre-allocated NoMemoryError */
+ struct RObject *stack_err; /* pre-allocated SysStackError */
+#ifdef MRB_GC_FIXED_ARENA
+ struct RObject *arena_err; /* pre-allocated arena overfow error */
+#endif
+
+ void *ud; /* auxiliary data */
+
+#ifdef MRB_FIXED_STATE_ATEXIT_STACK
+ mrb_atexit_func atexit_stack[MRB_FIXED_STATE_ATEXIT_STACK_SIZE];
+#else
+ mrb_atexit_func *atexit_stack;
+#endif
+ mrb_int atexit_stack_len;
+} mrb_state;
+
+
+typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
+
+/**
+ * Defines a new class.
+ *
+ * If you're creating a gem it may look something like this:
+ *
+ * !!!c
+ * void mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class);
+ * }
+ *
+ * void mrb_example_gem_final(mrb_state* mrb) {
+ * //free(TheAnimals);
+ * }
+ *
+ * @param [mrb_state *] mrb The current mruby state.
+ * @param [const char *] name The name of the defined class.
+ * @param [struct RClass *] super The new class parent.
+ * @return [struct RClass *] Reference to the newly defined class.
+ * @see mrb_define_class_under
+ */
+MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super);
+
+/**
+ * Defines a new module.
+ *
+ * @param [mrb_state *] mrb_state* The current mruby state.
+ * @param [const char *] char* The name of the module.
+ * @return [struct RClass *] Reference to the newly defined module.
+ */
+MRB_API struct RClass *mrb_define_module(mrb_state *, const char*);
+MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value);
+
+/**
+ * Include a module in another class or module.
+ * Equivalent to:
+ *
+ * module B
+ * include A
+ * end
+ * @param [mrb_state *] mrb_state* The current mruby state.
+ * @param [struct RClass *] RClass* A reference to module or a class.
+ * @param [struct RClass *] RClass* A reference to the module to be included.
+ */
+MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*);
+
+/**
+ * Prepends a module in another class or module.
+ *
+ * Equivalent to:
+ * module B
+ * prepend A
+ * end
+ * @param [mrb_state *] mrb_state* The current mruby state.
+ * @param [struct RClass *] RClass* A reference to module or a class.
+ * @param [struct RClass *] RClass* A reference to the module to be prepended.
+ */
+MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*);
+
+/**
+ * Defines a global function in ruby.
+ *
+ * If you're creating a gem it may look something like this
+ *
+ * Example:
+ *
+ * !!!c
+ * mrb_value example_method(mrb_state* mrb, mrb_value self)
+ * {
+ * puts("Executing example command!");
+ * return self;
+ * }
+ *
+ * void mrb_example_gem_init(mrb_state* mrb)
+ * {
+ * mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE());
+ * }
+ *
+ * @param [mrb_state *] mrb The MRuby state reference.
+ * @param [struct RClass *] cla The class pointer where the method will be defined.
+ * @param [const char *] name The name of the method being defined.
+ * @param [mrb_func_t] func The function pointer to the method definition.
+ * @param [mrb_aspec] aspec The method parameters declaration.
+ */
+MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t func, mrb_aspec aspec);
+
+/**
+ * Defines a class method.
+ *
+ * Example:
+ *
+ * # Ruby style
+ * class Foo
+ * def Foo.bar
+ * end
+ * end
+ * // C style
+ * mrb_value bar_method(mrb_state* mrb, mrb_value self){
+ * return mrb_nil_value();
+ * }
+ * void mrb_example_gem_init(mrb_state* mrb){
+ * struct RClass *foo;
+ * foo = mrb_define_class(mrb, "Foo", mrb->object_class);
+ * mrb_define_class_method(mrb, foo, "bar", bar_method, MRB_ARGS_NONE());
+ * }
+ * @param [mrb_state *] mrb_state* The MRuby state reference.
+ * @param [struct RClass *] RClass* The class where the class method will be defined.
+ * @param [const char *] char* The name of the class method being defined.
+ * @param [mrb_func_t] mrb_func_t The function pointer to the class method definition.
+ * @param [mrb_aspec] mrb_aspec The method parameters declaration.
+ */
+MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec);
+MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec);
+
+/**
+ * Defines a module fuction.
+ *
+ * Example:
+ *
+ * # Ruby style
+ * module Foo
+ * def Foo.bar
+ * end
+ * end
+ * // C style
+ * mrb_value bar_method(mrb_state* mrb, mrb_value self){
+ * return mrb_nil_value();
+ * }
+ * void mrb_example_gem_init(mrb_state* mrb){
+ * struct RClass *foo;
+ * foo = mrb_define_module(mrb, "Foo");
+ * mrb_define_module_function(mrb, foo, "bar", bar_method, MRB_ARGS_NONE());
+ * }
+ * @param [mrb_state *] mrb_state* The MRuby state reference.
+ * @param [struct RClass *] RClass* The module where the module function will be defined.
+ * @param [const char *] char* The name of the module function being defined.
+ * @param [mrb_func_t] mrb_func_t The function pointer to the module function definition.
+ * @param [mrb_aspec] mrb_aspec The method parameters declaration.
+ */
+MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec);
+
+/**
+ * Defines a constant.
+ *
+ * Example:
+ *
+ * # Ruby style
+ * class ExampleClass
+ * AGE = 22
+ * end
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb){
+ * mrb_define_const(mrb, mrb->kernel_module, "AGE", mrb_fixnum_value(22));
+ * }
+ *
+ * mrb_value
+ * mrb_example_gem_final(mrb_state* mrb){
+ * }
+ * @param [mrb_state *] mrb_state* The MRuby state reference.
+ * @param [struct RClass *] RClass* A class or module the constant is defined in.
+ * @param [const char *] name The name of the constant being defined.
+ * @param [mrb_value] mrb_value The value for the constant.
+ */
+MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value);
+
+/**
+ * Undefines a method.
+ *
+ * Example:
+ *
+ * # Ruby style
+ *
+ * class ExampleClassA
+ * def example_method
+ * "example"
+ * end
+ * end
+ * ExampleClassA.new.example_method # => example
+ *
+ * class ExampleClassB < ExampleClassA
+ * undef_method :example_method
+ * end
+ *
+ * ExampleClassB.new.example_method # => undefined method 'example_method' for ExampleClassB (NoMethodError)
+ *
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * mrb_value
+ * mrb_example_method(mrb_state *mrb){
+ * return mrb_str_new_lit(mrb, "example");
+ * }
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb){
+ * struct RClass *example_class_a;
+ * struct RClass *example_class_b;
+ * struct RClass *example_class_c;
+ *
+ * example_class_a = mrb_define_class(mrb, "ExampleClassA", mrb->object_class);
+ * mrb_define_method(mrb, example_class_a, "example_method", mrb_example_method, MRB_ARGS_NONE());
+ * example_class_b = mrb_define_class(mrb, "ExampleClassB", example_class_a);
+ * example_class_c = mrb_define_class(mrb, "ExampleClassC", example_class_b);
+ * mrb_undef_method(mrb, example_class_c, "example_method");
+ * }
+ *
+ * mrb_example_gem_final(mrb_state* mrb){
+ * }
+ * @param [mrb_state*] mrb_state* The mruby state reference.
+ * @param [struct RClass*] RClass* A class the method will be undefined from.
+ * @param [const char*] constchar* The name of the method to be undefined.
+ */
+MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
+
+/**
+ * Undefine a class method.
+ * Example:
+ *
+ * # Ruby style
+ * class ExampleClass
+ * def self.example_method
+ * "example"
+ * end
+ * end
+ *
+ * ExampleClass.example_method
+ *
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * mrb_value
+ * mrb_example_method(mrb_state *mrb){
+ * return mrb_str_new_lit(mrb, "example");
+ * }
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb){
+ * struct RClass *example_class;
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class);
+ * mrb_define_class_method(mrb, example_class, "example_method", mrb_example_method, MRB_ARGS_NONE());
+ * mrb_undef_class_method(mrb, example_class, "example_method");
+ * }
+ *
+ * void
+ * mrb_example_gem_final(mrb_state* mrb){
+ * }
+ * @param [mrb_state*] mrb_state* The mruby state reference.
+ * @param [RClass*] RClass* A class the class method will be undefined from.
+ * @param [constchar*] constchar* The name of the class method to be undefined.
+ */
+MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
+
+/**
+ * Initialize a new object instace of c class.
+ *
+ * Example:
+ *
+ * # Ruby style
+ * class ExampleClass
+ * end
+ *
+ * p ExampleClass # => #<ExampleClass:0x9958588>
+ * // C style
+ * #include <stdio.h>
+ * #include <mruby.h>
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_value obj;
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); # => class ExampleClass; end
+ * obj = mrb_obj_new(mrb, example_class, 0, NULL); # => ExampleClass.new
+ * mrb_p(mrb, obj); // => Kernel#p
+ * }
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [RClass*] c Reference to the class of the new object.
+ * @param [mrb_int] argc Number of arguments in argv
+ * @param [const mrb_value *] argv Array of mrb_value to initialize the object
+ * @return [mrb_value] The newly initialized object
+ */
+MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv);
+
+/** @see mrb_obj_new */
+MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const mrb_value *argv, struct RClass *c)
+{
+ return mrb_obj_new(mrb,c,argc,argv);
+}
+
+MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
+
+/**
+ * Creates a new instance of Class, Class.
+ *
+ * Example:
+ *
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ *
+ * mrb_value obj;
+ * example_class = mrb_class_new(mrb, mrb->object_class);
+ * obj = mrb_obj_new(mrb, example_class, 0, NULL); // => #<#<Class:0x9a945b8>:0x9a94588>
+ * mrb_p(mrb, obj); // => Kernel#p
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] super The super class or parent.
+ * @return [struct RClass *] Reference to the new class.
+ */
+MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super);
+
+/**
+ * Creates a new module, Module.
+ *
+ * Example:
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_module;
+ *
+ * example_module = mrb_module_new(mrb);
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @return [struct RClass *] Reference to the new module.
+ */
+MRB_API struct RClass * mrb_module_new(mrb_state *mrb);
+
+/**
+ * Returns an mrb_bool. True if class was defined, and false if the class was not defined.
+ *
+ * Example:
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_bool cd;
+ *
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class);
+ * cd = mrb_class_defined(mrb, "ExampleClass");
+ *
+ * // If mrb_class_defined returns 1 then puts "True"
+ * // If mrb_class_defined returns 0 then puts "False"
+ * if (cd == 1){
+ * puts("True");
+ * }
+ * else {
+ * puts("False");
+ * }
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name A string representing the name of the class.
+ * @return [mrb_bool] A boolean value.
+ */
+MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name);
+
+/**
+ * Gets a class.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name The name of the class.
+ * @return [struct RClass *] A reference to the class.
+*/
+MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name);
+
+/**
+ * Gets a exception class.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name The name of the class.
+ * @return [struct RClass *] A reference to the class.
+*/
+MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name);
+
+/**
+ * Returns an mrb_bool. True if inner class was defined, and false if the inner class was not defined.
+ *
+ * Example:
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_outer, *example_inner;
+ * mrb_bool cd;
+ *
+ * example_outer = mrb_define_module(mrb, "ExampleOuter");
+ *
+ * example_inner = mrb_define_class_under(mrb, example_outer, "ExampleInner", mrb->object_class);
+ * cd = mrb_class_defined_under(mrb, example_outer, "ExampleInner");
+ *
+ * // If mrb_class_defined_under returns 1 then puts "True"
+ * // If mrb_class_defined_under returns 0 then puts "False"
+ * if (cd == 1){
+ * puts("True");
+ * }
+ * else {
+ * puts("False");
+ * }
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer The name of the outer class.
+ * @param [const char *] name A string representing the name of the inner class.
+ * @return [mrb_bool] A boolean value.
+ */
+MRB_API mrb_bool mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name);
+
+/**
+ * Gets a child class.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer The name of the parent class.
+ * @param [const char *] name The name of the class.
+ * @return [struct RClass *] A reference to the class.
+*/
+MRB_API struct RClass * mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name);
+
+/**
+ * Gets a module.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [const char *] name The name of the module.
+ * @return [struct RClass *] A reference to the module.
+*/
+MRB_API struct RClass * mrb_module_get(mrb_state *mrb, const char *name);
+
+/**
+ * Gets a module defined under another module.
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer The name of the outer module.
+ * @param [const char *] name The name of the module.
+ * @return [struct RClass *] A reference to the module.
+*/
+MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name);
+MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
+
+/**
+ * Duplicate an object.
+ *
+ * Equivalent to:
+ * Object#dup
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [mrb_value] obj Object to be duplicate.
+ * @return [mrb_value] The newly duplicated object.
+ */
+MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
+MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method);
+
+/**
+ * Returns true if obj responds to the given method. If the method was defined for that
+ * class it returns true, it returns false otherwise.
+ *
+ * Example:
+ * # Ruby style
+ * class ExampleClass
+ * def example_method
+ * end
+ * end
+ *
+ * ExampleClass.new.respond_to?(:example_method) # => true
+ *
+ * // C style
+ * void
+ * mrb_example_gem_init(mrb_state* mrb) {
+ * struct RClass *example_class;
+ * mrb_sym mid;
+ * mrb_bool obj_resp;
+ *
+ * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class);
+ * mrb_define_method(mrb, example_class, "example_method", exampleMethod, MRB_ARGS_NONE());
+ * mid = mrb_intern_str(mrb, mrb_str_new_lit(mrb, "example_method" ));
+ * obj_resp = mrb_obj_respond_to(mrb, example_class, mid); // => 1(true in Ruby world)
+ *
+ * // If mrb_obj_respond_to returns 1 then puts "True"
+ * // If mrb_obj_respond_to returns 0 then puts "False"
+ * if (obj_resp == 1) {
+ * puts("True");
+ * }
+ * else if (obj_resp == 0) {
+ * puts("False");
+ * }
+ * }
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] c A reference to a class.
+ * @param [mrb_sym] mid A symbol referencing a method id.
+ * @return [mrb_bool] A boolean value.
+ */
+MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid);
+
+/**
+ * Defines a new class under a given module
+ *
+ * @param [mrb_state*] mrb The current mruby state.
+ * @param [struct RClass *] outer Reference to the module under which the new class will be defined
+ * @param [const char *] name The name of the defined class
+ * @param [struct RClass *] super The new class parent
+ * @return [struct RClass *] Reference to the newly defined class
+ * @see mrb_define_class
+ */
+MRB_API struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super);
+
+MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name);
+
+/**
+ * Function requires n arguments.
+ *
+ * @param n
+ * The number of required arguments.
+ */
+#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18)
+
+/**
+ * Funtion takes n optional arguments
+ *
+ * @param n
+ * The number of optional arguments.
+ */
+#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13)
+
+/**
+ * Funtion takes n1 mandatory arguments and n2 optional arguments
+ *
+ * @param n1
+ * The number of required arguments.
+ * @param n2
+ * The number of optional arguments.
+ */
+#define MRB_ARGS_ARG(n1,n2) (MRB_ARGS_REQ(n1)|MRB_ARGS_OPT(n2))
+
+/** rest argument */
+#define MRB_ARGS_REST() ((mrb_aspec)(1 << 12))
+
+/** required arguments after rest */
+#define MRB_ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 7)
+
+/** keyword arguments (n of keys, kdict) */
+#define MRB_ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 2) | ((n2)?(1<<1):0)))
+
+/**
+ * Function takes a block argument
+ */
+#define MRB_ARGS_BLOCK() ((mrb_aspec)1)
+
+/**
+ * Function accepts any number of arguments
+ */
+#define MRB_ARGS_ANY() MRB_ARGS_REST()
+
+/**
+ * Function accepts no arguments
+ */
+#define MRB_ARGS_NONE() ((mrb_aspec)0)
+
+/**
+ * Format specifiers for {mrb_get_args} function
+ *
+ * Must be a C string composed of the following format specifiers:
+ *
+ * | char | Ruby type | C types | Notes |
+ * |:----:|----------------|-------------------|----------------------------------------------------|
+ * | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument |
+ * | `C` | {Class}/{Module} | {mrb_value} | |
+ * | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` |
+ * | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` |
+ * | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` |
+ * | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` |
+ * | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` |
+ * | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` |
+ * | `f` | {Float} | {mrb_float} | |
+ * | `i` | {Integer} | {mrb_int} | |
+ * | `b` | boolean | {mrb_bool} | |
+ * | `n` | {Symbol} | {mrb_sym} | |
+ * | `&` | block | {mrb_value} | |
+ * | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. |
+ * | &vert; | optional | | After this spec following specs would be optional. |
+ * | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. |
+ *
+ * @see mrb_get_args
+ */
+typedef const char *mrb_args_format;
+
+/**
+ * Retrieve arguments from mrb_state.
+ *
+ * When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are
+ * applied to received arguments.
+ * Used inside a function of mrb_func_t type.
+ *
+ * @param mrb The current MRuby state.
+ * @param format [mrb_args_format] is a list of format specifiers
+ * @param ... The passing variadic arguments must be a pointer of retrieving type.
+ * @return the number of arguments retrieved.
+ * @see mrb_args_format
+ */
+MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...);
+
+static inline mrb_sym
+mrb_get_mid(mrb_state *mrb) /* get method symbol */
+{
+ return mrb->c->ci->mid;
+}
+
+static inline int
+mrb_get_argc(mrb_state *mrb) /* get argc */
+{
+ return mrb->c->ci->argc;
+}
+
+/* `strlen` for character string literals (use with caution or `strlen` instead)
+ Adjacent string literals are concatenated in C/C++ in translation phase 6.
+ If `lit` is not one, the compiler will report a syntax error:
+ MSVC: "error C2143: syntax error : missing ')' before 'string'"
+ GCC: "error: expected ')' before string constant"
+*/
+#define mrb_strlen_lit(lit) (sizeof(lit "") - 1)
+
+/**
+ * Call existing ruby functions.
+ *
+ * #include <stdio.h>
+ * #include <mruby.h>
+ * #include "mruby/compile.h"
+ *
+ * int
+ * main()
+ * {
+ * mrb_int i = 99;
+ * mrb_state *mrb = mrb_open();
+ *
+ * if (!mrb) { }
+ * FILE *fp = fopen("test.rb","r");
+ * mrb_value obj = mrb_load_file(mrb,fp);
+ * mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i));
+ * fclose(fp);
+ * mrb_close(mrb);
+ * }
+ * @param [mrb_state*] mrb_state* The current mruby state.
+ * @param [mrb_value] mrb_value A reference to an mruby value.
+ * @param [const char*] const char* The name of the method.
+ * @param [mrb_int] mrb_int The number of arguments the method has.
+ * @param [...] ... Variadic values(not type safe!).
+ * @return [mrb_value] mrb_value mruby function value.
+ */
+MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...);
+/**
+ * Call existing ruby functions. This is basically the type safe version of mrb_funcall.
+ *
+ * #include <stdio.h>
+ * #include <mruby.h>
+ * #include "mruby/compile.h"
+ * int
+ * main()
+ * {
+ * mrb_int i = 99;
+ * mrb_state *mrb = mrb_open();
+ *
+ * if (!mrb) { }
+ * mrb_sym m_sym = mrb_intern_lit(mrb, "method_name"); // Symbol for method.
+ *
+ * FILE *fp = fopen("test.rb","r");
+ * mrb_value obj = mrb_load_file(mrb,fp);
+ * mrb_funcall_argv(mrb, obj, m_sym, 1, &obj); // Calling ruby function from test.rb.
+ * fclose(fp);
+ * mrb_close(mrb);
+ * }
+ * @param [mrb_state*] mrb_state* The current mruby state.
+ * @param [mrb_value] mrb_value A reference to an mruby value.
+ * @param [mrb_sym] mrb_sym The symbol representing the method.
+ * @param [mrb_int] mrb_int The number of arguments the method has.
+ * @param [const mrb_value*] mrb_value* Pointer to the object.
+ * @return [mrb_value] mrb_value mruby function value.
+ * @see mrb_funcall
+ */
+MRB_API mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*);
+/**
+ * Call existing ruby functions with a block.
+ */
+MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value);
+/**
+ * Create a symbol
+ *
+ * # Ruby style:
+ * :pizza # => :pizza
+ *
+ * // C style:
+ * mrb_sym m_sym = mrb_intern_lit(mrb, "pizza"); // => :pizza
+ * @param [mrb_state*] mrb_state* The current mruby state.
+ * @param [const char*] const char* The name of the method.
+ * @return [mrb_sym] mrb_sym A symbol.
+ */
+MRB_API mrb_sym mrb_intern_cstr(mrb_state*,const char*);
+MRB_API mrb_sym mrb_intern(mrb_state*,const char*,size_t);
+MRB_API mrb_sym mrb_intern_static(mrb_state*,const char*,size_t);
+#define mrb_intern_lit(mrb, lit) mrb_intern_static(mrb, lit, mrb_strlen_lit(lit))
+MRB_API mrb_sym mrb_intern_str(mrb_state*,mrb_value);
+MRB_API mrb_value mrb_check_intern_cstr(mrb_state*,const char*);
+MRB_API mrb_value mrb_check_intern(mrb_state*,const char*,size_t);
+MRB_API mrb_value mrb_check_intern_str(mrb_state*,mrb_value);
+MRB_API const char *mrb_sym2name(mrb_state*,mrb_sym);
+MRB_API const char *mrb_sym2name_len(mrb_state*,mrb_sym,mrb_int*);
+MRB_API mrb_value mrb_sym2str(mrb_state*,mrb_sym);
+
+MRB_API void *mrb_malloc(mrb_state*, size_t); /* raise RuntimeError if no mem */
+MRB_API void *mrb_calloc(mrb_state*, size_t, size_t); /* ditto */
+MRB_API void *mrb_realloc(mrb_state*, void*, size_t); /* ditto */
+MRB_API void *mrb_realloc_simple(mrb_state*, void*, size_t); /* return NULL if no memory available */
+MRB_API void *mrb_malloc_simple(mrb_state*, size_t); /* return NULL if no memory available */
+MRB_API struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*);
+MRB_API void mrb_free(mrb_state*, void*);
+
+MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len);
+
+/**
+ * Turns a C string into a Ruby string value.
+ */
+MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*);
+MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len);
+#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit))
+
+#ifdef _WIN32
+char* mrb_utf8_from_locale(const char *p, int len);
+char* mrb_locale_from_utf8(const char *p, int len);
+#define mrb_locale_free(p) free(p)
+#define mrb_utf8_free(p) free(p)
+#else
+#define mrb_utf8_from_locale(p, l) (p)
+#define mrb_locale_from_utf8(p, l) (p)
+#define mrb_locale_free(p)
+#define mrb_utf8_free(p)
+#endif
+
+/**
+ * Creates new mrb_state.
+ *
+ * @return
+ * Pointer to the newly created mrb_state.
+ */
+MRB_API mrb_state* mrb_open(void);
+
+/**
+ * Create new mrb_state with custom allocators.
+ *
+ * @param f
+ * Reference to the allocation function.
+ * @param ud
+ * User data will be passed to custom allocator f.
+ * If user data isn't required just pass NULL.
+ * @return
+ * Pointer to the newly created mrb_state.
+ */
+MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud);
+
+/**
+ * Create new mrb_state with just the MRuby core
+ *
+ * @param f
+ * Reference to the allocation function.
+ * Use mrb_default_allocf for the default
+ * @param ud
+ * User data will be passed to custom allocator f.
+ * If user data isn't required just pass NULL.
+ * @return
+ * Pointer to the newly created mrb_state.
+ */
+MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
+
+/**
+ * Closes and frees a mrb_state.
+ *
+ * @param mrb
+ * Pointer to the mrb_state to be closed.
+ */
+MRB_API void mrb_close(mrb_state *mrb);
+
+/**
+ * The default allocation function.
+ *
+ * @see mrb_allocf
+ */
+MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
+
+MRB_API mrb_value mrb_top_self(mrb_state *);
+MRB_API mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value);
+MRB_API mrb_value mrb_top_run(mrb_state*, struct RProc*, mrb_value, unsigned int);
+MRB_API mrb_value mrb_vm_run(mrb_state*, struct RProc*, mrb_value, unsigned int);
+MRB_API mrb_value mrb_vm_exec(mrb_state*, struct RProc*, mrb_code*);
+/* compatibility macros */
+#define mrb_toplevel_run_keep(m,p,k) mrb_top_run((m),(p),mrb_top_self(m),(k))
+#define mrb_toplevel_run(m,p) mrb_toplevel_run_keep((m),(p),0)
+#define mrb_context_run(m,p,s,k) mrb_vm_run((m),(p),(s),(k))
+
+MRB_API void mrb_p(mrb_state*, mrb_value);
+MRB_API mrb_int mrb_obj_id(mrb_value obj);
+MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name);
+
+MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value);
+MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value);
+MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
+MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base);
+MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val);
+MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val);
+MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj);
+MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
+
+static inline int mrb_gc_arena_save(mrb_state*);
+static inline void mrb_gc_arena_restore(mrb_state*,int);
+
+static inline int
+mrb_gc_arena_save(mrb_state *mrb)
+{
+ return mrb->gc.arena_idx;
+}
+
+static inline void
+mrb_gc_arena_restore(mrb_state *mrb, int idx)
+{
+ mrb->gc.arena_idx = idx;
+}
+
+MRB_API int mrb_gc_arena_save(mrb_state*);
+MRB_API void mrb_gc_arena_restore(mrb_state*,int);
+
+MRB_API void mrb_garbage_collect(mrb_state*);
+MRB_API void mrb_full_gc(mrb_state*);
+MRB_API void mrb_incremental_gc(mrb_state *);
+MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*);
+#define mrb_gc_mark_value(mrb,val) do {\
+ if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \
+} while (0)
+MRB_API void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*);
+#define mrb_field_write_barrier_value(mrb, obj, val) do{\
+ if (!mrb_immediate_p(val)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val)); \
+} while (0)
+MRB_API void mrb_write_barrier(mrb_state *, struct RBasic*);
+
+MRB_API mrb_value mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method);
+MRB_API mrb_value mrb_any_to_s(mrb_state *mrb, mrb_value obj);
+MRB_API const char * mrb_obj_classname(mrb_state *mrb, mrb_value obj);
+MRB_API struct RClass* mrb_obj_class(mrb_state *mrb, mrb_value obj);
+MRB_API mrb_value mrb_class_path(mrb_state *mrb, struct RClass *c);
+MRB_API mrb_value mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method);
+MRB_API mrb_bool mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c);
+MRB_API mrb_value mrb_obj_inspect(mrb_state *mrb, mrb_value self);
+MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self);
+
+#ifndef ISPRINT
+#define ISASCII(c) ((unsigned)(c) <= 0x7f)
+#define ISPRINT(c) (((unsigned)(c) - 0x20) < 0x5f)
+#define ISSPACE(c) ((c) == ' ' || (unsigned)(c) - '\t' < 5)
+#define ISUPPER(c) (((unsigned)(c) - 'A') < 26)
+#define ISLOWER(c) (((unsigned)(c) - 'a') < 26)
+#define ISALPHA(c) ((((unsigned)(c) | 0x20) - 'a') < 26)
+#define ISDIGIT(c) (((unsigned)(c) - '0') < 10)
+#define ISXDIGIT(c) (ISDIGIT(c) || ((unsigned)(c) | 0x20) - 'a' < 6)
+#define ISALNUM(c) (ISALPHA(c) || ISDIGIT(c))
+#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#define ISCNTRL(c) ((unsigned)(c) < 0x20 || (c) == 0x7f)
+#define TOUPPER(c) (ISLOWER(c) ? ((c) & 0x5f) : (c))
+#define TOLOWER(c) (ISUPPER(c) ? ((c) | 0x20) : (c))
+#endif
+
+MRB_API mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len);
+MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc);
+
+MRB_API mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg);
+MRB_API mrb_noreturn void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...);
+MRB_API mrb_noreturn void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...);
+MRB_API void mrb_warn(mrb_state *mrb, const char *fmt, ...);
+MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...);
+MRB_API void mrb_print_backtrace(mrb_state *mrb);
+MRB_API void mrb_print_error(mrb_state *mrb);
+
+/* macros to get typical exception objects
+ note:
+ + those E_* macros requires mrb_state* variable named mrb.
+ + exception objects obtained from those macros are local to mrb
+*/
+#define E_RUNTIME_ERROR (mrb_exc_get(mrb, "RuntimeError"))
+#define E_TYPE_ERROR (mrb_exc_get(mrb, "TypeError"))
+#define E_ARGUMENT_ERROR (mrb_exc_get(mrb, "ArgumentError"))
+#define E_INDEX_ERROR (mrb_exc_get(mrb, "IndexError"))
+#define E_RANGE_ERROR (mrb_exc_get(mrb, "RangeError"))
+#define E_NAME_ERROR (mrb_exc_get(mrb, "NameError"))
+#define E_NOMETHOD_ERROR (mrb_exc_get(mrb, "NoMethodError"))
+#define E_SCRIPT_ERROR (mrb_exc_get(mrb, "ScriptError"))
+#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError"))
+#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError"))
+#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError"))
+
+#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError"))
+#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError"))
+
+#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError"))
+
+MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg);
+MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv);
+MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c);
+
+/* continue execution to the proc */
+/* this function should always be called as the last function of a method */
+/* e.g. return mrb_yield_cont(mrb, proc, self, argc, argv); */
+mrb_value mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb_value *argv);
+
+/* mrb_gc_protect() leaves the object in the arena */
+MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj);
+/* mrb_gc_register() keeps the object from GC. */
+MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj);
+/* mrb_gc_unregister() removes the object from GC root. */
+MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj);
+
+MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
+#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val))
+MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
+
+typedef enum call_type {
+ CALL_PUBLIC,
+ CALL_FCALL,
+ CALL_VCALL,
+ CALL_TYPE_MAX
+} call_type;
+
+MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2);
+MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass);
+MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val);
+
+MRB_API mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id);
+
+MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid);
+MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c);
+MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func);
+
+
+/*
+ * Resume a Fiber
+ *
+ * @mrbgem mruby-fiber
+ */
+MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv);
+
+/*
+ * Yield a Fiber
+ *
+ * @mrbgem mruby-fiber
+ */
+MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
+
+/*
+ * FiberError reference
+ *
+ * @mrbgem mruby-fiber
+ */
+#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError"))
+
+/* memory pool implementation */
+typedef struct mrb_pool mrb_pool;
+MRB_API struct mrb_pool* mrb_pool_open(mrb_state*);
+MRB_API void mrb_pool_close(struct mrb_pool*);
+MRB_API void* mrb_pool_alloc(struct mrb_pool*, size_t);
+MRB_API void* mrb_pool_realloc(struct mrb_pool*, void*, size_t oldlen, size_t newlen);
+MRB_API mrb_bool mrb_pool_can_realloc(struct mrb_pool*, void*, size_t);
+MRB_API void* mrb_alloca(mrb_state *mrb, size_t);
+
+MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func);
+
+MRB_API void mrb_show_version(mrb_state *mrb);
+MRB_API void mrb_show_copyright(mrb_state *mrb);
+
+MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
+
+#if 0
+/* memcpy and memset does not work with gdb reverse-next on my box */
+/* use naive memcpy and memset instead */
+#undef memcpy
+#undef memset
+static inline void*
+mrbmemcpy(void *dst, const void *src, size_t n)
+{
+ char *d = (char*)dst;
+ const char *s = (const char*)src;
+ while (n--)
+ *d++ = *s++;
+ return d;
+}
+#define memcpy(a,b,c) mrbmemcpy(a,b,c)
+
+static inline void*
+mrbmemset(void *s, int c, size_t n)
+{
+ char *t = (char*)s;
+ while (n--)
+ *t++ = c;
+ return s;
+}
+#define memset(a,b,c) mrbmemset(a,b,c)
+#endif
+
+MRB_END_DECL
+
+#endif /* MRUBY_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/array.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/array.h
new file mode 100644
index 00000000..54271555
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/array.h
@@ -0,0 +1,279 @@
+/*
+** mruby/array.h - Array class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_ARRAY_H
+#define MRUBY_ARRAY_H
+
+#include "common.h"
+
+/*
+ * Array class
+ */
+MRB_BEGIN_DECL
+
+
+typedef struct mrb_shared_array {
+ int refcnt;
+ mrb_int len;
+ mrb_value *ptr;
+} mrb_shared_array;
+
+#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
+struct RArray {
+ MRB_OBJECT_HEADER;
+ union {
+ struct {
+ mrb_int len;
+ union {
+ mrb_int capa;
+ mrb_shared_array *shared;
+ } aux;
+ mrb_value *ptr;
+ } heap;
+ mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
+ } as;
+};
+
+#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
+#define mrb_ary_value(p) mrb_obj_value((void*)(p))
+#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
+
+#define MRB_ARY_EMBED_MASK 7
+#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK)
+#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
+#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
+#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | (len + 1))
+#define ARY_EMBED_PTR(a) (&((a)->as.embed[0]))
+
+#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
+#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
+#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
+#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
+#define ARY_SET_LEN(a,n) do {\
+ if (ARY_EMBED_P(a)) {\
+ mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
+ ARY_SET_EMBED_LEN(a,n);\
+ }\
+ else\
+ (a)->as.heap.len = (n);\
+} while (0)
+#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
+#define MRB_ARY_SHARED 256
+#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
+#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
+#define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED)
+
+void mrb_ary_decref(mrb_state*, mrb_shared_array*);
+MRB_API void mrb_ary_modify(mrb_state*, struct RArray*);
+MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int);
+
+/*
+ * Initializes a new array.
+ *
+ * Equivalent to:
+ *
+ * Array.new
+ *
+ * @param mrb The mruby state reference.
+ * @return The initialized array.
+ */
+MRB_API mrb_value mrb_ary_new(mrb_state *mrb);
+
+/*
+ * Initializes a new array with initial values
+ *
+ * Equivalent to:
+ *
+ * Array[value1, value2, ...]
+ *
+ * @param mrb The mruby state reference.
+ * @param size The numer of values.
+ * @param vals The actual values.
+ * @return The initialized array.
+ */
+MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals);
+
+/*
+ * Initializes a new array with two initial values
+ *
+ * Equivalent to:
+ *
+ * Array[car, cdr]
+ *
+ * @param mrb The mruby state reference.
+ * @param car The first value.
+ * @param cdr The second value.
+ * @return The initialized array.
+ */
+MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr);
+
+/*
+ * Concatenate two arrays. The target array will be modified
+ *
+ * Equivalent to:
+ * ary.concat(other)
+ *
+ * @param mrb The mruby state reference.
+ * @param self The target array.
+ * @param other The array that will be concatenated to self.
+ */
+MRB_API void mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other);
+
+/*
+ * Create an array from the input. It tries calling to_a on the
+ * value. If value does not respond to that, it creates a new
+ * array with just this value.
+ *
+ * @param mrb The mruby state reference.
+ * @param value The value to change into an array.
+ * @return An array representation of value.
+ */
+MRB_API mrb_value mrb_ary_splat(mrb_state *mrb, mrb_value value);
+
+/*
+ * Pushes value into array.
+ *
+ * Equivalent to:
+ *
+ * ary << value
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The array in which the value will be pushed
+ * @param value The value to be pushed into array
+ */
+MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value);
+
+/*
+ * Pops the last element from the array.
+ *
+ * Equivalent to:
+ *
+ * ary.pop
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The array from which the value will be popped.
+ * @return The popped value.
+ */
+MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary);
+
+/*
+ * Returns a reference to an element of the array on the given index.
+ *
+ * Equivalent to:
+ *
+ * ary[n]
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The target array.
+ * @param n The array index being referenced
+ * @return The referenced value.
+ */
+MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n);
+
+/*
+ * Sets a value on an array at the given index
+ *
+ * Equivalent to:
+ *
+ * ary[n] = val
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The target array.
+ * @param n The array index being referenced.
+ * @param val The value being setted.
+ */
+MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val);
+
+/*
+ * Replace the array with another array
+ *
+ * Equivalent to:
+ *
+ * ary.replace(other)
+ *
+ * @param mrb The mruby state reference
+ * @param self The target array.
+ * @param other The array to replace it with.
+ */
+MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other);
+MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
+
+/*
+ * Unshift an element into the array
+ *
+ * Equivalent to:
+ *
+ * ary.unshift(item)
+ *
+ * @param mrb The mruby state reference.
+ * @param self The target array.
+ * @param item The item to unshift.
+ */
+MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
+
+/*
+ * Get nth element in the array
+ *
+ * Equivalent to:
+ *
+ * ary[offset]
+ *
+ * @param ary The target array.
+ * @param offset The element position (negative counts from the tail).
+ */
+MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
+
+/*
+ * Shifts the first element from the array.
+ *
+ * Equivalent to:
+ *
+ * ary.shift
+ *
+ * @param mrb The mruby state reference.
+ * @param self The array from which the value will be shifted.
+ * @return The shifted value.
+ */
+MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
+
+/*
+ * Removes all elements from the array
+ *
+ * Equivalent to:
+ *
+ * ary.clear
+ *
+ * @param mrb The mruby state reference.
+ * @param self The target array.
+ * @return self
+ */
+MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self);
+
+/*
+ * Join the array elements together in a string
+ *
+ * Equivalent to:
+ *
+ * ary.join(sep="")
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The target array
+ * @param sep The separater, can be NULL
+ */
+MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
+
+/*
+ * Update the capacity of the array
+ *
+ * @param mrb The mruby state reference.
+ * @param ary The target array.
+ * @param new_len The new capacity of the array
+ */
+MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
+
+MRB_END_DECL
+
+#endif /* MRUBY_ARRAY_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_nan.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_nan.h
new file mode 100644
index 00000000..700ea2ed
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_nan.h
@@ -0,0 +1,98 @@
+/*
+** mruby/boxing_nan.h - nan boxing mrb_value definition
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_BOXING_NAN_H
+#define MRUBY_BOXING_NAN_H
+
+#ifdef MRB_USE_FLOAT
+# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<----
+#endif
+
+#ifdef MRB_INT64
+# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<----
+#endif
+
+#define MRB_FIXNUM_SHIFT 0
+#define MRB_TT_HAS_BASIC MRB_TT_OBJECT
+
+#ifdef MRB_ENDIAN_BIG
+#define MRB_ENDIAN_LOHI(a,b) a b
+#else
+#define MRB_ENDIAN_LOHI(a,b) b a
+#endif
+
+/* value representation by nan-boxing:
+ * float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
+ * object: 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP
+ * int : 1111111111110001 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII
+ * sym : 1111111111110001 0100000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS
+ * In order to get enough bit size to save TT, all pointers are shifted 2 bits
+ * in the right direction. Also, TTTTTT is the mrb_vtype + 1;
+ */
+typedef struct mrb_value {
+ union {
+ mrb_float f;
+ union {
+ void *p;
+ struct {
+ MRB_ENDIAN_LOHI(
+ uint32_t ttt;
+ ,union {
+ mrb_int i;
+ mrb_sym sym;
+ };
+ )
+ };
+ } value;
+ };
+} mrb_value;
+
+#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
+
+#define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)-1)
+#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT)
+#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2))
+#define mrb_float(o) (o).f
+#define mrb_cptr(o) mrb_ptr(o)
+#define mrb_fixnum(o) (o).value.i
+#define mrb_symbol(o) (o).value.sym
+
+#ifdef MRB_64BIT
+#define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff)
+#else
+#define BOXNAN_SHIFT_LONG_POINTER(v) 0
+#endif
+
+#define BOXNAN_SET_VALUE(o, tt, attr, v) do {\
+ (o).attr = (v);\
+ (o).value.ttt = 0xfff00000 | (((tt)+1)<<14);\
+} while (0)
+
+#define BOXNAN_SET_OBJ_VALUE(o, tt, v) do {\
+ (o).value.p = (void*)((uintptr_t)(v)>>2);\
+ (o).value.ttt = (0xfff00000|(((tt)+1)<<14)|BOXNAN_SHIFT_LONG_POINTER(v));\
+} while (0)
+
+#define SET_FLOAT_VALUE(mrb,r,v) do { \
+ if (v != v) { \
+ (r).value.ttt = 0x7ff80000; \
+ (r).value.i = 0; \
+ } \
+ else { \
+ (r).f = v; \
+ }} while(0)
+
+#define SET_NIL_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
+#define SET_FALSE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
+#define SET_TRUE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
+#define SET_BOOL_VALUE(r,b) BOXNAN_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
+#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
+#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
+#define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v))
+#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_OBJ_VALUE(r, MRB_TT_CPTR, v)
+#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
+
+#endif /* MRUBY_BOXING_NAN_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_no.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_no.h
new file mode 100644
index 00000000..7ee44a93
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_no.h
@@ -0,0 +1,48 @@
+/*
+** mruby/boxing_no.h - unboxed mrb_value definition
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_BOXING_NO_H
+#define MRUBY_BOXING_NO_H
+
+#define MRB_FIXNUM_SHIFT 0
+#define MRB_TT_HAS_BASIC MRB_TT_OBJECT
+
+typedef struct mrb_value {
+ union {
+ mrb_float f;
+ void *p;
+ mrb_int i;
+ mrb_sym sym;
+ } value;
+ enum mrb_vtype tt;
+} mrb_value;
+
+#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
+
+#define mrb_ptr(o) (o).value.p
+#define mrb_cptr(o) mrb_ptr(o)
+#define mrb_float(o) (o).value.f
+#define mrb_fixnum(o) (o).value.i
+#define mrb_symbol(o) (o).value.sym
+#define mrb_type(o) (o).tt
+
+#define BOXNIX_SET_VALUE(o, ttt, attr, v) do {\
+ (o).tt = ttt;\
+ (o).attr = v;\
+} while (0)
+
+#define SET_NIL_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
+#define SET_FALSE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
+#define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
+#define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
+#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
+#define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v))
+#define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
+#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
+#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
+#define SET_UNDEF_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
+
+#endif /* MRUBY_BOXING_NO_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_word.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_word.h
new file mode 100644
index 00000000..d1c457fa
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/boxing_word.h
@@ -0,0 +1,120 @@
+/*
+** mruby/boxing_word.h - word boxing mrb_value definition
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_BOXING_WORD_H
+#define MRUBY_BOXING_WORD_H
+
+#if defined(MRB_INT16)
+# error MRB_INT16 is too small for MRB_WORD_BOXING.
+#endif
+
+#if defined(MRB_INT64) && !defined(MRB_64BIT)
+#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode.
+#endif
+
+struct RFloat {
+ MRB_OBJECT_HEADER;
+ mrb_float f;
+};
+
+struct RCptr {
+ MRB_OBJECT_HEADER;
+ void *p;
+};
+
+#define MRB_FIXNUM_SHIFT 1
+#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
+
+enum mrb_special_consts {
+ MRB_Qnil = 0,
+ MRB_Qfalse = 2,
+ MRB_Qtrue = 4,
+ MRB_Qundef = 6,
+};
+
+#define MRB_FIXNUM_FLAG 0x01
+#define MRB_SYMBOL_FLAG 0x0e
+#define MRB_SPECIAL_SHIFT 8
+
+typedef union mrb_value {
+ union {
+ void *p;
+ struct {
+ unsigned int i_flag : MRB_FIXNUM_SHIFT;
+ mrb_int i : (MRB_INT_BIT - MRB_FIXNUM_SHIFT);
+ };
+ struct {
+ unsigned int sym_flag : MRB_SPECIAL_SHIFT;
+ mrb_sym sym : (sizeof(mrb_sym) * CHAR_BIT);
+ };
+ struct RBasic *bp;
+ struct RFloat *fp;
+ struct RCptr *vp;
+ } value;
+ unsigned long w;
+} mrb_value;
+
+MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
+MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
+MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
+
+#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f)
+
+#define mrb_ptr(o) (o).value.p
+#define mrb_cptr(o) (o).value.vp->p
+#define mrb_float(o) (o).value.fp->f
+#define mrb_fixnum(o) ((mrb_int)(o).value.i)
+#define mrb_symbol(o) (o).value.sym
+
+static inline enum mrb_vtype
+mrb_type(mrb_value o)
+{
+ switch (o.w) {
+ case MRB_Qfalse:
+ case MRB_Qnil:
+ return MRB_TT_FALSE;
+ case MRB_Qtrue:
+ return MRB_TT_TRUE;
+ case MRB_Qundef:
+ return MRB_TT_UNDEF;
+ }
+ if (o.value.i_flag == MRB_FIXNUM_FLAG) {
+ return MRB_TT_FIXNUM;
+ }
+ if (o.value.sym_flag == MRB_SYMBOL_FLAG) {
+ return MRB_TT_SYMBOL;
+ }
+ return o.value.bp->tt;
+}
+
+#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse)
+#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG)
+#define mrb_undef_p(o) ((o).w == MRB_Qundef)
+#define mrb_nil_p(o) ((o).w == MRB_Qnil)
+
+#define BOXWORD_SET_VALUE(o, ttt, attr, v) do { \
+ switch (ttt) {\
+ case MRB_TT_FALSE: (o).w = (v) ? MRB_Qfalse : MRB_Qnil; break;\
+ case MRB_TT_TRUE: (o).w = MRB_Qtrue; break;\
+ case MRB_TT_UNDEF: (o).w = MRB_Qundef; break;\
+ case MRB_TT_FIXNUM: (o).w = 0;(o).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\
+ case MRB_TT_SYMBOL: (o).w = 0;(o).value.sym_flag = MRB_SYMBOL_FLAG; (o).attr = (v); break;\
+ default: (o).w = 0; (o).attr = (v); if ((o).value.bp) (o).value.bp->tt = ttt; break;\
+ }\
+} while (0)
+
+#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v)
+#define SET_CPTR_VALUE(mrb,r,v) r = mrb_word_boxing_cptr_value(mrb, v)
+#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
+#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
+#define SET_TRUE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
+#define SET_BOOL_VALUE(r,b) BOXWORD_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
+#define SET_INT_VALUE(r,n) BOXWORD_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
+#define SET_SYM_VALUE(r,v) BOXWORD_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
+#define SET_OBJ_VALUE(r,v) BOXWORD_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
+#define SET_UNDEF_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
+
+#endif /* MRUBY_BOXING_WORD_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/class.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/class.h
new file mode 100644
index 00000000..c0317b45
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/class.h
@@ -0,0 +1,92 @@
+/*
+** mruby/class.h - Class class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_CLASS_H
+#define MRUBY_CLASS_H
+
+#include "common.h"
+
+/**
+ * Class class
+ */
+MRB_BEGIN_DECL
+
+struct RClass {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+ struct kh_mt *mt;
+ struct RClass *super;
+};
+
+#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v)))
+#define RCLASS_SUPER(v) (((struct RClass*)(mrb_ptr(v)))->super)
+#define RCLASS_IV_TBL(v) (((struct RClass*)(mrb_ptr(v)))->iv)
+#define RCLASS_M_TBL(v) (((struct RClass*)(mrb_ptr(v)))->mt)
+
+static inline struct RClass*
+mrb_class(mrb_state *mrb, mrb_value v)
+{
+ switch (mrb_type(v)) {
+ case MRB_TT_FALSE:
+ if (mrb_fixnum(v))
+ return mrb->false_class;
+ return mrb->nil_class;
+ case MRB_TT_TRUE:
+ return mrb->true_class;
+ case MRB_TT_SYMBOL:
+ return mrb->symbol_class;
+ case MRB_TT_FIXNUM:
+ return mrb->fixnum_class;
+ case MRB_TT_FLOAT:
+ return mrb->float_class;
+ case MRB_TT_CPTR:
+ return mrb->object_class;
+ case MRB_TT_ENV:
+ return NULL;
+ default:
+ return mrb_obj_ptr(v)->c;
+ }
+}
+
+/* TODO: figure out where to put user flags */
+#define MRB_FLAG_IS_FROZEN (1 << 18)
+#define MRB_FLAG_IS_PREPENDED (1 << 19)
+#define MRB_FLAG_IS_ORIGIN (1 << 20)
+#define MRB_CLASS_ORIGIN(c) do {\
+ if (c->flags & MRB_FLAG_IS_PREPENDED) {\
+ c = c->super;\
+ while (!(c->flags & MRB_FLAG_IS_ORIGIN)) {\
+ c = c->super;\
+ }\
+ }\
+} while (0)
+#define MRB_FLAG_IS_INHERITED (1 << 21)
+#define MRB_INSTANCE_TT_MASK (0xFF)
+#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt)
+#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK)
+
+MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
+MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
+MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
+MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
+MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
+MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
+MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
+
+MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
+MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
+
+MRB_API struct RClass* mrb_class_real(struct RClass* cl);
+
+void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
+mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
+void mrb_gc_mark_mt(mrb_state*, struct RClass*);
+size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
+void mrb_gc_free_mt(mrb_state*, struct RClass*);
+
+MRB_END_DECL
+
+#endif /* MRUBY_CLASS_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/common.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/common.h
new file mode 100644
index 00000000..d6ec78b0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/common.h
@@ -0,0 +1,72 @@
+/*
+**"common.h - mruby common platform definition"
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_COMMON_H
+#define MRUBY_COMMON_H
+
+
+#ifdef __cplusplus
+#ifdef MRB_ENABLE_CXX_ABI
+#define MRB_BEGIN_DECL
+#define MRB_END_DECL
+#else
+# define MRB_BEGIN_DECL extern "C" {
+# define MRB_END_DECL }
+#endif
+#else
+/** Start declarations in C mode */
+# define MRB_BEGIN_DECL
+/** End declarations in C mode */
+# define MRB_END_DECL
+#endif
+
+/**
+ * Shared compiler macros
+ */
+MRB_BEGIN_DECL
+
+/** Declare a function that never returns. */
+#if __STDC_VERSION__ >= 201112L
+# define mrb_noreturn _Noreturn
+#elif defined __GNUC__ && !defined __STRICT_ANSI__
+# define mrb_noreturn __attribute__((noreturn))
+#elif defined _MSC_VER
+# define mrb_noreturn __declspec(noreturn)
+#else
+# define mrb_noreturn
+#endif
+
+/** Mark a function as deprecated. */
+#if defined __GNUC__ && !defined __STRICT_ANSI__
+# define mrb_deprecated __attribute__((deprecated))
+#elif defined _MSC_VER
+# define mrb_deprecated __declspec(deprecated)
+#else
+# define mrb_deprecated
+#endif
+
+/** Declare a function as always inlined. */
+#if defined(_MSC_VER)
+# define MRB_INLINE static __inline
+#else
+# define MRB_INLINE static inline
+#endif
+
+
+/** Declare a public MRuby API function. */
+#if defined(MRB_BUILD_AS_DLL)
+#if defined(MRB_CORE) || defined(MRB_LIB)
+# define MRB_API __declspec(dllexport)
+#else
+# define MRB_API __declspec(dllimport)
+#endif
+#else
+# define MRB_API extern
+#endif
+
+MRB_END_DECL
+
+#endif /* MRUBY_COMMON_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/compile.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/compile.h
new file mode 100644
index 00000000..d1ff0530
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/compile.h
@@ -0,0 +1,195 @@
+/*
+** mruby/compile.h - mruby parser
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_COMPILE_H
+#define MRUBY_COMPILE_H
+
+#include "common.h"
+
+/**
+ * MRuby Compiler
+ */
+MRB_BEGIN_DECL
+
+#include <mruby.h>
+
+struct mrb_jmpbuf;
+
+struct mrb_parser_state;
+/* load context */
+typedef struct mrbc_context {
+ mrb_sym *syms;
+ int slen;
+ char *filename;
+ short lineno;
+ int (*partial_hook)(struct mrb_parser_state*);
+ void *partial_data;
+ struct RClass *target_class;
+ mrb_bool capture_errors:1;
+ mrb_bool dump_result:1;
+ mrb_bool no_exec:1;
+ mrb_bool keep_lv:1;
+ mrb_bool no_optimize:1;
+
+ size_t parser_nerr;
+} mrbc_context;
+
+MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb);
+MRB_API void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt);
+MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s);
+MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data);
+
+/* AST node structure */
+typedef struct mrb_ast_node {
+ struct mrb_ast_node *car, *cdr;
+ uint16_t lineno, filename_index;
+} mrb_ast_node;
+
+/* lexer states */
+enum mrb_lex_state_enum {
+ EXPR_BEG, /* ignore newline, +/- is a sign. */
+ EXPR_END, /* newline significant, +/- is an operator. */
+ EXPR_ENDARG, /* ditto, and unbound braces. */
+ EXPR_ENDFN, /* ditto, and unbound braces. */
+ EXPR_ARG, /* newline significant, +/- is an operator. */
+ EXPR_CMDARG, /* newline significant, +/- is an operator. */
+ EXPR_MID, /* newline significant, +/- is an operator. */
+ EXPR_FNAME, /* ignore newline, no reserved words. */
+ EXPR_DOT, /* right after '.' or '::', no reserved words. */
+ EXPR_CLASS, /* immediate after 'class', no here document. */
+ EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */
+ EXPR_MAX_STATE
+};
+
+/* saved error message */
+struct mrb_parser_message {
+ int lineno;
+ int column;
+ char* message;
+};
+
+#define STR_FUNC_PARSING 0x01
+#define STR_FUNC_EXPAND 0x02
+#define STR_FUNC_REGEXP 0x04
+#define STR_FUNC_WORD 0x08
+#define STR_FUNC_SYMBOL 0x10
+#define STR_FUNC_ARRAY 0x20
+#define STR_FUNC_HEREDOC 0x40
+#define STR_FUNC_XQUOTE 0x80
+
+enum mrb_string_type {
+ str_not_parsing = (0),
+ str_squote = (STR_FUNC_PARSING),
+ str_dquote = (STR_FUNC_PARSING|STR_FUNC_EXPAND),
+ str_regexp = (STR_FUNC_PARSING|STR_FUNC_REGEXP|STR_FUNC_EXPAND),
+ str_sword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY),
+ str_dword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
+ str_ssym = (STR_FUNC_PARSING|STR_FUNC_SYMBOL),
+ str_ssymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY),
+ str_dsymbols = (STR_FUNC_PARSING|STR_FUNC_SYMBOL|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
+ str_heredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC),
+ str_xquote = (STR_FUNC_PARSING|STR_FUNC_XQUOTE|STR_FUNC_EXPAND),
+};
+
+/* heredoc structure */
+struct mrb_parser_heredoc_info {
+ mrb_bool allow_indent:1;
+ mrb_bool line_head:1;
+ enum mrb_string_type type;
+ const char *term;
+ int term_len;
+ mrb_ast_node *doc;
+};
+
+#define MRB_PARSER_TOKBUF_MAX 65536
+#define MRB_PARSER_TOKBUF_SIZE 256
+
+/* parser structure */
+struct mrb_parser_state {
+ mrb_state *mrb;
+ struct mrb_pool *pool;
+ mrb_ast_node *cells;
+ const char *s, *send;
+#ifndef MRB_DISABLE_STDIO
+ FILE *f;
+#endif
+ mrbc_context *cxt;
+ char const *filename;
+ int lineno;
+ int column;
+
+ enum mrb_lex_state_enum lstate;
+ mrb_ast_node *lex_strterm; /* (type nest_level beg . end) */
+
+ unsigned int cond_stack;
+ unsigned int cmdarg_stack;
+ int paren_nest;
+ int lpar_beg;
+ int in_def, in_single;
+ mrb_bool cmd_start:1;
+ mrb_ast_node *locals;
+
+ mrb_ast_node *pb;
+ char *tokbuf;
+ char buf[MRB_PARSER_TOKBUF_SIZE];
+ int tidx;
+ int tsiz;
+
+ mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
+ mrb_ast_node *heredocs_from_nextline;
+ mrb_ast_node *parsing_heredoc;
+ mrb_ast_node *lex_strterm_before_heredoc;
+ mrb_bool heredoc_end_now:1; /* for mirb */
+
+ void *ylval;
+
+ size_t nerr;
+ size_t nwarn;
+ mrb_ast_node *tree;
+
+ mrb_bool no_optimize:1;
+ mrb_bool capture_errors:1;
+ struct mrb_parser_message error_buffer[10];
+ struct mrb_parser_message warn_buffer[10];
+
+ mrb_sym* filename_table;
+ size_t filename_table_length;
+ int current_filename_index;
+
+ struct mrb_jmpbuf* jmp;
+};
+
+MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*);
+MRB_API void mrb_parser_free(struct mrb_parser_state*);
+MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
+MRB_API double mrb_float_read(const char*, char**);
+
+MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
+MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
+
+/* utility functions */
+#ifndef MRB_DISABLE_STDIO
+MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
+#endif
+MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
+MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrbc_context*);
+MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
+MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c);
+
+/* program load functions */
+#ifndef MRB_DISABLE_STDIO
+MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
+MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
+#endif
+MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s);
+MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len);
+MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
+MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *cxt);
+
+/** @} */
+MRB_END_DECL
+
+#endif /* MRUBY_COMPILE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/data.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/data.h
new file mode 100644
index 00000000..59047052
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/data.h
@@ -0,0 +1,75 @@
+/*
+** mruby/data.h - Data class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_DATA_H
+#define MRUBY_DATA_H
+
+#include "common.h"
+
+/**
+ * Custom C wrapped data.
+ *
+ * Defining Ruby wrappers around native objects.
+ */
+MRB_BEGIN_DECL
+
+/**
+ * Custom data type description.
+ */
+typedef struct mrb_data_type {
+ /** data type name */
+ const char *struct_name;
+
+ /** data type release function pointer */
+ void (*dfree)(mrb_state *mrb, void*);
+} mrb_data_type;
+
+struct RData {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+ const mrb_data_type *type;
+ void *data;
+};
+
+MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void *datap, const mrb_data_type *type);
+
+#define Data_Wrap_Struct(mrb,klass,type,ptr)\
+ mrb_data_object_alloc(mrb,klass,ptr,type)
+
+#define Data_Make_Struct(mrb,klass,strct,type,sval,data) do { \
+ sval = mrb_malloc(mrb, sizeof(strct)); \
+ { static const strct zero = { 0 }; *sval = zero; };\
+ data = Data_Wrap_Struct(mrb,klass,type,sval);\
+} while (0)
+
+#define RDATA(obj) ((struct RData *)(mrb_ptr(obj)))
+#define DATA_PTR(d) (RDATA(d)->data)
+#define DATA_TYPE(d) (RDATA(d)->type)
+MRB_API void mrb_data_check_type(mrb_state *mrb, mrb_value, const mrb_data_type*);
+MRB_API void *mrb_data_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*);
+#define DATA_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_get_ptr(mrb,obj,dtype)
+MRB_API void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*);
+#define DATA_CHECK_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_check_get_ptr(mrb,obj,dtype)
+
+/* obsolete functions and macros */
+#define mrb_data_check_and_get(mrb,obj,dtype) mrb_data_get_ptr(mrb,obj,dtype)
+#define mrb_get_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type)
+#define mrb_check_datatype(mrb,val,type) mrb_data_get_ptr(mrb, val, type)
+#define Data_Get_Struct(mrb,obj,type,sval) do {\
+ *(void**)&sval = mrb_data_get_ptr(mrb, obj, type); \
+} while (0)
+
+static inline void
+mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type)
+{
+ mrb_assert(mrb_type(v) == MRB_TT_DATA);
+ DATA_PTR(v) = ptr;
+ DATA_TYPE(v) = type;
+}
+
+MRB_END_DECL
+
+#endif /* MRUBY_DATA_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/debug.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/debug.h
new file mode 100644
index 00000000..d1de3488
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/debug.h
@@ -0,0 +1,66 @@
+/*
+** mruby/debug.h - mruby debug info
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_DEBUG_H
+#define MRUBY_DEBUG_H
+
+#include "common.h"
+
+/**
+ * MRuby Debugging.
+ */
+MRB_BEGIN_DECL
+
+typedef enum mrb_debug_line_type {
+ mrb_debug_line_ary = 0,
+ mrb_debug_line_flat_map = 1
+} mrb_debug_line_type;
+
+typedef struct mrb_irep_debug_info_line {
+ uint32_t start_pos;
+ uint16_t line;
+} mrb_irep_debug_info_line;
+
+typedef struct mrb_irep_debug_info_file {
+ uint32_t start_pos;
+ const char *filename;
+ mrb_sym filename_sym;
+ uint32_t line_entry_count;
+ mrb_debug_line_type line_type;
+ union {
+ void *ptr;
+ mrb_irep_debug_info_line *flat_map;
+ uint16_t *ary;
+ } lines;
+} mrb_irep_debug_info_file;
+
+typedef struct mrb_irep_debug_info {
+ uint32_t pc_count;
+ uint16_t flen;
+ mrb_irep_debug_info_file **files;
+} mrb_irep_debug_info;
+
+/*
+ * get line from irep's debug info and program counter
+ * @return returns NULL if not found
+ */
+MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc);
+
+/*
+ * get line from irep's debug info and program counter
+ * @return returns -1 if not found
+ */
+MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc);
+
+MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
+ mrb_state *mrb, mrb_irep *irep,
+ uint32_t start_pos, uint32_t end_pos);
+MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep);
+MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d);
+
+MRB_END_DECL
+
+#endif /* MRUBY_DEBUG_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/dump.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/dump.h
new file mode 100644
index 00000000..f56d66a3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/dump.h
@@ -0,0 +1,196 @@
+/*
+** mruby/dump.h - mruby binary dumper (mrbc binary format)
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_DUMP_H
+#define MRUBY_DUMP_H
+
+#include <mruby.h>
+#include <mruby/irep.h>
+#include "common.h"
+
+/**
+ * Dumping compiled mruby script.
+ */
+MRB_BEGIN_DECL
+
+#define DUMP_DEBUG_INFO 1
+#define DUMP_ENDIAN_BIG 2
+#define DUMP_ENDIAN_LIL 4
+#define DUMP_ENDIAN_NAT 6
+#define DUMP_ENDIAN_MASK 6
+
+int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
+#ifndef MRB_DISABLE_STDIO
+int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*);
+int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname);
+mrb_irep *mrb_read_irep_file(mrb_state*, FILE*);
+MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*);
+MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*);
+#endif
+MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
+
+/* dump/load error code
+ *
+ * NOTE: MRB_DUMP_GENERAL_FAILURE is caused by
+ * unspecified issues like malloc failed.
+ */
+#define MRB_DUMP_OK 0
+#define MRB_DUMP_GENERAL_FAILURE (-1)
+#define MRB_DUMP_WRITE_FAULT (-2)
+#define MRB_DUMP_READ_FAULT (-3)
+#define MRB_DUMP_CRC_ERROR (-4)
+#define MRB_DUMP_INVALID_FILE_HEADER (-5)
+#define MRB_DUMP_INVALID_IREP (-6)
+#define MRB_DUMP_INVALID_ARGUMENT (-7)
+
+/* null symbol length */
+#define MRB_DUMP_NULL_SYM_LEN 0xFFFF
+
+/* Rite Binary File header */
+#define RITE_BINARY_IDENT "RITE"
+#define RITE_BINARY_IDENT_LIL "ETIR"
+#define RITE_BINARY_FORMAT_VER "0004"
+#define RITE_COMPILER_NAME "MATZ"
+#define RITE_COMPILER_VERSION "0000"
+
+#define RITE_VM_VER "0000"
+
+#define RITE_BINARY_EOF "END\0"
+#define RITE_SECTION_IREP_IDENT "IREP"
+#define RITE_SECTION_LINENO_IDENT "LINE"
+#define RITE_SECTION_DEBUG_IDENT "DBG\0"
+#define RITE_SECTION_LV_IDENT "LVAR"
+
+#define MRB_DUMP_DEFAULT_STR_LEN 128
+#define MRB_DUMP_ALIGNMENT sizeof(uint32_t)
+
+/* binary header */
+struct rite_binary_header {
+ uint8_t binary_ident[4]; /* Binary Identifier */
+ uint8_t binary_version[4]; /* Binary Format Version */
+ uint8_t binary_crc[2]; /* Binary CRC */
+ uint8_t binary_size[4]; /* Binary Size */
+ uint8_t compiler_name[4]; /* Compiler name */
+ uint8_t compiler_version[4];
+};
+
+/* section header */
+#define RITE_SECTION_HEADER \
+ uint8_t section_ident[4]; \
+ uint8_t section_size[4]
+
+struct rite_section_header {
+ RITE_SECTION_HEADER;
+};
+
+struct rite_section_irep_header {
+ RITE_SECTION_HEADER;
+
+ uint8_t rite_version[4]; /* Rite Instruction Specification Version */
+};
+
+struct rite_section_lineno_header {
+ RITE_SECTION_HEADER;
+};
+
+struct rite_section_debug_header {
+ RITE_SECTION_HEADER;
+};
+
+struct rite_section_lv_header {
+ RITE_SECTION_HEADER;
+};
+
+#define RITE_LV_NULL_MARK UINT16_MAX
+
+struct rite_binary_footer {
+ RITE_SECTION_HEADER;
+};
+
+static inline int
+bigendian_p()
+{
+ int i;
+ char *p;
+
+ i = 1;
+ p = (char*)&i;
+ return p[0]?0:1;
+}
+
+static inline size_t
+uint8_to_bin(uint8_t s, uint8_t *bin)
+{
+ *bin = s;
+ return sizeof(uint8_t);
+}
+
+static inline size_t
+uint16_to_bin(uint16_t s, uint8_t *bin)
+{
+ *bin++ = (s >> 8) & 0xff;
+ *bin = s & 0xff;
+ return sizeof(uint16_t);
+}
+
+static inline size_t
+uint32_to_bin(uint32_t l, uint8_t *bin)
+{
+ *bin++ = (l >> 24) & 0xff;
+ *bin++ = (l >> 16) & 0xff;
+ *bin++ = (l >> 8) & 0xff;
+ *bin = l & 0xff;
+ return sizeof(uint32_t);
+}
+
+static inline size_t
+uint32l_to_bin(uint32_t l, uint8_t *bin)
+{
+ bin[3] = (l >> 24) & 0xff;
+ bin[2] = (l >> 16) & 0xff;
+ bin[1] = (l >> 8) & 0xff;
+ bin[0] = l & 0xff;
+ return sizeof(uint32_t);
+}
+
+static inline uint32_t
+bin_to_uint32(const uint8_t *bin)
+{
+ return (uint32_t)bin[0] << 24 |
+ (uint32_t)bin[1] << 16 |
+ (uint32_t)bin[2] << 8 |
+ (uint32_t)bin[3];
+}
+
+static inline uint32_t
+bin_to_uint32l(const uint8_t *bin)
+{
+ return (uint32_t)bin[3] << 24 |
+ (uint32_t)bin[2] << 16 |
+ (uint32_t)bin[1] << 8 |
+ (uint32_t)bin[0];
+}
+
+static inline uint16_t
+bin_to_uint16(const uint8_t *bin)
+{
+ return (uint16_t)bin[0] << 8 |
+ (uint16_t)bin[1];
+}
+
+static inline uint8_t
+bin_to_uint8(const uint8_t *bin)
+{
+ return (uint8_t)bin[0];
+}
+
+MRB_END_DECL
+
+/** @internal crc.c */
+uint16_t
+calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc);
+
+#endif /* MRUBY_DUMP_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/error.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/error.h
new file mode 100644
index 00000000..0a262550
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/error.h
@@ -0,0 +1,76 @@
+/*
+** mruby/error.h - Exception class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_ERROR_H
+#define MRUBY_ERROR_H
+
+#include "common.h"
+
+/**
+ * MRuby error handling.
+ */
+MRB_BEGIN_DECL
+
+struct RException {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+};
+
+#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v))
+
+MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
+MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
+#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
+MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
+MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
+MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
+MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
+
+/* declaration for fail method */
+MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
+
+struct RBreak {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+ struct RProc *proc;
+ mrb_value val;
+};
+
+/**
+ * Protect
+ *
+ * @mrbgem mruby-error
+ */
+MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
+
+/**
+ * Ensure
+ *
+ * @mrbgem mruby-error
+ */
+MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t ensure, mrb_value e_data);
+
+/**
+ * Rescue
+ *
+ * @mrbgem mruby-error
+ */
+MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t rescue, mrb_value r_data);
+
+/**
+ * Rescue exception
+ *
+ * @mrbgem mruby-error
+ */
+MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t rescue, mrb_value r_data,
+ mrb_int len, struct RClass **classes);
+
+MRB_END_DECL
+
+#endif /* MRUBY_ERROR_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/gc.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/gc.h
new file mode 100644
index 00000000..ce214aa5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/gc.h
@@ -0,0 +1,80 @@
+/*
+** mruby/gc.h - garbage collector for mruby
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_GC_H
+#define MRUBY_GC_H
+
+#include "common.h"
+
+/**
+ * Uncommon memory management stuffs.
+ */
+MRB_BEGIN_DECL
+
+
+struct mrb_state;
+
+#define MRB_EACH_OBJ_OK 0
+#define MRB_EACH_OBJ_BREAK 1
+typedef int (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data);
+void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data);
+MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c);
+
+#ifndef MRB_GC_ARENA_SIZE
+#define MRB_GC_ARENA_SIZE 100
+#endif
+
+typedef enum {
+ MRB_GC_STATE_ROOT = 0,
+ MRB_GC_STATE_MARK,
+ MRB_GC_STATE_SWEEP
+} mrb_gc_state;
+
+typedef struct mrb_heap_page {
+ struct RBasic *freelist;
+ struct mrb_heap_page *prev;
+ struct mrb_heap_page *next;
+ struct mrb_heap_page *free_next;
+ struct mrb_heap_page *free_prev;
+ mrb_bool old:1;
+ void *objects[];
+} mrb_heap_page;
+
+typedef struct mrb_gc {
+ mrb_heap_page *heaps; /* heaps for GC */
+ mrb_heap_page *sweeps;
+ mrb_heap_page *free_heaps;
+ size_t live; /* count of live objects */
+#ifdef MRB_GC_FIXED_ARENA
+ struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */
+#else
+ struct RBasic **arena; /* GC protection array */
+ int arena_capa;
+#endif
+ int arena_idx;
+
+ mrb_gc_state state; /* state of gc */
+ int current_white_part; /* make white object by white_part */
+ struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */
+ struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */
+ size_t live_after_mark;
+ size_t threshold;
+ int interval_ratio;
+ int step_ratio;
+ mrb_bool iterating :1;
+ mrb_bool disabled :1;
+ mrb_bool full :1;
+ mrb_bool generational :1;
+ mrb_bool out_of_memory :1;
+ size_t majorgc_old_threshold;
+} mrb_gc;
+
+MRB_API mrb_bool
+mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object);
+
+MRB_END_DECL
+
+#endif /* MRUBY_GC_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/hash.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/hash.h
new file mode 100644
index 00000000..1a870785
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/hash.h
@@ -0,0 +1,182 @@
+/*
+** mruby/hash.h - Hash class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_HASH_H
+#define MRUBY_HASH_H
+
+#include "common.h"
+#include <mruby/khash.h>
+
+/**
+ * Hash class
+ */
+MRB_BEGIN_DECL
+
+struct RHash {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+ struct kh_ht *ht;
+};
+
+#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
+#define mrb_hash_value(p) mrb_obj_value((void*)(p))
+
+MRB_API mrb_value mrb_hash_new_capa(mrb_state*, mrb_int);
+
+/*
+ * Initializes a new hash.
+ *
+ * Equivalent to:
+ *
+ * Hash.new
+ *
+ * @param mrb The mruby state reference.
+ * @return The initialized hash.
+ */
+MRB_API mrb_value mrb_hash_new(mrb_state *mrb);
+
+/*
+ * Sets a keys and values to hashes.
+ *
+ * Equivalent to:
+ *
+ * hash[key] = val
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @param key The key to set.
+ * @param val The value to set.
+ * @return The value.
+ */
+MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val);
+
+/*
+ * Gets a value from a key. If the key is not found, the default of the
+ * hash is used.
+ *
+ * Equivalent to:
+ *
+ * hash[key]
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @param key The key to get.
+ * @return The found value.
+ */
+MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
+
+/*
+ * Gets a value from a key. If the key is not found, the default parameter is
+ * used.
+ *
+ * Equivalent to:
+ *
+ * hash.hash_key?(key) ? hash[key] : def
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @param key The key to get.
+ * @param def The default value.
+ * @return The found value.
+ */
+MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def);
+
+/*
+ * Deletes hash key and value pair.
+ *
+ * Equivalent to:
+ *
+ * hash.delete(key)
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @param key The key to delete.
+ * @return The deleted value.
+ */
+MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
+
+/*
+ * Gets an array of keys.
+ *
+ * Equivalent to:
+ *
+ * hash.keys
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @return An array with the keys of the hash.
+ */
+MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
+MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
+
+/*
+ * Check if the hash is empty
+ *
+ * Equivalent to:
+ *
+ * hash.empty?
+ *
+ * @param mrb The mruby state reference.
+ * @param self The target hash.
+ * @return True if the hash is empty, false otherwise.
+ */
+MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
+
+/*
+ * Gets an array of values.
+ *
+ * Equivalent to:
+ *
+ * hash.values
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @return An array with the values of the hash.
+ */
+MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
+
+/*
+ * Clears the hash.
+ *
+ * Equivalent to:
+ *
+ * hash.clear
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @return The hash
+ */
+MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
+
+/* declaration of struct kh_ht */
+/* be careful when you touch the internal */
+typedef struct {
+ mrb_value v;
+ mrb_int n;
+} mrb_hash_value;
+
+KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE)
+
+/* RHASH_TBL allocates st_table if not available. */
+#define RHASH(obj) ((struct RHash*)(mrb_ptr(obj)))
+#define RHASH_TBL(h) (RHASH(h)->ht)
+#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone"))
+#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
+MRB_API struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
+
+#define MRB_HASH_DEFAULT 1
+#define MRB_HASH_PROC_DEFAULT 2
+#define MRB_RHASH_DEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_DEFAULT)
+#define MRB_RHASH_PROCDEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_PROC_DEFAULT)
+
+/* GC functions */
+void mrb_gc_mark_hash(mrb_state*, struct RHash*);
+size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*);
+void mrb_gc_free_hash(mrb_state*, struct RHash*);
+
+MRB_END_DECL
+
+#endif /* MRUBY_HASH_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/irep.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/irep.h
new file mode 100644
index 00000000..2717b09c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/irep.h
@@ -0,0 +1,64 @@
+/*
+** mruby/irep.h - mrb_irep structure
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_IREP_H
+#define MRUBY_IREP_H
+
+#include "common.h"
+#include <mruby/compile.h>
+
+/**
+ * Compiled mruby scripts.
+ */
+MRB_BEGIN_DECL
+
+enum irep_pool_type {
+ IREP_TT_STRING,
+ IREP_TT_FIXNUM,
+ IREP_TT_FLOAT,
+};
+
+struct mrb_locals {
+ mrb_sym name;
+ uint16_t r;
+};
+
+/* Program data array struct */
+typedef struct mrb_irep {
+ uint16_t nlocals; /* Number of local variables */
+ uint16_t nregs; /* Number of register variables */
+ uint8_t flags;
+
+ mrb_code *iseq;
+ mrb_value *pool;
+ mrb_sym *syms;
+ struct mrb_irep **reps;
+
+ struct mrb_locals *lv;
+ /* debug info */
+ mrb_bool own_filename;
+ const char *filename;
+ uint16_t *lines;
+ struct mrb_irep_debug_info* debug_info;
+
+ int ilen, plen, slen, rlen, refcnt;
+
+ struct mrb_irep *outer; /* Refers outer scope */
+ struct RClass *target_class;
+} mrb_irep;
+
+#define MRB_ISEQ_NO_FREE 1
+
+MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
+MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
+MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
+void mrb_irep_free(mrb_state*, struct mrb_irep*);
+void mrb_irep_incref(mrb_state*, struct mrb_irep*);
+void mrb_irep_decref(mrb_state*, struct mrb_irep*);
+
+MRB_END_DECL
+
+#endif /* MRUBY_IREP_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/istruct.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/istruct.h
new file mode 100644
index 00000000..4d2393cc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/istruct.h
@@ -0,0 +1,47 @@
+/*
+** mruby/istruct.h - Inline structures
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_ISTRUCT_H
+#define MRUBY_ISTRUCT_H
+
+#include "common.h"
+#include <string.h>
+
+/**
+ * Inline structures that fit in RVALUE
+ *
+ * They cannot have finalizer, and cannot have instance variables.
+ */
+MRB_BEGIN_DECL
+
+#define ISTRUCT_DATA_SIZE (sizeof(void*) * 3)
+
+struct RIstruct {
+ MRB_OBJECT_HEADER;
+ char inline_data[ISTRUCT_DATA_SIZE];
+};
+
+#define RISTRUCT(obj) ((struct RIstruct*)(mrb_ptr(obj)))
+#define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data)
+
+MRB_INLINE mrb_int mrb_istruct_size()
+{
+ return ISTRUCT_DATA_SIZE;
+}
+
+MRB_INLINE void* mrb_istruct_ptr(mrb_value object)
+{
+ return ISTRUCT_PTR(object);
+}
+
+MRB_INLINE void mrb_istruct_copy(mrb_value dest, mrb_value src)
+{
+ memcpy(ISTRUCT_PTR(dest), ISTRUCT_PTR(src), ISTRUCT_DATA_SIZE);
+}
+
+MRB_END_DECL
+
+#endif /* MRUBY_ISTRUCT_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/khash.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/khash.h
new file mode 100644
index 00000000..9c40c6b8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/khash.h
@@ -0,0 +1,274 @@
+/*
+** mruby/khash.c - Hash for mruby
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_KHASH_H
+#define MRUBY_KHASH_H
+
+#include <string.h>
+
+#include <mruby.h>
+#include "common.h"
+
+/**
+ * khash definitions used in mruby's hash table.
+ */
+MRB_BEGIN_DECL
+
+typedef uint32_t khint_t;
+typedef khint_t khiter_t;
+
+#ifndef KHASH_DEFAULT_SIZE
+# define KHASH_DEFAULT_SIZE 32
+#endif
+#define KHASH_MIN_SIZE 8
+
+#define UPPER_BOUND(x) ((x)>>2|(x)>>1)
+
+/* extern uint8_t __m[]; */
+
+/* mask for flags */
+static const uint8_t __m_empty[] = {0x02, 0x08, 0x20, 0x80};
+static const uint8_t __m_del[] = {0x01, 0x04, 0x10, 0x40};
+static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
+
+
+#define __ac_isempty(ed_flag, i) (ed_flag[(i)/4]&__m_empty[(i)%4])
+#define __ac_isdel(ed_flag, i) (ed_flag[(i)/4]&__m_del[(i)%4])
+#define __ac_iseither(ed_flag, i) (ed_flag[(i)/4]&__m_either[(i)%4])
+#define khash_power2(v) do { \
+ v--;\
+ v |= v >> 1;\
+ v |= v >> 2;\
+ v |= v >> 4;\
+ v |= v >> 8;\
+ v |= v >> 16;\
+ v++;\
+} while (0)
+#define khash_mask(h) ((h)->n_buckets-1)
+#define khash_upper_bound(h) (UPPER_BOUND((h)->n_buckets))
+
+/* declare struct kh_xxx and kh_xxx_funcs
+
+ name: hash name
+ khkey_t: key data type
+ khval_t: value data type
+ kh_is_map: (0: hash set / 1: hash map)
+*/
+#define KHASH_DECLARE(name, khkey_t, khval_t, kh_is_map) \
+ typedef struct kh_##name { \
+ khint_t n_buckets; \
+ khint_t size; \
+ khint_t n_occupied; \
+ uint8_t *ed_flags; \
+ khkey_t *keys; \
+ khval_t *vals; \
+ } kh_##name##_t; \
+ void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h); \
+ kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size); \
+ kh_##name##_t *kh_init_##name(mrb_state *mrb); \
+ void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h); \
+ void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
+ khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
+ khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
+ void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
+ void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
+ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
+
+static inline void
+kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
+{
+ while (len-- > 0) {
+ *p++ = c;
+ }
+}
+
+/* define kh_xxx_funcs
+
+ name: hash name
+ khkey_t: key data type
+ khval_t: value data type
+ kh_is_map: (0: hash set / 1: hash map)
+ __hash_func: hash function
+ __hash_equal: hash comparation function
+*/
+#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
+ void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
+ { \
+ khint_t sz = h->n_buckets; \
+ size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
+ uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
+ h->size = h->n_occupied = 0; \
+ h->keys = (khkey_t *)p; \
+ h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
+ h->ed_flags = p+len*sz; \
+ kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
+ } \
+ kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
+ kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
+ if (size < KHASH_MIN_SIZE) \
+ size = KHASH_MIN_SIZE; \
+ khash_power2(size); \
+ h->n_buckets = size; \
+ kh_alloc_##name(mrb, h); \
+ return h; \
+ } \
+ kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
+ return kh_init_##name##_size(mrb, KHASH_DEFAULT_SIZE); \
+ } \
+ void kh_destroy_##name(mrb_state *mrb, kh_##name##_t *h) \
+ { \
+ if (h) { \
+ mrb_free(mrb, h->keys); \
+ mrb_free(mrb, h); \
+ } \
+ } \
+ void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h) \
+ { \
+ (void)mrb; \
+ if (h && h->ed_flags) { \
+ kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \
+ h->size = h->n_occupied = 0; \
+ } \
+ } \
+ khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \
+ { \
+ khint_t k = __hash_func(mrb,key) & khash_mask(h), step = 0; \
+ (void)mrb; \
+ while (!__ac_isempty(h->ed_flags, k)) { \
+ if (!__ac_isdel(h->ed_flags, k)) { \
+ if (__hash_equal(mrb,h->keys[k], key)) return k; \
+ } \
+ k = (k+(++step)) & khash_mask(h); \
+ } \
+ return kh_end(h); \
+ } \
+ void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets) \
+ { \
+ if (new_n_buckets < KHASH_MIN_SIZE) \
+ new_n_buckets = KHASH_MIN_SIZE; \
+ khash_power2(new_n_buckets); \
+ { \
+ kh_##name##_t hh; \
+ uint8_t *old_ed_flags = h->ed_flags; \
+ khkey_t *old_keys = h->keys; \
+ khval_t *old_vals = h->vals; \
+ khint_t old_n_buckets = h->n_buckets; \
+ khint_t i; \
+ hh.n_buckets = new_n_buckets; \
+ kh_alloc_##name(mrb, &hh); \
+ /* relocate */ \
+ for (i=0 ; i<old_n_buckets ; i++) { \
+ if (!__ac_iseither(old_ed_flags, i)) { \
+ khint_t k = kh_put_##name(mrb, &hh, old_keys[i], NULL); \
+ if (kh_is_map) kh_value(&hh,k) = old_vals[i]; \
+ } \
+ } \
+ /* copy hh to h */ \
+ *h = hh; \
+ mrb_free(mrb, old_keys); \
+ } \
+ } \
+ khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
+ { \
+ khint_t k, del_k, step = 0; \
+ if (h->n_occupied >= khash_upper_bound(h)) { \
+ kh_resize_##name(mrb, h, h->n_buckets*2); \
+ } \
+ k = __hash_func(mrb,key) & khash_mask(h); \
+ del_k = kh_end(h); \
+ while (!__ac_isempty(h->ed_flags, k)) { \
+ if (!__ac_isdel(h->ed_flags, k)) { \
+ if (__hash_equal(mrb,h->keys[k], key)) { \
+ if (ret) *ret = 0; \
+ return k; \
+ } \
+ } \
+ else if (del_k == kh_end(h)) { \
+ del_k = k; \
+ } \
+ k = (k+(++step)) & khash_mask(h); \
+ } \
+ if (del_k != kh_end(h)) { \
+ /* put at del */ \
+ h->keys[del_k] = key; \
+ h->ed_flags[del_k/4] &= ~__m_del[del_k%4]; \
+ h->size++; \
+ if (ret) *ret = 2; \
+ return del_k; \
+ } \
+ else { \
+ /* put at empty */ \
+ h->keys[k] = key; \
+ h->ed_flags[k/4] &= ~__m_empty[k%4]; \
+ h->size++; \
+ h->n_occupied++; \
+ if (ret) *ret = 1; \
+ return k; \
+ } \
+ } \
+ void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x) \
+ { \
+ (void)mrb; \
+ mrb_assert(x != h->n_buckets && !__ac_iseither(h->ed_flags, x)); \
+ h->ed_flags[x/4] |= __m_del[x%4]; \
+ h->size--; \
+ } \
+ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \
+ { \
+ kh_##name##_t *h2; \
+ khiter_t k, k2; \
+ \
+ h2 = kh_init_##name(mrb); \
+ for (k = kh_begin(h); k != kh_end(h); k++) { \
+ if (kh_exist(h, k)) { \
+ k2 = kh_put_##name(mrb, h2, kh_key(h, k), NULL); \
+ if (kh_is_map) kh_value(h2, k2) = kh_value(h, k); \
+ } \
+ } \
+ return h2; \
+ }
+
+
+#define khash_t(name) kh_##name##_t
+
+#define kh_init_size(name,mrb,size) kh_init_##name##_size(mrb,size)
+#define kh_init(name,mrb) kh_init_##name(mrb)
+#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
+#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
+#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
+#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
+#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
+#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
+#define kh_del(name, mrb, h, k) kh_del_##name(mrb, h, k)
+#define kh_copy(name, mrb, h) kh_copy_##name(mrb, h)
+
+#define kh_exist(h, x) (!__ac_iseither((h)->ed_flags, (x)))
+#define kh_key(h, x) ((h)->keys[x])
+#define kh_val(h, x) ((h)->vals[x])
+#define kh_value(h, x) ((h)->vals[x])
+#define kh_begin(h) (khint_t)(0)
+#define kh_end(h) ((h)->n_buckets)
+#define kh_size(h) ((h)->size)
+#define kh_n_buckets(h) ((h)->n_buckets)
+
+#define kh_int_hash_func(mrb,key) (khint_t)((key)^((key)<<2)^((key)>>2))
+#define kh_int_hash_equal(mrb,a, b) (a == b)
+#define kh_int64_hash_func(mrb,key) (khint_t)((key)>>33^(key)^(key)<<11)
+#define kh_int64_hash_equal(mrb,a, b) (a == b)
+static inline khint_t __ac_X31_hash_string(const char *s)
+{
+ khint_t h = *s;
+ if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;
+ return h;
+}
+#define kh_str_hash_func(mrb,key) __ac_X31_hash_string(key)
+#define kh_str_hash_equal(mrb,a, b) (strcmp(a, b) == 0)
+
+typedef const char *kh_cstr_t;
+
+MRB_END_DECL
+
+#endif /* MRUBY_KHASH_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/numeric.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/numeric.h
new file mode 100644
index 00000000..40c8c4a2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/numeric.h
@@ -0,0 +1,155 @@
+/*
+** mruby/numeric.h - Numeric, Integer, Float, Fixnum class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_NUMERIC_H
+#define MRUBY_NUMERIC_H
+
+#include "common.h"
+
+/**
+ * Numeric class and it's sub-classes.
+ *
+ * Integer, Float and Fixnum
+ */
+MRB_BEGIN_DECL
+
+#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX)
+#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN)
+#define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t))
+#define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int)
+#define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
+#define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
+#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,double)
+
+MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
+MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
+/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
+MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
+MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
+
+mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
+mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
+mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y);
+mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
+
+#ifndef __has_builtin
+ #define __has_builtin(x) 0
+#endif
+
+#if (defined(__GNUC__) && __GNUC__ >= 5) || \
+ (__has_builtin(__builtin_add_overflow) && \
+ __has_builtin(__builtin_sub_overflow) && \
+ __has_builtin(__builtin_mul_overflow))
+# define MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
+#endif
+
+/*
+// Clang 3.8 and 3.9 have problem compiling mruby in 32-bit mode, when MRB_INT64 is set
+// because of missing __mulodi4 and similar functions in its runtime. We need to use custom
+// implementation for them.
+*/
+#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
+#if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ >= 8) && \
+ defined(MRB_32BIT) && defined(MRB_INT64)
+#undef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
+#endif
+#endif
+
+#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
+
+#ifndef MRB_WORD_BOXING
+# define WBCHK(x) 0
+#else
+# define WBCHK(x) !FIXABLE(x)
+#endif
+
+static inline mrb_bool
+mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
+{
+ return __builtin_add_overflow(augend, addend, sum) || WBCHK(*sum);
+}
+
+static inline mrb_bool
+mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
+{
+ return __builtin_sub_overflow(minuend, subtrahend, difference) || WBCHK(*difference);
+}
+
+static inline mrb_bool
+mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
+{
+ return __builtin_mul_overflow(multiplier, multiplicand, product) || WBCHK(*product);
+}
+
+#undef WBCHK
+
+#else
+
+#define MRB_UINT_MAKE2(n) uint ## n ## _t
+#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n)
+#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT)
+
+#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT))
+
+static inline mrb_bool
+mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum)
+{
+ mrb_uint x = (mrb_uint)augend;
+ mrb_uint y = (mrb_uint)addend;
+ mrb_uint z = (mrb_uint)(x + y);
+ *sum = (mrb_int)z;
+ return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK);
+}
+
+static inline mrb_bool
+mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference)
+{
+ mrb_uint x = (mrb_uint)minuend;
+ mrb_uint y = (mrb_uint)subtrahend;
+ mrb_uint z = (mrb_uint)(x - y);
+ *difference = (mrb_int)z;
+ return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK);
+}
+
+static inline mrb_bool
+mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product)
+{
+#if MRB_INT_BIT == 32
+ int64_t n = (int64_t)multiplier * multiplicand;
+ *product = (mrb_int)n;
+ return !FIXABLE(n);
+#else
+ if (multiplier > 0) {
+ if (multiplicand > 0) {
+ if (multiplier > MRB_INT_MAX / multiplicand) return TRUE;
+ }
+ else {
+ if (multiplicand < MRB_INT_MAX / multiplier) return TRUE;
+ }
+ }
+ else {
+ if (multiplicand > 0) {
+ if (multiplier < MRB_INT_MAX / multiplicand) return TRUE;
+ }
+ else {
+ if (multiplier != 0 && multiplicand < MRB_INT_MAX / multiplier) return TRUE;
+ }
+ }
+ *product = multiplier * multiplicand;
+ return FALSE;
+#endif
+}
+
+#undef MRB_INT_OVERFLOW_MASK
+#undef mrb_uint
+#undef MRB_UINT_MAKE
+#undef MRB_UINT_MAKE2
+
+#endif
+
+MRB_END_DECL
+
+#endif /* MRUBY_NUMERIC_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/object.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/object.h
new file mode 100644
index 00000000..9347981d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/object.h
@@ -0,0 +1,43 @@
+/*
+** mruby/object.h - mruby object definition
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_OBJECT_H
+#define MRUBY_OBJECT_H
+
+#define MRB_OBJECT_HEADER \
+ enum mrb_vtype tt:8;\
+ uint32_t color:3;\
+ uint32_t flags:21;\
+ struct RClass *c;\
+ struct RBasic *gcnext
+
+#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & flag)
+
+
+struct RBasic {
+ MRB_OBJECT_HEADER;
+};
+#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
+
+#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN)
+#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN)
+#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN)
+
+struct RObject {
+ MRB_OBJECT_HEADER;
+ struct iv_tbl *iv;
+};
+#define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v)))
+
+#define mrb_immediate_p(x) (mrb_type(x) < MRB_TT_HAS_BASIC)
+#define mrb_special_const_p(x) mrb_immediate_p(x)
+
+struct RFiber {
+ MRB_OBJECT_HEADER;
+ struct mrb_context *cxt;
+};
+
+#endif /* MRUBY_OBJECT_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/opcode.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/opcode.h
new file mode 100644
index 00000000..9a511627
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/opcode.h
@@ -0,0 +1,161 @@
+/*
+** mruby/opcode.h - RiteVM operation codes
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_OPCODE_H
+#define MRUBY_OPCODE_H
+
+#define MAXARG_Bx (0xffff)
+#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
+
+/* instructions: packed 32 bit */
+/* ------------------------------- */
+/* A:B:C:OP = 9: 9: 7: 7 */
+/* A:Bx:OP = 9:16: 7 */
+/* Ax:OP = 25: 7 */
+/* A:Bz:Cz:OP = 9:14: 2: 7 */
+
+#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
+#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
+#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff))
+#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
+#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
+#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
+#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
+#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
+#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
+#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
+#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
+
+#define MKOPCODE(op) ((op) & 0x7f)
+#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
+#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
+#define MKARG_C(c) (((c) & 0x7f) << 7)
+#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
+#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
+#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
+#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
+#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
+
+#define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a))
+#define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b))
+#define MKOP_ABC(op,a,b,c) (MKOP_AB(op,a,b)|MKARG_C(c))
+#define MKOP_ABx(op,a,bx) (MKOP_A(op,a)|MKARG_Bx(bx))
+#define MKOP_Bx(op,bx) (MKOPCODE(op)|MKARG_Bx(bx))
+#define MKOP_sBx(op,sbx) (MKOPCODE(op)|MKARG_sBx(sbx))
+#define MKOP_AsBx(op,a,sbx) (MKOP_A(op,a)|MKARG_sBx(sbx))
+#define MKOP_Ax(op,ax) (MKOPCODE(op)|MKARG_Ax(ax))
+#define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c))
+
+enum {
+ /*-----------------------------------------------------------------------
+ operation code operand description
+ ------------------------------------------------------------------------*/
+ OP_NOP=0,/* */
+ OP_MOVE,/* A B R(A) := R(B) */
+ OP_LOADL,/* A Bx R(A) := Pool(Bx) */
+ OP_LOADI,/* A sBx R(A) := sBx */
+ OP_LOADSYM,/* A Bx R(A) := Syms(Bx) */
+ OP_LOADNIL,/* A R(A) := nil */
+ OP_LOADSELF,/* A R(A) := self */
+ OP_LOADT,/* A R(A) := true */
+ OP_LOADF,/* A R(A) := false */
+
+ OP_GETGLOBAL,/* A Bx R(A) := getglobal(Syms(Bx)) */
+ OP_SETGLOBAL,/* A Bx setglobal(Syms(Bx), R(A)) */
+ OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */
+ OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */
+ OP_GETIV,/* A Bx R(A) := ivget(Syms(Bx)) */
+ OP_SETIV,/* A Bx ivset(Syms(Bx),R(A)) */
+ OP_GETCV,/* A Bx R(A) := cvget(Syms(Bx)) */
+ OP_SETCV,/* A Bx cvset(Syms(Bx),R(A)) */
+ OP_GETCONST,/* A Bx R(A) := constget(Syms(Bx)) */
+ OP_SETCONST,/* A Bx constset(Syms(Bx),R(A)) */
+ OP_GETMCNST,/* A Bx R(A) := R(A)::Syms(Bx) */
+ OP_SETMCNST,/* A Bx R(A+1)::Syms(Bx) := R(A) */
+ OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */
+ OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */
+
+ OP_JMP,/* sBx pc+=sBx */
+ OP_JMPIF,/* A sBx if R(A) pc+=sBx */
+ OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */
+ OP_ONERR,/* sBx rescue_push(pc+sBx) */
+ OP_RESCUE,/* A B C if A (if C exc=R(A) else R(A) := exc);
+ if B R(B) := exc.isa?(R(B)); clear(exc) */
+ OP_POPERR,/* A A.times{rescue_pop()} */
+ OP_RAISE,/* A raise(R(A)) */
+ OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */
+ OP_EPOP,/* A A.times{ensure_pop().call} */
+
+ OP_SEND,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
+ OP_SENDB,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
+ OP_FSEND,/* A B C R(A) := fcall(R(A),Syms(B),R(A+1),...,R(A+C-1)) */
+ OP_CALL,/* A R(A) := self.call(frame.argc, frame.argv) */
+ OP_SUPER,/* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
+ OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */
+ OP_ENTER,/* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
+ OP_KARG,/* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
+ OP_KDICT,/* A C R(A) := kdict */
+
+ OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */
+ OP_TAILCALL,/* A B C return call(R(A),Syms(B),*R(C)) */
+ OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */
+
+ OP_ADD,/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1) */
+ OP_ADDI,/* A B C R(A) := R(A)+C (Syms[B]=:+) */
+ OP_SUB,/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1) */
+ OP_SUBI,/* A B C R(A) := R(A)-C (Syms[B]=:-) */
+ OP_MUL,/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1) */
+ OP_DIV,/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1) */
+ OP_EQ,/* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1) */
+ OP_LT,/* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1) */
+ OP_LE,/* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1) */
+ OP_GT,/* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1) */
+ OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */
+
+ OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
+ OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */
+ OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */
+ OP_AREF,/* A B C R(A) := R(B)[C] */
+ OP_ASET,/* A B C R(B)[C] := R(A) */
+ OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A) */
+
+ OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */
+ OP_STRCAT,/* A B str_cat(R(A),R(B)) */
+
+ OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
+ OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */
+ OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */
+
+ OP_OCLASS,/* A R(A) := ::Object */
+ OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
+ OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */
+ OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
+ OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */
+ OP_SCLASS,/* A B R(A) := R(B).singleton_class */
+ OP_TCLASS,/* A R(A) := target_class */
+
+ OP_DEBUG,/* A B C print R(A),R(B),R(C) */
+ OP_STOP,/* stop VM */
+ OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */
+
+ OP_RSVD1,/* reserved instruction #1 */
+ OP_RSVD2,/* reserved instruction #2 */
+ OP_RSVD3,/* reserved instruction #3 */
+ OP_RSVD4,/* reserved instruction #4 */
+ OP_RSVD5,/* reserved instruction #5 */
+};
+
+#define OP_L_STRICT 1
+#define OP_L_CAPTURE 2
+#define OP_L_METHOD OP_L_STRICT
+#define OP_L_LAMBDA (OP_L_STRICT|OP_L_CAPTURE)
+#define OP_L_BLOCK OP_L_CAPTURE
+
+#define OP_R_NORMAL 0
+#define OP_R_BREAK 1
+#define OP_R_RETURN 2
+
+#endif /* MRUBY_OPCODE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/proc.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/proc.h
new file mode 100644
index 00000000..9c266628
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/proc.h
@@ -0,0 +1,83 @@
+/*
+** mruby/proc.h - Proc class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_PROC_H
+#define MRUBY_PROC_H
+
+#include "common.h"
+#include <mruby/irep.h>
+
+/**
+ * Proc class
+ */
+MRB_BEGIN_DECL
+
+struct REnv {
+ MRB_OBJECT_HEADER;
+ mrb_value *stack;
+ ptrdiff_t cioff;
+ union {
+ mrb_sym mid;
+ struct mrb_context *c;
+ } cxt;
+};
+
+#define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len)
+#define MRB_ENV_STACK_LEN(e) ((mrb_int)(e)->flags)
+#define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1)
+#define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0)
+
+MRB_API void mrb_env_unshare(mrb_state*, struct REnv*);
+
+struct RProc {
+ MRB_OBJECT_HEADER;
+ union {
+ mrb_irep *irep;
+ mrb_func_t func;
+ } body;
+ struct RClass *target_class;
+ struct REnv *env;
+};
+
+/* aspec access */
+#define MRB_ASPEC_REQ(a) (((a) >> 18) & 0x1f)
+#define MRB_ASPEC_OPT(a) (((a) >> 13) & 0x1f)
+#define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1)
+#define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f)
+#define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f)
+#define MRB_ASPEC_KDICT(a) ((a) & (1<<1))
+#define MRB_ASPEC_BLOCK(a) ((a) & 1)
+
+#define MRB_PROC_CFUNC 128
+#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC) != 0)
+#define MRB_PROC_STRICT 256
+#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
+#define MRB_PROC_ORPHAN 512
+#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
+
+#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
+
+struct RProc *mrb_proc_new(mrb_state*, mrb_irep*);
+struct RProc *mrb_closure_new(mrb_state*, mrb_irep*);
+MRB_API struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t);
+MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals);
+void mrb_proc_copy(struct RProc *a, struct RProc *b);
+
+/* implementation of #send method */
+MRB_API mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
+
+/* following functions are defined in mruby-proc-ext so please include it when using */
+MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*);
+MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
+/* old name */
+#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
+
+#include <mruby/khash.h>
+KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE)
+
+MRB_END_DECL
+
+#endif /* MRUBY_PROC_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/range.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/range.h
new file mode 100644
index 00000000..b166e586
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/range.h
@@ -0,0 +1,49 @@
+/*
+** mruby/range.h - Range class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_RANGE_H
+#define MRUBY_RANGE_H
+
+#include "common.h"
+
+/**
+ * Range class
+ */
+MRB_BEGIN_DECL
+
+typedef struct mrb_range_edges {
+ mrb_value beg;
+ mrb_value end;
+} mrb_range_edges;
+
+struct RRange {
+ MRB_OBJECT_HEADER;
+ mrb_range_edges *edges;
+ mrb_bool excl : 1;
+};
+
+MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v);
+#define mrb_range_raw_ptr(v) ((struct RRange*)mrb_ptr(v))
+#define mrb_range_value(p) mrb_obj_value((void*)(p))
+
+/*
+ * Initializes a Range.
+ *
+ * If the third parameter is FALSE then it includes the last value in the range.
+ * If the third parameter is TRUE then it excludes the last value in the range.
+ *
+ * @param start the beginning value.
+ * @param end the ending value.
+ * @param exclude represents the inclusion or exclusion of the last value.
+ */
+MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude);
+
+MRB_API mrb_int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc);
+mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int));
+
+MRB_END_DECL
+
+#endif /* MRUBY_RANGE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/re.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/re.h
new file mode 100644
index 00000000..1d09d06c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/re.h
@@ -0,0 +1,16 @@
+/*
+** mruby/re.h - Regexp class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_RE_H
+#define MRUBY_RE_H
+
+MRB_BEGIN_DECL
+
+#define REGEXP_CLASS "Regexp"
+
+MRB_END_DECL
+
+#endif /* RE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/string.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/string.h
new file mode 100644
index 00000000..df6fb25c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/string.h
@@ -0,0 +1,430 @@
+/*
+** mruby/string.h - String class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_STRING_H
+#define MRUBY_STRING_H
+
+#include "common.h"
+
+/**
+ * String class
+ */
+MRB_BEGIN_DECL
+
+extern const char mrb_digitmap[];
+
+#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1))
+
+struct RString {
+ MRB_OBJECT_HEADER;
+ union {
+ struct {
+ mrb_int len;
+ union {
+ mrb_int capa;
+ struct mrb_shared_string *shared;
+ } aux;
+ char *ptr;
+ } heap;
+ char ary[RSTRING_EMBED_LEN_MAX + 1];
+ } as;
+};
+
+#define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED)
+#define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED)
+#define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK))
+#define RSTR_SET_EMBED_LEN(s, n) do {\
+ size_t tmp_n = (n);\
+ s->flags &= ~MRB_STR_EMBED_LEN_MASK;\
+ s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\
+} while (0)
+#define RSTR_SET_LEN(s, n) do {\
+ if (RSTR_EMBED_P(s)) {\
+ RSTR_SET_EMBED_LEN((s),(n));\
+ }\
+ else {\
+ s->as.heap.len = (mrb_int)(n);\
+ }\
+} while (0)
+#define RSTR_EMBED_LEN(s)\
+ (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT)
+#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr)
+#define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len)
+#define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa)
+
+#define RSTR_SHARED_P(s) ((s)->flags & MRB_STR_SHARED)
+#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
+#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
+
+#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)
+#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
+#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
+
+/*
+ * Returns a pointer from a Ruby string
+ */
+#define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s)))
+#define RSTRING(s) mrb_str_ptr(s)
+#define RSTRING_PTR(s) RSTR_PTR(RSTRING(s))
+#define RSTRING_EMBED_LEN(s) RSTR_EMBED_LEN(RSTRING(s))
+#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s))
+#define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s))
+#define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s))
+MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
+
+#define MRB_STR_SHARED 1
+#define MRB_STR_NOFREE 2
+#define MRB_STR_NO_UTF 8
+#define MRB_STR_EMBED 16
+#define MRB_STR_EMBED_LEN_MASK 0x3e0
+#define MRB_STR_EMBED_LEN_SHIFT 5
+
+void mrb_gc_free_str(mrb_state*, struct RString*);
+MRB_API void mrb_str_modify(mrb_state*, struct RString*);
+
+/*
+ * Finds the index of a substring in a string
+ */
+MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
+#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
+
+/*
+ * Appends self to other. Returns self as a concatnated string.
+ *
+ *
+ * Example:
+ *
+ * !!!c
+ * int
+ * main(int argc,
+ * char **argv)
+ * {
+ * // Variable declarations.
+ * mrb_value str1;
+ * mrb_value str2;
+ *
+ * mrb_state *mrb = mrb_open();
+ * if (!mrb)
+ * {
+ * // handle error
+ * }
+ *
+ * // Creates new Ruby strings.
+ * str1 = mrb_str_new_lit(mrb, "abc");
+ * str2 = mrb_str_new_lit(mrb, "def");
+ *
+ * // Concatnates str2 to str1.
+ * mrb_str_concat(mrb, str1, str2);
+ *
+ * // Prints new Concatnated Ruby string.
+ * mrb_p(mrb, str1);
+ *
+ * mrb_close(mrb);
+ * return 0;
+ * }
+ *
+ *
+ * Result:
+ *
+ * => "abcdef"
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] self String to concatenate.
+ * @param [mrb_value] other String to append to self.
+ * @return [mrb_value] Returns a new String appending other to self.
+ */
+MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
+
+/*
+ * Adds two strings together.
+ *
+ *
+ * Example:
+ *
+ * !!!c
+ * int
+ * main(int argc,
+ * char **argv)
+ * {
+ * // Variable declarations.
+ * mrb_value a;
+ * mrb_value b;
+ * mrb_value c;
+ *
+ * mrb_state *mrb = mrb_open();
+ * if (!mrb)
+ * {
+ * // handle error
+ * }
+ *
+ * // Creates two Ruby strings from the passed in C strings.
+ * a = mrb_str_new_lit(mrb, "abc");
+ * b = mrb_str_new_lit(mrb, "def");
+ *
+ * // Prints both C strings.
+ * mrb_p(mrb, a);
+ * mrb_p(mrb, b);
+ *
+ * // Concatnates both Ruby strings.
+ * c = mrb_str_plus(mrb, a, b);
+ *
+ * // Prints new Concatnated Ruby string.
+ * mrb_p(mrb, c);
+ *
+ * mrb_close(mrb);
+ * return 0;
+ * }
+ *
+ *
+ * Result:
+ *
+ * => "abc" # First string
+ * => "def" # Second string
+ * => "abcdef" # First & Second concatnated.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] a First string to concatenate.
+ * @param [mrb_value] b Second string to concatenate.
+ * @return [mrb_value] Returns a new String containing a concatenated to b.
+ */
+MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
+
+/*
+ * Converts pointer into a Ruby string.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [void*] p The pointer to convert to Ruby string.
+ * @return [mrb_value] Returns a new Ruby String.
+ */
+MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*);
+
+/*
+ * Returns an object as a Ruby string.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] obj An object to return as a Ruby string.
+ * @return [mrb_value] An object as a Ruby string.
+ */
+MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
+
+/*
+ * Resizes the string's length. Returns the amount of characters
+ * in the specified by len.
+ *
+ * Example:
+ *
+ * !!!c
+ * int
+ * main(int argc,
+ * char **argv)
+ * {
+ * // Variable declaration.
+ * mrb_value str;
+ *
+ * mrb_state *mrb = mrb_open();
+ * if (!mrb)
+ * {
+ * // handle error
+ * }
+ * // Creates a new string.
+ * str = mrb_str_new_lit(mrb, "Hello, world!");
+ * // Returns 5 characters of
+ * mrb_str_resize(mrb, str, 5);
+ * mrb_p(mrb, str);
+ *
+ * mrb_close(mrb);
+ * return 0;
+ * }
+ *
+ * Result:
+ *
+ * => "Hello"
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str The Ruby string to resize.
+ * @param [mrb_value] len The length.
+ * @return [mrb_value] An object as a Ruby string.
+ */
+MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
+
+/*
+ * Returns a sub string.
+ *
+ * Example:
+ *
+ * !!!c
+ * int
+ * main(int argc,
+ * char const **argv)
+ * {
+ * // Variable declarations.
+ * mrb_value str1;
+ * mrb_value str2;
+ *
+ * mrb_state *mrb = mrb_open();
+ * if (!mrb)
+ * {
+ * // handle error
+ * }
+ * // Creates new string.
+ * str1 = mrb_str_new_lit(mrb, "Hello, world!");
+ * // Returns a sub-string within the range of 0..2
+ * str2 = mrb_str_substr(mrb, str1, 0, 2);
+ *
+ * // Prints sub-string.
+ * mrb_p(mrb, str2);
+ *
+ * mrb_close(mrb);
+ * return 0;
+ * }
+ *
+ * Result:
+ *
+ * => "He"
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string.
+ * @param [mrb_int] beg The beginning point of the sub-string.
+ * @param [mrb_int] len The end point of the sub-string.
+ * @return [mrb_value] An object as a Ruby sub-string.
+ */
+MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
+
+/*
+ * Returns a Ruby string type.
+ *
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string.
+ * @return [mrb_value] A Ruby string.
+ */
+MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
+
+MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
+MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
+MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
+
+MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
+MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str);
+/*
+ * Returns the length of the Ruby string.
+ *
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string.
+ * @return [mrb_int] The length of the passed in Ruby string.
+ */
+MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str);
+
+/*
+ * Duplicates a string object.
+ *
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string.
+ * @return [mrb_value] Duplicated Ruby string.
+ */
+MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str);
+
+/*
+ * Returns a symbol from a passed in Ruby string.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] self Ruby string.
+ * @return [mrb_value] A symbol.
+ */
+MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self);
+
+MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck);
+MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck);
+
+/*
+ * Returns a converted string type.
+ */
+MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
+
+/*
+ * Returns true if the strings match and false if the strings don't match.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str1 Ruby string to compare.
+ * @param [mrb_value] str2 Ruby string to compare.
+ * @return [mrb_value] boolean value.
+ */
+MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
+
+/*
+ * Returns a concated string comprised of a Ruby string and a C string.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string.
+ * @param [const char *] ptr A C string.
+ * @param [size_t] len length of C string.
+ * @return [mrb_value] A Ruby string.
+ * @see mrb_str_cat_cstr
+ */
+MRB_API mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
+
+/*
+ * Returns a concated string comprised of a Ruby string and a C string.
+ *
+ * @param [mrb_state] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string.
+ * @param [const char *] ptr A C string.
+ * @return [mrb_value] A Ruby string.
+ * @see mrb_str_cat
+ */
+MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr);
+MRB_API mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2);
+#define mrb_str_cat_lit(mrb, str, lit) mrb_str_cat(mrb, str, lit, mrb_strlen_lit(lit))
+
+/*
+ * Adds str2 to the end of str1.
+ */
+MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2);
+
+/*
+ * Returns 0 if both Ruby strings are equal. Returns a value < 0 if Ruby str1 is less than Ruby str2. Returns a value > 0 if Ruby str2 is greater than Ruby str1.
+ */
+MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
+
+/*
+ * Returns a newly allocated C string from a Ruby string.
+ * This is an utility function to pass a Ruby string to C library functions.
+ *
+ * - Returned string does not contain any NUL characters (but terminator).
+ * - It raises an ArgumentError exception if Ruby string contains
+ * NUL characters.
+ * - Retured string will be freed automatically on next GC.
+ * - Caller can modify returned string without affecting Ruby string
+ * (e.g. it can be used for mkstemp(3)).
+ *
+ * @param [mrb_state *] mrb The current mruby state.
+ * @param [mrb_value] str Ruby string. Must be an instance of String.
+ * @return [char *] A newly allocated C string.
+ */
+MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
+
+mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
+mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str);
+mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
+
+/*
+ * Returns a printable version of str, surrounded by quote marks, with special characters escaped.
+ */
+mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
+
+void mrb_noregexp(mrb_state *mrb, mrb_value self);
+void mrb_regexp_check(mrb_state *mrb, mrb_value obj);
+
+/* For backward compatibility */
+#define mrb_str_cat2(mrb, str, ptr) mrb_str_cat_cstr(mrb, str, ptr)
+#define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len)
+#define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2)
+
+MRB_END_DECL
+
+#endif /* MRUBY_STRING_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/throw.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/throw.h
new file mode 100644
index 00000000..5d3d214e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/throw.h
@@ -0,0 +1,55 @@
+/*
+** mruby/throw.h - mruby exception throwing handler
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRB_THROW_H
+#define MRB_THROW_H
+
+#if defined(MRB_ENABLE_CXX_ABI)
+# if !defined(__cplusplus)
+# error Trying to use C++ exception handling in C code
+# endif
+#endif
+
+#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
+
+#define MRB_TRY(buf) do { try {
+#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; }
+#define MRB_END_EXC(buf) } } while(0)
+
+#define MRB_THROW(buf) throw((buf)->impl)
+typedef mrb_int mrb_jmpbuf_impl;
+
+#else
+
+#include <setjmp.h>
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#define MRB_SETJMP _setjmp
+#define MRB_LONGJMP _longjmp
+#else
+#define MRB_SETJMP setjmp
+#define MRB_LONGJMP longjmp
+#endif
+
+#define MRB_TRY(buf) do { if (MRB_SETJMP((buf)->impl) == 0) {
+#define MRB_CATCH(buf) } else {
+#define MRB_END_EXC(buf) } } while(0)
+
+#define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1);
+#define mrb_jmpbuf_impl jmp_buf
+
+#endif
+
+struct mrb_jmpbuf {
+ mrb_jmpbuf_impl impl;
+
+#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
+ static mrb_int jmpbuf_id;
+ mrb_jmpbuf() : impl(jmpbuf_id++) {}
+#endif
+};
+
+#endif /* MRB_THROW_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/value.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/value.h
new file mode 100644
index 00000000..98c68d65
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/value.h
@@ -0,0 +1,303 @@
+/*
+** mruby/value.h - mruby value definitions
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_VALUE_H
+#define MRUBY_VALUE_H
+
+#include "common.h"
+
+/**
+ * MRuby Value definition functions and macros.
+ */
+MRB_BEGIN_DECL
+
+typedef uint32_t mrb_sym;
+typedef uint8_t mrb_bool;
+struct mrb_state;
+
+#if defined(MRB_INT16) && defined(MRB_INT64)
+# error "You can't define MRB_INT16 and MRB_INT64 at the same time."
+#endif
+
+#if defined _MSC_VER && _MSC_VER < 1800
+# define PRIo64 "llo"
+# define PRId64 "lld"
+# define PRIx64 "llx"
+# define PRIo16 "ho"
+# define PRId16 "hd"
+# define PRIx16 "hx"
+# define PRIo32 "o"
+# define PRId32 "d"
+# define PRIx32 "x"
+#else
+# include <inttypes.h>
+#endif
+
+#if defined(MRB_INT64)
+ typedef int64_t mrb_int;
+# define MRB_INT_BIT 64
+# define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT)
+# define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT)
+# define MRB_PRIo PRIo64
+# define MRB_PRId PRId64
+# define MRB_PRIx PRIx64
+#elif defined(MRB_INT16)
+ typedef int16_t mrb_int;
+# define MRB_INT_BIT 16
+# define MRB_INT_MIN (INT16_MIN>>MRB_FIXNUM_SHIFT)
+# define MRB_INT_MAX (INT16_MAX>>MRB_FIXNUM_SHIFT)
+# define MRB_PRIo PRIo16
+# define MRB_PRId PRId16
+# define MRB_PRIx PRIx16
+#else
+ typedef int32_t mrb_int;
+# define MRB_INT_BIT 32
+# define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT)
+# define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT)
+# define MRB_PRIo PRIo32
+# define MRB_PRId PRId32
+# define MRB_PRIx PRIx32
+#endif
+
+
+MRB_API double mrb_float_read(const char*, char**);
+#ifdef MRB_USE_FLOAT
+ typedef float mrb_float;
+#else
+ typedef double mrb_float;
+#endif
+
+#if defined _MSC_VER && _MSC_VER < 1900
+# ifndef __cplusplus
+# define inline __inline
+# endif
+# include <stdarg.h>
+MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg);
+MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
+# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg)
+# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__)
+# if _MSC_VER < 1800
+# include <float.h>
+# define isfinite(n) _finite(n)
+# define isnan _isnan
+# define isinf(n) (!_finite(n) && !_isnan(n))
+# define signbit(n) (_copysign(1.0, (n)) < 0.0)
+static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
+# define INFINITY (*(float *)&IEEE754_INFINITY_BITS_SINGLE)
+# define NAN ((float)(INFINITY - INFINITY))
+# endif
+#endif
+
+enum mrb_vtype {
+ MRB_TT_FALSE = 0, /* 0 */
+ MRB_TT_FREE, /* 1 */
+ MRB_TT_TRUE, /* 2 */
+ MRB_TT_FIXNUM, /* 3 */
+ MRB_TT_SYMBOL, /* 4 */
+ MRB_TT_UNDEF, /* 5 */
+ MRB_TT_FLOAT, /* 6 */
+ MRB_TT_CPTR, /* 7 */
+ MRB_TT_OBJECT, /* 8 */
+ MRB_TT_CLASS, /* 9 */
+ MRB_TT_MODULE, /* 10 */
+ MRB_TT_ICLASS, /* 11 */
+ MRB_TT_SCLASS, /* 12 */
+ MRB_TT_PROC, /* 13 */
+ MRB_TT_ARRAY, /* 14 */
+ MRB_TT_HASH, /* 15 */
+ MRB_TT_STRING, /* 16 */
+ MRB_TT_RANGE, /* 17 */
+ MRB_TT_EXCEPTION, /* 18 */
+ MRB_TT_FILE, /* 19 */
+ MRB_TT_ENV, /* 20 */
+ MRB_TT_DATA, /* 21 */
+ MRB_TT_FIBER, /* 22 */
+ MRB_TT_ISTRUCT, /* 23 */
+ MRB_TT_BREAK, /* 24 */
+ MRB_TT_MAXDEFINE /* 25 */
+};
+
+#include <mruby/object.h>
+
+#ifdef MRB_DOCUMENTATION_BLOCK
+
+/**
+ * @abstract
+ * MRuby value boxing.
+ *
+ * Actual implementation depends on configured boxing type.
+ *
+ * @see mruby/boxing_no.h Default boxing representation
+ * @see mruby/boxing_word.h Word representation
+ * @see mruby/boxing_nan.h Boxed double representation
+ */
+typedef void mrb_value;
+
+#endif
+
+#if defined(MRB_NAN_BOXING)
+#include "boxing_nan.h"
+#elif defined(MRB_WORD_BOXING)
+#include "boxing_word.h"
+#else
+#include "boxing_no.h"
+#endif
+
+#ifndef mrb_fixnum_p
+#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM)
+#endif
+#ifndef mrb_undef_p
+#define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF)
+#endif
+#ifndef mrb_nil_p
+#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !mrb_fixnum(o))
+#endif
+#ifndef mrb_bool
+#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
+#endif
+#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
+#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
+#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
+#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
+#define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH)
+#define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR)
+#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION)
+#define mrb_test(o) mrb_bool(o)
+MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value);
+
+/*
+ * Returns a float in Ruby.
+ */
+MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
+{
+ mrb_value v;
+ (void) mrb;
+ SET_FLOAT_VALUE(mrb, v, f);
+ return v;
+}
+
+static inline mrb_value
+mrb_cptr_value(struct mrb_state *mrb, void *p)
+{
+ mrb_value v;
+ (void) mrb;
+ SET_CPTR_VALUE(mrb,v,p);
+ return v;
+}
+
+/*
+ * Returns a fixnum in Ruby.
+ */
+MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i)
+{
+ mrb_value v;
+ SET_INT_VALUE(v, i);
+ return v;
+}
+
+static inline mrb_value
+mrb_symbol_value(mrb_sym i)
+{
+ mrb_value v;
+ SET_SYM_VALUE(v, i);
+ return v;
+}
+
+static inline mrb_value
+mrb_obj_value(void *p)
+{
+ mrb_value v;
+ SET_OBJ_VALUE(v, (struct RBasic*)p);
+ mrb_assert(p == mrb_ptr(v));
+ mrb_assert(((struct RBasic*)p)->tt == mrb_type(v));
+ return v;
+}
+
+
+/*
+ * Get a nil mrb_value object.
+ *
+ * @return
+ * nil mrb_value object reference.
+ */
+MRB_INLINE mrb_value mrb_nil_value(void)
+{
+ mrb_value v;
+ SET_NIL_VALUE(v);
+ return v;
+}
+
+/*
+ * Returns false in Ruby.
+ */
+MRB_INLINE mrb_value mrb_false_value(void)
+{
+ mrb_value v;
+ SET_FALSE_VALUE(v);
+ return v;
+}
+
+/*
+ * Returns true in Ruby.
+ */
+MRB_INLINE mrb_value mrb_true_value(void)
+{
+ mrb_value v;
+ SET_TRUE_VALUE(v);
+ return v;
+}
+
+static inline mrb_value
+mrb_bool_value(mrb_bool boolean)
+{
+ mrb_value v;
+ SET_BOOL_VALUE(v, boolean);
+ return v;
+}
+
+static inline mrb_value
+mrb_undef_value(void)
+{
+ mrb_value v;
+ SET_UNDEF_VALUE(v);
+ return v;
+}
+
+#ifdef MRB_USE_ETEXT_EDATA
+#if (defined(__APPLE__) && defined(__MACH__))
+#include <mach-o/getsect.h>
+static inline mrb_bool
+mrb_ro_data_p(const char *p)
+{
+ return (const char*)get_etext() < p && p < (const char*)get_edata();
+}
+#else
+extern char _etext[];
+#ifdef MRB_NO_INIT_ARRAY_START
+extern char _edata[];
+
+static inline mrb_bool
+mrb_ro_data_p(const char *p)
+{
+ return _etext < p && p < _edata;
+}
+#else
+extern char __init_array_start[];
+
+static inline mrb_bool
+mrb_ro_data_p(const char *p)
+{
+ return _etext < p && p < (char*)&__init_array_start;
+}
+#endif
+#endif
+#else
+# define mrb_ro_data_p(p) FALSE
+#endif
+
+MRB_END_DECL
+
+#endif /* MRUBY_VALUE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/variable.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/variable.h
new file mode 100644
index 00000000..5fef83fa
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/variable.h
@@ -0,0 +1,138 @@
+/*
+** mruby/variable.h - mruby variables
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_VARIABLE_H
+#define MRUBY_VARIABLE_H
+
+#include "common.h"
+
+/**
+ * Functions to access mruby variables.
+ */
+MRB_BEGIN_DECL
+
+typedef struct global_variable {
+ int counter;
+ mrb_value *data;
+ mrb_value (*getter)(void);
+ void (*setter)(void);
+ /* void (*marker)(); */
+ /* int block_trace; */
+ /* struct trace_var *trace; */
+} global_variable;
+
+struct global_entry {
+ global_variable *var;
+ mrb_sym id;
+};
+
+mrb_value mrb_vm_special_get(mrb_state*, mrb_sym);
+void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
+mrb_value mrb_vm_iv_get(mrb_state*, mrb_sym);
+void mrb_vm_iv_set(mrb_state*, mrb_sym, mrb_value);
+mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
+void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
+mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
+void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value);
+MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym);
+MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value);
+MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
+MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
+
+MRB_API mrb_bool mrb_iv_p(mrb_state *mrb, mrb_sym sym);
+MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym sym);
+MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
+MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
+MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
+MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
+MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
+MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
+MRB_API mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym);
+MRB_API void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src);
+MRB_API mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id);
+
+/**
+ * Get a global variable. Will return nil if the var does not exist
+ *
+ * Example:
+ *
+ * !!!ruby
+ * # Ruby style
+ * var = $value
+ *
+ * !!!c
+ * // C style
+ * mrb_sym sym = mrb_intern_lit(mrb, "$value");
+ * mrb_value var = mrb_gv_get(mrb, sym);
+ *
+ * @param mrb The mruby state reference
+ * @param sym The name of the global variable
+ * @return The value of that global variable. May be nil
+ */
+MRB_API mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym);
+
+/**
+ * Set a global variable
+ *
+ * Example:
+ *
+ * !!!ruby
+ * # Ruby style
+ * $value = "foo"
+ *
+ * !!!c
+ * // C style
+ * mrb_sym sym = mrb_intern_lit(mrb, "$value");
+ * mrb_gv_set(mrb, sym, mrb_str_new_lit("foo"));
+ *
+ * @param mrb The mruby state reference
+ * @param sym The name of the global variable
+ * @param val The value of the global variable
+ */
+MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
+
+/**
+ * Remove a global variable.
+ *
+ * Example:
+ *
+ * !!!ruby
+ * # Ruby style
+ * $value = nil
+ *
+ * !!!c
+ * // C style
+ * mrb_sym sym = mrb_intern_lit(mrb, "$value");
+ * mrb_gv_remove(mrb, sym);
+ *
+ * @param mrb The mruby state reference
+ * @param sym The name of the global variable
+ * @param val The value of the global variable
+ */
+MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym);
+
+MRB_API mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym);
+MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v);
+MRB_API void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v);
+MRB_API mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym);
+mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
+mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
+mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
+mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
+mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
+mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
+mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
+
+/* GC functions */
+void mrb_gc_mark_gv(mrb_state*);
+void mrb_gc_free_gv(mrb_state*);
+void mrb_gc_mark_iv(mrb_state*, struct RObject*);
+size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
+void mrb_gc_free_iv(mrb_state*, struct RObject*);
+
+MRB_END_DECL
+
+#endif /* MRUBY_VARIABLE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/include/mruby/version.h b/web/server/h2o/libh2o/deps/mruby/include/mruby/version.h
new file mode 100644
index 00000000..8414bf20
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/include/mruby/version.h
@@ -0,0 +1,110 @@
+/*
+** mruby/version.h - mruby version definition
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_VERSION_H
+#define MRUBY_VERSION_H
+
+#include "common.h"
+
+/**
+ * mruby version definition macros
+ */
+MRB_BEGIN_DECL
+
+/*
+ * A passed in expression.
+ */
+#define MRB_STRINGIZE0(expr) #expr
+
+/*
+ * Passes in an expression to MRB_STRINGIZE0.
+ */
+#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr)
+
+/*
+ * The version of Ruby used by mruby.
+ */
+#define MRUBY_RUBY_VERSION "1.9"
+
+/*
+ * Ruby engine.
+ */
+#define MRUBY_RUBY_ENGINE "mruby"
+
+/*
+ * Major release version number.
+ */
+#define MRUBY_RELEASE_MAJOR 1
+
+/*
+ * Minor release version number.
+ */
+#define MRUBY_RELEASE_MINOR 3
+
+/*
+ * Tiny release version number.
+ */
+#define MRUBY_RELEASE_TEENY 0
+
+/*
+ * The mruby version.
+ */
+#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY)
+
+/*
+ * Release number.
+ */
+#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
+
+/*
+ * Release year.
+ */
+#define MRUBY_RELEASE_YEAR 2017
+
+/*
+ * Release month.
+ */
+#define MRUBY_RELEASE_MONTH 7
+
+/*
+ * Release day.
+ */
+#define MRUBY_RELEASE_DAY 4
+
+/*
+ * Release date as a string.
+ */
+#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY)
+
+/*
+ * The year mruby was first created.
+ */
+#define MRUBY_BIRTH_YEAR 2010
+
+/*
+ * MRuby's authors.
+ */
+#define MRUBY_AUTHOR "mruby developers"
+
+/*
+ * mruby's version, and release date.
+ */
+#define MRUBY_DESCRIPTION \
+ "mruby " MRUBY_VERSION \
+ " (" MRUBY_RELEASE_DATE ") " \
+
+/*
+ * mruby's copyright information.
+ */
+#define MRUBY_COPYRIGHT \
+ "mruby - Copyright (c) " \
+ MRB_STRINGIZE(MRUBY_BIRTH_YEAR)"-" \
+ MRB_STRINGIZE(MRUBY_RELEASE_YEAR)" " \
+ MRUBY_AUTHOR \
+
+MRB_END_DECL
+
+#endif /* MRUBY_VERSION_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/lib/mruby-core-ext.rb b/web/server/h2o/libh2o/deps/mruby/lib/mruby-core-ext.rb
new file mode 100644
index 00000000..4c6d3ca7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/lib/mruby-core-ext.rb
@@ -0,0 +1,79 @@
+class Object
+ class << self
+ def attr_block(*syms)
+ syms.flatten.each do |sym|
+ class_eval "def #{sym}(&block);block.call(@#{sym}) if block_given?;@#{sym};end"
+ end
+ end
+ end
+end
+
+class String
+ def relative_path_from(dir)
+ Pathname.new(File.expand_path(self)).relative_path_from(Pathname.new(File.expand_path(dir))).to_s
+ end
+
+ def relative_path
+ relative_path_from(Dir.pwd)
+ end
+
+ # Compatible with 1.9 on 1.8
+ def %(params)
+ if params.is_a?(Hash)
+ str = self.clone
+ params.each do |k, v|
+ str.gsub!("%{#{k}}") { v }
+ end
+ str
+ else
+ if params.is_a?(Array)
+ sprintf(self, *params)
+ else
+ sprintf(self, params)
+ end
+ end
+ end
+end
+
+class Symbol
+ # Compatible with 1.9 on 1.8
+ def to_proc
+ proc { |obj, *args| obj.send(self, *args) }
+ end
+end
+
+module Enumerable
+ # Compatible with 1.9 on 1.8
+ def each_with_object(memo)
+ return to_enum :each_with_object, memo unless block_given?
+ each { |obj| yield obj, memo }
+ memo
+ end
+end
+
+$pp_show = true
+
+if $verbose.nil?
+ if Rake.respond_to?(:verbose) && !Rake.verbose.nil?
+ if Rake.verbose.class == TrueClass
+ # verbose message logging
+ $pp_show = false
+ else
+ $pp_show = true
+ Rake.verbose(false)
+ end
+ else
+ # could not identify rake version
+ $pp_show = false
+ end
+else
+ $pp_show = false if $verbose
+end
+
+def _pp(cmd, src, tgt=nil, options={})
+ return unless $pp_show
+
+ width = 5
+ template = options[:indent] ? "%#{width*options[:indent]}s %s %s" : "%-#{width}s %s %s"
+ puts template % [cmd, src, tgt ? "-> #{tgt}" : nil]
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/lib/mruby/build.rb b/web/server/h2o/libh2o/deps/mruby/lib/mruby/build.rb
new file mode 100644
index 00000000..7d6aa49e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/lib/mruby/build.rb
@@ -0,0 +1,355 @@
+require "mruby/build/load_gems"
+require "mruby/build/command"
+
+module MRuby
+ class << self
+ def targets
+ @targets ||= {}
+ end
+
+ def each_target(&block)
+ return to_enum(:each_target) if block.nil?
+ @targets.each do |key, target|
+ target.instance_eval(&block)
+ end
+ end
+ end
+
+ class Toolchain
+ class << self
+ attr_accessor :toolchains
+ end
+
+ def initialize(name, &block)
+ @name, @initializer = name.to_s, block
+ MRuby::Toolchain.toolchains ||= {}
+ MRuby::Toolchain.toolchains[@name] = self
+ end
+
+ def setup(conf,params={})
+ conf.instance_exec(conf, params, &@initializer)
+ end
+
+ def self.load
+ Dir.glob("#{MRUBY_ROOT}/tasks/toolchains/*.rake").each do |file|
+ Kernel.load file
+ end
+ end
+ end
+ Toolchain.load
+
+ class Build
+ class << self
+ attr_accessor :current
+ end
+ include Rake::DSL
+ include LoadGems
+ attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
+ attr_reader :libmruby, :gems, :toolchains
+ attr_writer :enable_bintest, :enable_test
+
+ COMPILERS = %w(cc cxx objc asm)
+ COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
+ attr_block MRuby::Build::COMMANDS
+
+ Exts = Struct.new(:object, :executable, :library)
+
+ def initialize(name='host', build_dir=nil, &block)
+ @name = name.to_s
+
+ unless MRuby.targets[@name]
+ if ENV['OS'] == 'Windows_NT'
+ @exts = Exts.new('.o', '.exe', '.a')
+ else
+ @exts = Exts.new('.o', '', '.a')
+ end
+
+ build_dir = build_dir || ENV['MRUBY_BUILD_DIR'] || "#{MRUBY_ROOT}/build"
+
+ @file_separator = '/'
+ @build_dir = "#{build_dir}/#{@name}"
+ @gem_clone_dir = "#{build_dir}/mrbgems"
+ @cc = Command::Compiler.new(self, %w(.c))
+ @cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp))
+ @objc = Command::Compiler.new(self, %w(.m))
+ @asm = Command::Compiler.new(self, %w(.S .asm))
+ @linker = Command::Linker.new(self)
+ @archiver = Command::Archiver.new(self)
+ @yacc = Command::Yacc.new(self)
+ @gperf = Command::Gperf.new(self)
+ @git = Command::Git.new(self)
+ @mrbc = Command::Mrbc.new(self)
+
+ @bins = []
+ @gems, @libmruby = MRuby::Gem::List.new, []
+ @build_mrbtest_lib_only = false
+ @cxx_exception_enabled = false
+ @cxx_exception_disabled = false
+ @cxx_abi_enabled = false
+ @enable_bintest = false
+ @enable_test = false
+ @toolchains = []
+
+ MRuby.targets[@name] = self
+ end
+
+ MRuby::Build.current = MRuby.targets[@name]
+ MRuby.targets[@name].instance_eval(&block)
+
+ build_mrbc_exec if name == 'host'
+ build_mrbtest if test_enabled?
+ end
+
+ def enable_debug
+ compilers.each do |c|
+ c.defines += %w(MRB_DEBUG)
+ if toolchains.any? { |toolchain| toolchain == "gcc" }
+ c.flags += %w(-g3 -O0)
+ end
+ end
+ @mrbc.compile_options += ' -g'
+ end
+
+ def disable_cxx_exception
+ if @cxx_exception_enabled or @cxx_abi_enabled
+ raise "cxx_exception already enabled"
+ end
+ @cxx_exception_disabled = true
+ end
+
+ def enable_cxx_exception
+ return if @cxx_exception_enabled
+ return if @cxx_abi_enabled
+ if @cxx_exception_disabled
+ raise "cxx_exception disabled"
+ end
+ @cxx_exception_enabled = true
+ compilers.each { |c|
+ c.defines += %w(MRB_ENABLE_CXX_EXCEPTION)
+ c.flags << c.cxx_exception_flag
+ }
+ linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
+ end
+
+ def cxx_exception_enabled?
+ @cxx_exception_enabled
+ end
+
+ def cxx_abi_enabled?
+ @cxx_abi_enabled
+ end
+
+ def enable_cxx_abi
+ return if @cxx_abi_enabled
+ if @cxx_exception_enabled
+ raise "cxx_exception already enabled"
+ end
+ compilers.each { |c|
+ c.defines += %w(MRB_ENABLE_CXX_EXCEPTION MRB_ENABLE_CXX_ABI)
+ c.flags << c.cxx_compile_flag
+ }
+ compilers.each { |c| c.flags << c.cxx_compile_flag }
+ linker.command = cxx.command if toolchains.find { |v| v == 'gcc' }
+ @cxx_abi_enabled = true
+ end
+
+ def compile_as_cxx src, cxx_src, obj = nil, includes = []
+ src = File.absolute_path src
+ cxx_src = File.absolute_path cxx_src
+ obj = objfile(cxx_src) if obj.nil?
+
+ file cxx_src => [src, __FILE__] do |t|
+ FileUtils.mkdir_p File.dirname t.name
+ IO.write t.name, <<EOS
+#define __STDC_CONSTANT_MACROS
+#define __STDC_LIMIT_MACROS
+
+#ifndef MRB_ENABLE_CXX_ABI
+extern "C" {
+#endif
+#include "#{src}"
+#ifndef MRB_ENABLE_CXX_ABI
+}
+#endif
+EOS
+ end
+
+ file obj => cxx_src do |t|
+ cxx.run t.name, t.prerequisites.first, [], ["#{MRUBY_ROOT}/src"] + includes
+ end
+
+ obj
+ end
+
+ def enable_bintest
+ @enable_bintest = true
+ end
+
+ def bintest_enabled?
+ @enable_bintest
+ end
+
+ def toolchain(name, params={})
+ tc = Toolchain.toolchains[name.to_s]
+ fail "Unknown #{name} toolchain" unless tc
+ tc.setup(self, params)
+ @toolchains.unshift name.to_s
+ end
+
+ def primary_toolchain
+ @toolchains.first
+ end
+
+ def root
+ MRUBY_ROOT
+ end
+
+ def enable_test
+ @enable_test = true
+ end
+
+ def test_enabled?
+ @enable_test
+ end
+
+ def build_mrbtest
+ gem :core => 'mruby-test'
+ end
+
+ def build_mrbc_exec
+ gem :core => 'mruby-bin-mrbc'
+ end
+
+ def mrbcfile
+ return @mrbcfile if @mrbcfile
+
+ mrbc_build = MRuby.targets['host']
+ gems.each { |v| mrbc_build = self if v.name == 'mruby-bin-mrbc' }
+ @mrbcfile = mrbc_build.exefile("#{mrbc_build.build_dir}/bin/mrbc")
+ end
+
+ def compilers
+ COMPILERS.map do |c|
+ instance_variable_get("@#{c}")
+ end
+ end
+
+ def define_rules
+ compilers.each do |compiler|
+ if respond_to?(:enable_gems?) && enable_gems?
+ compiler.defines -= %w(DISABLE_GEMS)
+ else
+ compiler.defines += %w(DISABLE_GEMS)
+ end
+ compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
+ end
+ end
+
+ def filename(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| filename(n) }
+ else
+ '"%s"' % name.gsub('/', file_separator)
+ end
+ end
+
+ def cygwin_filename(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| cygwin_filename(n) }
+ else
+ '"%s"' % `cygpath -w "#{filename(name)}"`.strip
+ end
+ end
+
+ def exefile(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| exefile(n) }
+ else
+ "#{name}#{exts.executable}"
+ end
+ end
+
+ def objfile(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| objfile(n) }
+ else
+ "#{name}#{exts.object}"
+ end
+ end
+
+ def libfile(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| libfile(n) }
+ else
+ "#{name}#{exts.library}"
+ end
+ end
+
+ def build_mrbtest_lib_only
+ @build_mrbtest_lib_only = true
+ end
+
+ def build_mrbtest_lib_only?
+ @build_mrbtest_lib_only
+ end
+
+ def run_test
+ puts ">>> Test #{name} <<<"
+ mrbtest = exefile("#{build_dir}/bin/mrbtest")
+ sh "#{filename mrbtest.relative_path}#{$verbose ? ' -v' : ''}"
+ puts
+ run_bintest if bintest_enabled?
+ end
+
+ def run_bintest
+ targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
+ targets << filename(".") if File.directory? "./bintest"
+ sh "ruby test/bintest.rb #{targets.join ' '}"
+ end
+
+ def print_build_summary
+ puts "================================================"
+ puts " Config Name: #{@name}"
+ puts " Output Directory: #{self.build_dir.relative_path}"
+ puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
+ unless @gems.empty?
+ puts " Included Gems:"
+ @gems.map do |gem|
+ gem_version = " - #{gem.version}" if gem.version != '0.0.0'
+ gem_summary = " - #{gem.summary}" if gem.summary
+ puts " #{gem.name}#{gem_version}#{gem_summary}"
+ puts " - Binaries: #{gem.bins.join(', ')}" unless gem.bins.empty?
+ end
+ end
+ puts "================================================"
+ puts
+ end
+ end # Build
+
+ class CrossBuild < Build
+ attr_block %w(test_runner)
+ # cross compiling targets for building native extensions.
+ # host - arch of where the built binary will run
+ # build - arch of the machine building the binary
+ attr_accessor :host_target, :build_target
+
+ def initialize(name, build_dir=nil, &block)
+ @test_runner = Command::CrossTestRunner.new(self)
+ super
+ end
+
+ def mrbcfile
+ MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/mrbc")
+ end
+
+ def run_test
+ mrbtest = exefile("#{build_dir}/bin/mrbtest")
+ if (@test_runner.command == nil)
+ puts "You should run #{mrbtest} on target device."
+ puts
+ else
+ @test_runner.run(mrbtest)
+ end
+ end
+ end # CrossBuild
+end # MRuby
diff --git a/web/server/h2o/libh2o/deps/mruby/lib/mruby/build/command.rb b/web/server/h2o/libh2o/deps/mruby/lib/mruby/build/command.rb
new file mode 100644
index 00000000..694b4a24
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/lib/mruby/build/command.rb
@@ -0,0 +1,324 @@
+require 'forwardable'
+
+module MRuby
+ class Command
+ include Rake::DSL
+ extend Forwardable
+ def_delegators :@build, :filename, :objfile, :libfile, :exefile, :cygwin_filename
+ attr_accessor :build, :command
+
+ def initialize(build)
+ @build = build
+ end
+
+ # clone is deep clone without @build
+ def clone
+ target = super
+ excepts = %w(@build)
+ instance_variables.each do |attr|
+ unless excepts.include?(attr.to_s)
+ val = Marshal::load(Marshal.dump(instance_variable_get(attr))) # deep clone
+ target.instance_variable_set(attr, val)
+ end
+ end
+ target
+ end
+
+ NotFoundCommands = {}
+
+ private
+ def _run(options, params={})
+ return sh command + ' ' + ( options % params ) if NotFoundCommands.key? @command
+ begin
+ sh build.filename(command) + ' ' + ( options % params )
+ rescue RuntimeError
+ NotFoundCommands[@command] = true
+ _run options, params
+ end
+ end
+ end
+
+ class Command::Compiler < Command
+ attr_accessor :flags, :include_paths, :defines, :source_exts
+ attr_accessor :compile_options, :option_define, :option_include_path, :out_ext
+ attr_accessor :cxx_compile_flag, :cxx_exception_flag
+
+ def initialize(build, source_exts=[])
+ super(build)
+ @command = ENV['CC'] || 'cc'
+ @flags = [ENV['CFLAGS'] || []]
+ @source_exts = source_exts
+ @include_paths = ["#{MRUBY_ROOT}/include"]
+ @defines = %w()
+ @option_include_path = '-I%s'
+ @option_define = '-D%s'
+ @compile_options = '%{flags} -o %{outfile} -c %{infile}'
+ end
+
+ alias header_search_paths include_paths
+ def search_header_path(name)
+ header_search_paths.find do |v|
+ File.exist? build.filename("#{v}/#{name}").sub(/^"(.*)"$/, '\1')
+ end
+ end
+
+ def search_header(name)
+ path = search_header_path name
+ path && build.filename("#{path}/#{name}").sub(/^"(.*)"$/, '\1')
+ end
+
+ def all_flags(_defineds=[], _include_paths=[], _flags=[])
+ define_flags = [defines, _defineds].flatten.map{ |d| option_define % d }
+ include_path_flags = [include_paths, _include_paths].flatten.map do |f|
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ option_include_path % cygwin_filename(f)
+ else
+ option_include_path % filename(f)
+ end
+ end
+ [flags, define_flags, include_path_flags, _flags].flatten.join(' ')
+ end
+
+ def run(outfile, infile, _defineds=[], _include_paths=[], _flags=[])
+ FileUtils.mkdir_p File.dirname(outfile)
+ _pp "CC", infile.relative_path, outfile.relative_path
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
+ :infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) }
+ else
+ _run compile_options, { :flags => all_flags(_defineds, _include_paths, _flags),
+ :infile => filename(infile), :outfile => filename(outfile) }
+ end
+ end
+
+ def define_rules(build_dir, source_dir='')
+ @out_ext = build.exts.object
+ gemrake = File.join(source_dir, "mrbgem.rake")
+ rakedep = File.exist?(gemrake) ? [ gemrake ] : []
+
+ if build_dir.include? "mrbgems/"
+ generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(.*)#{Regexp.escape out_ext}$")
+ else
+ generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(?!mrbgems/.+/)(.*)#{Regexp.escape out_ext}$")
+ end
+ source_exts.each do |ext, compile|
+ rule generated_file_matcher => [
+ proc { |file|
+ file.sub(generated_file_matcher, "#{source_dir}/\\1#{ext}")
+ },
+ proc { |file|
+ get_dependencies(file) + rakedep
+ }
+ ] do |t|
+ run t.name, t.prerequisites.first
+ end
+
+ rule generated_file_matcher => [
+ proc { |file|
+ file.sub(generated_file_matcher, "#{build_dir}/\\1#{ext}")
+ },
+ proc { |file|
+ get_dependencies(file) + rakedep
+ }
+ ] do |t|
+ run t.name, t.prerequisites.first
+ end
+ end
+ end
+
+ private
+ def get_dependencies(file)
+ file = file.ext('d') unless File.extname(file) == '.d'
+ if File.exist?(file)
+ File.read(file).gsub("\\\n ", "").scan(/^\S+:\s+(.+)$/).flatten.map {|s| s.split(' ') }.flatten
+ else
+ []
+ end + [ MRUBY_CONFIG ]
+ end
+ end
+
+ class Command::Linker < Command
+ attr_accessor :flags, :library_paths, :flags_before_libraries, :libraries, :flags_after_libraries
+ attr_accessor :link_options, :option_library, :option_library_path
+
+ def initialize(build)
+ super
+ @command = ENV['LD'] || 'ld'
+ @flags = (ENV['LDFLAGS'] || [])
+ @flags_before_libraries, @flags_after_libraries = [], []
+ @libraries = []
+ @library_paths = []
+ @option_library = '-l%s'
+ @option_library_path = '-L%s'
+ @link_options = "%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}"
+ end
+
+ def all_flags(_library_paths=[], _flags=[])
+ library_path_flags = [library_paths, _library_paths].flatten.map do |f|
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ option_library_path % cygwin_filename(f)
+ else
+ option_library_path % filename(f)
+ end
+ end
+ [flags, library_path_flags, _flags].flatten.join(' ')
+ end
+
+ def library_flags(_libraries)
+ [libraries, _libraries].flatten.map{ |d| option_library % d }.join(' ')
+ end
+
+ def run(outfile, objfiles, _libraries=[], _library_paths=[], _flags=[], _flags_before_libraries=[], _flags_after_libraries=[])
+ FileUtils.mkdir_p File.dirname(outfile)
+ library_flags = [libraries, _libraries].flatten.map { |d| option_library % d }
+
+ _pp "LD", outfile.relative_path
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ _run link_options, { :flags => all_flags(_library_paths, _flags),
+ :outfile => cygwin_filename(outfile) , :objs => cygwin_filename(objfiles).join(' '),
+ :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '),
+ :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '),
+ :libs => library_flags.join(' ') }
+ else
+ _run link_options, { :flags => all_flags(_library_paths, _flags),
+ :outfile => filename(outfile) , :objs => filename(objfiles).join(' '),
+ :flags_before_libraries => [flags_before_libraries, _flags_before_libraries].flatten.join(' '),
+ :flags_after_libraries => [flags_after_libraries, _flags_after_libraries].flatten.join(' '),
+ :libs => library_flags.join(' ') }
+ end
+ end
+ end
+
+ class Command::Archiver < Command
+ attr_accessor :archive_options
+
+ def initialize(build)
+ super
+ @command = ENV['AR'] || 'ar'
+ @archive_options = 'rs %{outfile} %{objs}'
+ end
+
+ def run(outfile, objfiles)
+ FileUtils.mkdir_p File.dirname(outfile)
+ _pp "AR", outfile.relative_path
+ if MRUBY_BUILD_HOST_IS_CYGWIN
+ _run archive_options, { :outfile => cygwin_filename(outfile), :objs => cygwin_filename(objfiles).join(' ') }
+ else
+ _run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).join(' ') }
+ end
+ end
+ end
+
+ class Command::Yacc < Command
+ attr_accessor :compile_options
+
+ def initialize(build)
+ super
+ @command = 'bison'
+ @compile_options = '-o %{outfile} %{infile}'
+ end
+
+ def run(outfile, infile)
+ FileUtils.mkdir_p File.dirname(outfile)
+ _pp "YACC", infile.relative_path, outfile.relative_path
+ _run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) }
+ end
+ end
+
+ class Command::Gperf < Command
+ attr_accessor :compile_options
+
+ def initialize(build)
+ super
+ @command = 'gperf'
+ @compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}'
+ end
+
+ def run(outfile, infile)
+ FileUtils.mkdir_p File.dirname(outfile)
+ _pp "GPERF", infile.relative_path, outfile.relative_path
+ _run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) }
+ end
+ end
+
+ class Command::Git < Command
+ attr_accessor :flags
+ attr_accessor :clone_options, :pull_options, :checkout_options
+
+ def initialize(build)
+ super
+ @command = 'git'
+ @flags = %w[]
+ @clone_options = "clone %{flags} %{url} %{dir}"
+ @pull_options = "pull"
+ @checkout_options = "checkout %{checksum_hash}"
+ end
+
+ def run_clone(dir, url, _flags = [])
+ _pp "GIT", url, dir.relative_path
+ _run clone_options, { :flags => [flags, _flags].flatten.join(' '), :url => url, :dir => filename(dir) }
+ end
+
+ def run_pull(dir, url)
+ root = Dir.pwd
+ Dir.chdir dir
+ _pp "GIT PULL", url, dir.relative_path
+ _run pull_options
+ Dir.chdir root
+ end
+
+ def run_checkout(dir, checksum_hash)
+ root = Dir.pwd
+ Dir.chdir dir
+ _pp "GIT CHECKOUT", checksum_hash
+ _run checkout_options, { :checksum_hash => checksum_hash }
+ Dir.chdir root
+ end
+ end
+
+ class Command::Mrbc < Command
+ attr_accessor :compile_options
+
+ def initialize(build)
+ super
+ @command = nil
+ @compile_options = "-B%{funcname} -o-"
+ end
+
+ def run(out, infiles, funcname)
+ @command ||= @build.mrbcfile
+ infiles = [infiles].flatten
+ infiles.each do |f|
+ _pp "MRBC", f.relative_path, nil, :indent => 2
+ end
+ IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}} #{filename(infiles).join(' ')}", 'r+') do |io|
+ out.puts io.read
+ end
+ # if mrbc execution fail, drop the file
+ if $?.exitstatus != 0
+ File.delete(out.path)
+ exit(-1)
+ end
+ end
+ end
+
+ class Command::CrossTestRunner < Command
+ attr_accessor :runner_options
+ attr_accessor :verbose_flag
+ attr_accessor :flags
+
+ def initialize(build)
+ super
+ @command = nil
+ @runner_options = '%{flags} %{infile}'
+ @verbose_flag = ''
+ @flags = []
+ end
+
+ def run(testbinfile)
+ puts "TEST for " + @build.name
+ _run runner_options, { :flags => [flags, verbose_flag].flatten.join(' '), :infile => testbinfile }
+ end
+ end
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/lib/mruby/build/load_gems.rb b/web/server/h2o/libh2o/deps/mruby/lib/mruby/build/load_gems.rb
new file mode 100644
index 00000000..b48df651
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/lib/mruby/build/load_gems.rb
@@ -0,0 +1,122 @@
+module MRuby
+ module LoadGems
+ def gembox(gemboxfile)
+ gembox = File.expand_path("#{gemboxfile}.gembox", "#{MRUBY_ROOT}/mrbgems")
+ fail "Can't find gembox '#{gembox}'" unless File.exist?(gembox)
+
+ GemBox.config = self
+ GemBox.path = gembox
+
+ instance_eval File.read(gembox)
+
+ GemBox.path = nil
+ end
+
+ def gem(gemdir, &block)
+ caller_dir = File.expand_path(File.dirname(/^(.*?):\d/.match(caller.first).to_a[1]))
+
+ if gemdir.is_a?(Hash)
+ gemdir = load_special_path_gem(gemdir)
+ elsif GemBox.path && gemdir.is_a?(String)
+ gemdir = File.expand_path(gemdir, File.dirname(GemBox.path))
+ else
+ gemdir = File.expand_path(gemdir, caller_dir)
+ end
+
+ gemrake = File.join(gemdir, "mrbgem.rake")
+
+ fail "Can't find #{gemrake}" unless File.exist?(gemrake)
+ Gem.current = nil
+ load gemrake
+ return nil unless Gem.current
+
+ Gem.current.dir = gemdir
+ Gem.current.build = self.is_a?(MRuby::Build) ? self : MRuby::Build.current
+ Gem.current.build_config_initializer = block
+ gems << Gem.current
+
+ cxx_srcs = ['src', 'test', 'tools'].map do |subdir|
+ Dir.glob("#{Gem.current.dir}/#{subdir}/*.{cpp,cxx,cc}")
+ end.flatten
+ enable_cxx_exception unless cxx_srcs.empty?
+
+ Gem.current
+ end
+
+ def load_special_path_gem(params)
+ if params[:github]
+ params[:git] = "https://github.com/#{params[:github]}.git"
+ elsif params[:bitbucket]
+ if params[:method] == "ssh"
+ params[:git] = "git@bitbucket.org:#{params[:bitbucket]}.git"
+ else
+ params[:git] = "https://bitbucket.org/#{params[:bitbucket]}.git"
+ end
+ elsif params[:mgem]
+ mgem_list_dir = "#{gem_clone_dir}/mgem-list"
+ mgem_list_url = 'https://github.com/mruby/mgem-list.git'
+ if File.exist? mgem_list_dir
+ git.run_pull mgem_list_dir, mgem_list_url if $pull_gems
+ else
+ FileUtils.mkdir_p mgem_list_dir
+ git.run_clone mgem_list_dir, mgem_list_url, "--depth 1"
+ end
+
+ require 'yaml'
+
+ conf_path = "#{mgem_list_dir}/#{params[:mgem]}.gem"
+ conf_path = "#{mgem_list_dir}/mruby-#{params[:mgem]}.gem" unless File.exist? conf_path
+ fail "mgem not found: #{params[:mgem]}" unless File.exist? conf_path
+ conf = YAML.load File.read conf_path
+
+ fail "unknown mgem protocol: #{conf['protocol']}" if conf['protocol'] != 'git'
+ params[:git] = conf['repository']
+ params[:branch] = conf['branch'] if conf['branch']
+ end
+
+ if params[:core]
+ gemdir = "#{root}/mrbgems/#{params[:core]}"
+ elsif params[:path]
+ require 'pathname'
+ gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}"
+ elsif params[:git]
+ url = params[:git]
+ gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}"
+
+ # by default the 'master' branch is used
+ branch = params[:branch] ? params[:branch] : 'master'
+
+ if File.exist?(gemdir)
+ if $pull_gems
+ git.run_pull gemdir, url
+ else
+ gemdir
+ end
+ else
+ options = [params[:options]] || []
+ options << "--recursive"
+ options << "--branch \"#{branch}\""
+ options << "--depth 1" unless params[:checksum_hash]
+ FileUtils.mkdir_p "#{gem_clone_dir}"
+ git.run_clone gemdir, url, options
+ end
+
+ if params[:checksum_hash]
+ # Jump to the specified commit
+ git.run_checkout gemdir, params[:checksum_hash]
+ else
+ # Jump to the top of the branch
+ git.run_checkout gemdir, branch if $pull_gems
+ end
+ else
+ fail "unknown gem option #{params}"
+ end
+
+ gemdir
+ end
+
+ def enable_gems?
+ !@gems.empty?
+ end
+ end # LoadGems
+end # MRuby
diff --git a/web/server/h2o/libh2o/deps/mruby/lib/mruby/gem.rb b/web/server/h2o/libh2o/deps/mruby/lib/mruby/gem.rb
new file mode 100644
index 00000000..27a1d358
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/lib/mruby/gem.rb
@@ -0,0 +1,459 @@
+require 'pathname'
+require 'forwardable'
+require 'tsort'
+require 'shellwords'
+
+module MRuby
+ module Gem
+ class << self
+ attr_accessor :current
+ end
+ LinkerConfig = Struct.new(:libraries, :library_paths, :flags, :flags_before_libraries, :flags_after_libraries)
+
+ class Specification
+ include Rake::DSL
+ extend Forwardable
+ def_delegators :@build, :filename, :objfile, :libfile, :exefile
+
+ attr_accessor :name, :dir, :build
+ alias mruby build
+ attr_accessor :build_config_initializer
+ attr_accessor :mrblib_dir, :objs_dir
+
+ attr_accessor :version
+ attr_accessor :description, :summary
+ attr_accessor :homepage
+ attr_accessor :licenses, :authors
+ alias :license= :licenses=
+ alias :author= :authors=
+
+ attr_accessor :rbfiles, :objs
+ attr_accessor :test_objs, :test_rbfiles, :test_args
+ attr_accessor :test_preload
+
+ attr_accessor :bins
+
+ attr_accessor :requirements
+ attr_reader :dependencies, :conflicts
+
+ attr_accessor :export_include_paths
+
+ attr_reader :generate_functions
+
+ attr_block MRuby::Build::COMMANDS
+
+ def initialize(name, &block)
+ @name = name
+ @initializer = block
+ @version = "0.0.0"
+ @mrblib_dir = "mrblib"
+ @objs_dir = "src"
+ MRuby::Gem.current = self
+ end
+
+ def setup
+ MRuby::Gem.current = self
+ MRuby::Build::COMMANDS.each do |command|
+ instance_variable_set("@#{command}", @build.send(command).clone)
+ end
+ @linker = LinkerConfig.new([], [], [], [], [])
+
+ @rbfiles = Dir.glob("#{@dir}/#{@mrblib_dir}/**/*.rb").sort
+ @objs = Dir.glob("#{@dir}/#{@objs_dir}/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
+ objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
+ end
+
+ @test_rbfiles = Dir.glob("#{dir}/test/**/*.rb")
+ @test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
+ objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
+ end
+ @custom_test_init = !@test_objs.empty?
+ @test_preload = nil # 'test/assert.rb'
+ @test_args = {}
+
+ @bins = []
+
+ @requirements = []
+ @dependencies, @conflicts = [], []
+ @export_include_paths = []
+ @export_include_paths << "#{dir}/include" if File.directory? "#{dir}/include"
+
+ instance_eval(&@initializer)
+
+ @generate_functions = !(@rbfiles.empty? && @objs.empty?)
+ @objs << objfile("#{build_dir}/gem_init") if @generate_functions
+
+ if !name || !licenses || !authors
+ fail "#{name || dir} required to set name, license(s) and author(s)"
+ end
+
+ build.libmruby << @objs
+
+ instance_eval(&@build_config_initializer) if @build_config_initializer
+ end
+
+ def setup_compilers
+ compilers.each do |compiler|
+ compiler.define_rules build_dir, "#{dir}"
+ compiler.defines << %Q[MRBGEM_#{funcname.upcase}_VERSION=#{version}]
+ compiler.include_paths << "#{dir}/include" if File.directory? "#{dir}/include"
+ end
+
+ define_gem_init_builder if @generate_functions
+ end
+
+ def add_dependency(name, *requirements)
+ default_gem = requirements.last.kind_of?(Hash) ? requirements.pop : nil
+ requirements = ['>= 0.0.0'] if requirements.empty?
+ requirements.flatten!
+ @dependencies << {:gem => name, :requirements => requirements, :default => default_gem}
+ end
+
+ def add_test_dependency(*args)
+ add_dependency(*args) if build.test_enabled?
+ end
+
+ def add_conflict(name, *req)
+ @conflicts << {:gem => name, :requirements => req.empty? ? nil : req}
+ end
+
+ def self.bin=(bin)
+ @bins = [bin].flatten
+ end
+
+ def build_dir
+ "#{build.build_dir}/mrbgems/#{name}"
+ end
+
+ def test_rbireps
+ "#{build_dir}/gem_test.c"
+ end
+
+ def search_package(name, version_query=nil)
+ package_query = name
+ package_query += " #{version_query}" if version_query
+ _pp "PKG-CONFIG", package_query
+ escaped_package_query = Shellwords.escape(package_query)
+ if system("pkg-config --exists #{escaped_package_query}")
+ cc.flags += [`pkg-config --cflags #{escaped_package_query}`.strip]
+ cxx.flags += [`pkg-config --cflags #{escaped_package_query}`.strip]
+ linker.flags_before_libraries += [`pkg-config --libs #{escaped_package_query}`.strip]
+ true
+ else
+ false
+ end
+ end
+
+ def funcname
+ @funcname ||= @name.gsub('-', '_')
+ end
+
+ def compilers
+ MRuby::Build::COMPILERS.map do |c|
+ instance_variable_get("@#{c}")
+ end
+ end
+
+ def define_gem_init_builder
+ file objfile("#{build_dir}/gem_init") => [ "#{build_dir}/gem_init.c", File.join(dir, "mrbgem.rake") ]
+ file "#{build_dir}/gem_init.c" => [build.mrbcfile, __FILE__] + [rbfiles].flatten do |t|
+ FileUtils.mkdir_p build_dir
+ generate_gem_init("#{build_dir}/gem_init.c")
+ end
+ end
+
+ def generate_gem_init(fname)
+ open(fname, 'w') do |f|
+ print_gem_init_header f
+ build.mrbc.run f, rbfiles, "gem_mrblib_irep_#{funcname}" unless rbfiles.empty?
+ f.puts %Q[void mrb_#{funcname}_gem_init(mrb_state *mrb);]
+ f.puts %Q[void mrb_#{funcname}_gem_final(mrb_state *mrb);]
+ f.puts %Q[]
+ f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_init(mrb_state *mrb) {]
+ f.puts %Q[ int ai = mrb_gc_arena_save(mrb);]
+ f.puts %Q[ mrb_#{funcname}_gem_init(mrb);] if objs != [objfile("#{build_dir}/gem_init")]
+ unless rbfiles.empty?
+ f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});]
+ f.puts %Q[ if (mrb->exc) {]
+ f.puts %Q[ mrb_print_error(mrb);]
+ f.puts %Q[ exit(EXIT_FAILURE);]
+ f.puts %Q[ }]
+ end
+ f.puts %Q[ mrb_gc_arena_restore(mrb, ai);]
+ f.puts %Q[}]
+ f.puts %Q[]
+ f.puts %Q[void GENERATED_TMP_mrb_#{funcname}_gem_final(mrb_state *mrb) {]
+ f.puts %Q[ mrb_#{funcname}_gem_final(mrb);] if objs != [objfile("#{build_dir}/gem_init")]
+ f.puts %Q[}]
+ end
+ end # generate_gem_init
+
+ def print_gem_comment(f)
+ f.puts %Q[/*]
+ f.puts %Q[ * This file is loading the irep]
+ f.puts %Q[ * Ruby GEM code.]
+ f.puts %Q[ *]
+ f.puts %Q[ * IMPORTANT:]
+ f.puts %Q[ * This file was generated!]
+ f.puts %Q[ * All manual changes will get lost.]
+ f.puts %Q[ */]
+ end
+
+ def print_gem_init_header(f)
+ print_gem_comment(f)
+ f.puts %Q[#include <stdlib.h>] unless rbfiles.empty?
+ f.puts %Q[#include <mruby.h>]
+ f.puts %Q[#include <mruby/irep.h>] unless rbfiles.empty?
+ end
+
+ def print_gem_test_header(f)
+ print_gem_comment(f)
+ f.puts %Q[#include <stdio.h>]
+ f.puts %Q[#include <stdlib.h>]
+ f.puts %Q[#include <mruby.h>]
+ f.puts %Q[#include <mruby/irep.h>]
+ f.puts %Q[#include <mruby/variable.h>]
+ f.puts %Q[#include <mruby/hash.h>] unless test_args.empty?
+ end
+
+ def test_dependencies
+ [@name]
+ end
+
+ def custom_test_init?
+ @custom_test_init
+ end
+
+ def version_ok?(req_versions)
+ req_versions.map do |req|
+ cmp, ver = req.split
+ cmp_result = Version.new(version) <=> Version.new(ver)
+ case cmp
+ when '=' then cmp_result == 0
+ when '!=' then cmp_result != 0
+ when '>' then cmp_result == 1
+ when '<' then cmp_result == -1
+ when '>=' then cmp_result >= 0
+ when '<=' then cmp_result <= 0
+ when '~>'
+ Version.new(version).twiddle_wakka_ok?(Version.new(ver))
+ else
+ fail "Comparison not possible with '#{cmp}'"
+ end
+ end.all?
+ end
+ end # Specification
+
+ class Version
+ include Comparable
+ include Enumerable
+
+ def <=>(other)
+ ret = 0
+ own = to_enum
+
+ other.each do |oth|
+ begin
+ ret = own.next <=> oth
+ rescue StopIteration
+ ret = 0 <=> oth
+ end
+
+ break unless ret == 0
+ end
+
+ ret
+ end
+
+ # ~> compare algorithm
+ #
+ # Example:
+ # ~> 2.2 means >= 2.2.0 and < 3.0.0
+ # ~> 2.2.0 means >= 2.2.0 and < 2.3.0
+ def twiddle_wakka_ok?(other)
+ gr_or_eql = (self <=> other) >= 0
+ still_minor = (self <=> other.skip_minor) < 0
+ gr_or_eql and still_minor
+ end
+
+ def skip_minor
+ a = @ary.dup
+ a.slice!(-1)
+ a[-1] = a[-1].succ
+ a
+ end
+
+ def initialize(str)
+ @str = str
+ @ary = @str.split('.').map(&:to_i)
+ end
+
+ def each(&block); @ary.each(&block); end
+ def [](index); @ary[index]; end
+ def []=(index, value)
+ @ary[index] = value
+ @str = @ary.join('.')
+ end
+ def slice!(index)
+ @ary.slice!(index)
+ @str = @ary.join('.')
+ end
+ end # Version
+
+ class List
+ include Enumerable
+
+ def initialize
+ @ary = []
+ end
+
+ def each(&b)
+ @ary.each(&b)
+ end
+
+ def <<(gem)
+ unless @ary.detect {|g| g.dir == gem.dir }
+ @ary << gem
+ else
+ # GEM was already added to this list
+ end
+ end
+
+ def empty?
+ @ary.empty?
+ end
+
+ def generate_gem_table build
+ gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
+
+ default_gems = []
+ each do |g|
+ g.dependencies.each do |dep|
+ unless gem_table.key? dep[:gem]
+ if dep[:default]; default_gems << dep
+ elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core
+ default_gems << { :gem => dep[:gem], :default => { :core => dep[:gem] } }
+ else # fallback to mgem-list
+ default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
+ end
+ end
+ end
+ end
+
+ until default_gems.empty?
+ def_gem = default_gems.pop
+
+ spec = build.gem def_gem[:default]
+ fail "Invalid gem name: #{spec.name} (Expected: #{def_gem[:gem]})" if spec.name != def_gem[:gem]
+ spec.setup
+
+ spec.dependencies.each do |dep|
+ unless gem_table.key? dep[:gem]
+ if dep[:default]; default_gems << dep
+ else default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
+ end
+ end
+ end
+ gem_table[spec.name] = spec
+ end
+
+ each do |g|
+ g.dependencies.each do |dep|
+ name = dep[:gem]
+ req_versions = dep[:requirements]
+ dep_g = gem_table[name]
+
+ # check each GEM dependency against all available GEMs
+ if dep_g.nil?
+ fail "The GEM '#{g.name}' depends on the GEM '#{name}' but it could not be found"
+ end
+ unless dep_g.version_ok? req_versions
+ fail "#{name} version should be #{req_versions.join(' and ')} but was '#{dep_g.version}'"
+ end
+ end
+
+ cfls = g.conflicts.select { |c|
+ cfl_g = gem_table[c[:gem]]
+ cfl_g and cfl_g.version_ok?(c[:requirements] || ['>= 0.0.0'])
+ }.map { |c| "#{c[:gem]}(#{gem_table[c[:gem]].version})" }
+ fail "Conflicts of gem `#{g.name}` found: #{cfls.join ', '}" unless cfls.empty?
+ end
+
+ gem_table
+ end
+
+ def tsort_dependencies ary, table, all_dependency_listed = false
+ unless all_dependency_listed
+ left = ary.dup
+ until left.empty?
+ v = left.pop
+ table[v].dependencies.each do |dep|
+ left.push dep[:gem]
+ ary.push dep[:gem]
+ end
+ end
+ end
+
+ ary.uniq!
+ table.instance_variable_set :@root_gems, ary
+ class << table
+ include TSort
+ def tsort_each_node &b
+ @root_gems.each &b
+ end
+
+ def tsort_each_child(n, &b)
+ fetch(n).dependencies.each do |v|
+ b.call v[:gem]
+ end
+ end
+ end
+
+ begin
+ table.tsort.map { |v| table[v] }
+ rescue TSort::Cyclic => e
+ fail "Circular mrbgem dependency found: #{e.message}"
+ end
+ end
+
+ def check(build)
+ gem_table = generate_gem_table build
+
+ @ary = tsort_dependencies gem_table.keys, gem_table, true
+
+ each(&:setup_compilers)
+
+ each do |g|
+ import_include_paths(g)
+ end
+ end
+
+ def import_include_paths(g)
+ gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
+ g.dependencies.each do |dep|
+ dep_g = gem_table[dep[:gem]]
+ # We can do recursive call safely
+ # as circular dependency has already detected in the caller.
+ import_include_paths(dep_g)
+
+ dep_g.export_include_paths.uniq!
+ g.compilers.each do |compiler|
+ compiler.include_paths += dep_g.export_include_paths
+ g.export_include_paths += dep_g.export_include_paths
+ compiler.include_paths.uniq!
+ g.export_include_paths.uniq!
+ end
+ end
+ end
+ end # List
+ end # Gem
+
+ GemBox = Object.new
+ class << GemBox
+ attr_accessor :path
+
+ def new(&block); block.call(self); end
+ def config=(obj); @config = obj; end
+ def gem(gemdir, &block); @config.gem(gemdir, &block); end
+ end # GemBox
+end # MRuby
diff --git a/web/server/h2o/libh2o/deps/mruby/lib/mruby/source.rb b/web/server/h2o/libh2o/deps/mruby/lib/mruby/source.rb
new file mode 100644
index 00000000..5819a322
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/lib/mruby/source.rb
@@ -0,0 +1,30 @@
+require "pathname"
+
+module MRuby
+ module Source
+ # MRuby's source root directory
+ ROOT = Pathname.new(File.expand_path('../../../',__FILE__))
+
+ # Reads a constant defined at version.h
+ MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] }
+
+ MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION']
+ MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE']
+
+ MRUBY_RELEASE_MAJOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MAJOR'])
+ MRUBY_RELEASE_MINOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MINOR'])
+ MRUBY_RELEASE_TEENY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_TEENY'])
+
+ MRUBY_VERSION = [MRUBY_RELEASE_MAJOR,MRUBY_RELEASE_MINOR,MRUBY_RELEASE_TEENY].join('.')
+ MRUBY_RELEASE_NO = (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY)
+
+ MRUBY_RELEASE_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_YEAR'])
+ MRUBY_RELEASE_MONTH = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MONTH'])
+ MRUBY_RELEASE_DAY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_DAY'])
+ MRUBY_RELEASE_DATE = [MRUBY_RELEASE_YEAR,MRUBY_RELEASE_MONTH,MRUBY_RELEASE_DAY].join('.')
+
+ MRUBY_BIRTH_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_BIRTH_YEAR'])
+
+ MRUBY_AUTHOR = MRUBY_READ_VERSION_CONSTANT['MRUBY_AUTHOR']
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/minirake b/web/server/h2o/libh2o/deps/mruby/minirake
new file mode 100755
index 00000000..542c37a7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/minirake
@@ -0,0 +1,484 @@
+#!/usr/bin/env ruby
+
+# Original is https://github.com/jimweirich/rake/
+# Copyright (c) 2003 Jim Weirich
+# License: MIT-LICENSE
+
+require 'getoptlong'
+require 'fileutils'
+
+class String
+ def ext(newext='')
+ return self.dup if ['.', '..'].include? self
+ if newext != ''
+ newext = (newext =~ /^\./) ? newext : ("." + newext)
+ end
+ self.chomp(File.extname(self)) << newext
+ end
+
+ def pathmap(spec=nil, &block)
+ return self if spec.nil?
+ result = ''
+ spec.scan(/%\{[^}]*\}-?\d*[sdpfnxX%]|%-?\d+d|%.|[^%]+/) do |frag|
+ case frag
+ when '%f'
+ result << File.basename(self)
+ when '%n'
+ result << File.basename(self).ext
+ when '%d'
+ result << File.dirname(self)
+ when '%x'
+ result << File.extname(self)
+ when '%X'
+ result << self.ext
+ when '%p'
+ result << self
+ when '%s'
+ result << (File::ALT_SEPARATOR || File::SEPARATOR)
+ when '%-'
+ # do nothing
+ when '%%'
+ result << "%"
+ when /%(-?\d+)d/
+ result << pathmap_partial($1.to_i)
+ when /^%\{([^}]*)\}(\d*[dpfnxX])/
+ patterns, operator = $1, $2
+ result << pathmap('%' + operator).pathmap_replace(patterns, &block)
+ when /^%/
+ fail ArgumentError, "Unknown pathmap specifier #{frag} in '#{spec}'"
+ else
+ result << frag
+ end
+ end
+ result
+ end
+end
+
+module MiniRake
+ class Task
+ TASKS = Hash.new
+ RULES = Array.new
+
+ # List of prerequisites for a task.
+ attr_reader :prerequisites
+
+ # Source dependency for rule synthesized tasks. Nil if task was not
+ # sythesized from a rule.
+ attr_accessor :source
+
+ # Create a task named +task_name+ with no actions or prerequisites..
+ # use +enhance+ to add actions and prerequisites.
+ def initialize(task_name)
+ @name = task_name
+ @prerequisites = []
+ @actions = []
+ end
+
+ # Enhance a task with prerequisites or actions. Returns self.
+ def enhance(deps=nil, &block)
+ @prerequisites |= deps if deps
+ @actions << block if block_given?
+ self
+ end
+
+ # Name of the task.
+ def name
+ @name.to_s
+ end
+
+ # Invoke the task if it is needed. Prerequites are invoked first.
+ def invoke
+ puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
+ return if @already_invoked
+ @already_invoked = true
+ prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
+ prerequisites.each { |n| Task[n].invoke }
+ execute if needed?
+ end
+
+ # Execute the actions associated with this task.
+ def execute
+ puts "Execute #{name}" if $trace
+ self.class.enhance_with_matching_rule(name) if @actions.empty?
+ unless $dryrun
+ @actions.each { |act| act.call(self) }
+ end
+ end
+
+ # Is this task needed?
+ def needed?
+ true
+ end
+
+ # Timestamp for this task. Basic tasks return the current time for
+ # their time stamp. Other tasks can be more sophisticated.
+ def timestamp
+ Time.now
+ end
+
+ # Class Methods ----------------------------------------------------
+
+ class << self
+
+ # Clear the task list. This cause rake to immediately forget all
+ # the tasks that have been assigned. (Normally used in the unit
+ # tests.)
+ def clear
+ TASKS.clear
+ RULES.clear
+ end
+
+ # List of all defined tasks.
+ def tasks
+ TASKS.keys.sort.collect { |tn| Task[tn] }
+ end
+
+ # Return a task with the given name. If the task is not currently
+ # known, try to synthesize one from the defined rules. If no
+ # rules are found, but an existing file matches the task name,
+ # assume it is a file task with no dependencies or actions.
+ def [](task_name)
+ task_name = task_name.to_s
+ if task = TASKS[task_name]
+ return task
+ end
+ if task = enhance_with_matching_rule(task_name)
+ return task
+ end
+ if File.exist?(task_name)
+ return FileTask.define_task(task_name)
+ end
+ fail "Don't know how to rake #{task_name}"
+ end
+
+ # Define a task given +args+ and an option block. If a rule with
+ # the given name already exists, the prerequisites and actions are
+ # added to the existing task.
+ def define_task(args, &block)
+ task_name, deps = resolve_args(args)
+ lookup(task_name).enhance([deps].flatten, &block)
+ end
+
+ # Define a rule for synthesizing tasks.
+ def create_rule(args, &block)
+ pattern, deps = resolve_args(args)
+ pattern = Regexp.new(Regexp.quote(pattern) + '$') if String === pattern
+ RULES << [pattern, deps, block]
+ end
+
+
+ # Lookup a task. Return an existing task if found, otherwise
+ # create a task of the current type.
+ def lookup(task_name)
+ name = task_name.to_s
+ TASKS[name] ||= self.new(name)
+ end
+
+ # If a rule can be found that matches the task name, enhance the
+ # task with the prerequisites and actions from the rule. Set the
+ # source attribute of the task appropriately for the rule. Return
+ # the enhanced task or nil of no rule was found.
+ def enhance_with_matching_rule(task_name)
+ RULES.each do |pattern, extensions, block|
+ if pattern.match(task_name)
+ ext = extensions.first
+ deps = extensions[1..-1]
+ case ext
+ when String
+ source = task_name.sub(/\.[^.]*$/, ext)
+ when Proc
+ source = ext.call(task_name)
+ else
+ fail "Don't know how to handle rule dependent: #{ext.inspect}"
+ end
+ if File.exist?(source)
+ task = FileTask.define_task({task_name => [source]+deps}, &block)
+ task.source = source
+ return task
+ end
+ end
+ end
+ nil
+ end
+
+ private
+
+ # Resolve the arguments for a task/rule.
+ def resolve_args(args)
+ case args
+ when Hash
+ fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
+ fail "No Task Name Given" if args.size < 1
+ task_name = args.keys[0]
+ deps = args[task_name]
+ deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
+ else
+ task_name = args
+ deps = []
+ end
+ [task_name, deps]
+ end
+ end
+ end
+
+
+ ######################################################################
+ class FileTask < Task
+ # Is this file task needed? Yes if it doesn't exist, or if its time
+ # stamp is out of date.
+ def needed?
+ return true unless File.exist?(name)
+ prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
+ latest_prereq = prerequisites.collect{|n| Task[n].timestamp}.max
+ return false if latest_prereq.nil?
+ timestamp < latest_prereq
+ end
+
+ # Time stamp for file task.
+ def timestamp
+ return Time.at(0) unless File.exist?(name)
+ stat = File::stat(name.to_s)
+ stat.directory? ? Time.at(0) : stat.mtime
+ end
+ end
+
+ module DSL
+ # Declare a basic task.
+ def task(args, &block)
+ MiniRake::Task.define_task(args, &block)
+ end
+
+ # Declare a file task.
+ def file(args, &block)
+ MiniRake::FileTask.define_task(args, &block)
+ end
+
+ # Declare a set of files tasks to create the given directories on
+ # demand.
+ def directory(args, &block)
+ MiniRake::FileTask.define_task(args) do |t|
+ block.call(t) unless block.nil?
+ dir = args.is_a?(Hash) ? args.keys.first : args
+ (dir.split(File::SEPARATOR) + ['']).inject do |acc, part|
+ (acc + File::SEPARATOR).tap do |d|
+ Dir.mkdir(d) unless File.exists? d
+ end + part
+ end
+ end
+ end
+
+ # Declare a rule for auto-tasks.
+ def rule(args, &block)
+ MiniRake::Task.create_rule(args, &block)
+ end
+
+ # Write a message to standard out if $verbose is enabled.
+ def log(msg)
+ print " " if $trace && $verbose
+ puts msg if $verbose
+ end
+
+ # Run the system command +cmd+.
+ def sh(cmd)
+ puts cmd if $verbose
+ system(cmd) or fail "Command Failed: [#{cmd}]"
+ end
+
+ def desc(text)
+ end
+ end
+end
+
+Rake = MiniRake
+extend MiniRake::DSL
+
+
+######################################################################
+# Task Definition Functions ...
+
+######################################################################
+# Rake main application object. When invoking +rake+ from the command
+# line, a RakeApp object is created and run.
+#
+class RakeApp
+ RAKEFILES = ['rakefile', 'Rakefile']
+
+ OPTIONS = [
+ ['--dry-run', '-n', GetoptLong::NO_ARGUMENT,
+ "Do a dry run without executing actions."],
+ ['--help', '-H', GetoptLong::NO_ARGUMENT,
+ "Display this help message."],
+ ['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT,
+ "Include LIBDIR in the search path for required modules."],
+ ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
+ "Do not search parent directories for the Rakefile."],
+ ['--quiet', '-q', GetoptLong::NO_ARGUMENT,
+ "Do not log messages to standard output (default)."],
+ ['--rakefile', '-f', GetoptLong::REQUIRED_ARGUMENT,
+ "Use FILE as the rakefile."],
+ ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
+ "Require MODULE before executing rakefile."],
+ ['--tasks', '-T', GetoptLong::NO_ARGUMENT,
+ "Display the tasks and dependencies, then exit."],
+ ['--pull-gems','-p', GetoptLong::NO_ARGUMENT,
+ "Pull all git mrbgems."],
+ ['--trace', '-t', GetoptLong::NO_ARGUMENT,
+ "Turn on invoke/execute tracing."],
+ ['--usage', '-h', GetoptLong::NO_ARGUMENT,
+ "Display usage."],
+ ['--verbose', '-v', GetoptLong::NO_ARGUMENT,
+ "Log message to standard output."],
+ ['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT,
+ "Change executing directory of rakefiles."]
+ ]
+
+ # Create a RakeApp object.
+ def initialize
+ @rakefile = nil
+ @nosearch = false
+ end
+
+ # True if one of the files in RAKEFILES is in the current directory.
+ # If a match is found, it is copied into @rakefile.
+ def have_rakefile
+ RAKEFILES.each do |fn|
+ if File.exist?(fn)
+ @rakefile = fn
+ return true
+ end
+ end
+ return false
+ end
+
+ # Display the program usage line.
+ def usage
+ puts "rake [-f rakefile] {options} targets..."
+ end
+
+ # Display the rake command line help.
+ def help
+ usage
+ puts
+ puts "Options are ..."
+ puts
+ OPTIONS.sort.each do |long, short, mode, desc|
+ if mode == GetoptLong::REQUIRED_ARGUMENT
+ if desc =~ /\b([A-Z]{2,})\b/
+ long = long + "=#{$1}"
+ end
+ end
+ printf " %-20s (%s)\n", long, short
+ printf " %s\n", desc
+ end
+ end
+
+ # Display the tasks and dependencies.
+ def display_tasks
+ MiniRake::Task.tasks.each do |t|
+ puts "#{t.class} #{t.name}"
+ t.prerequisites.each { |pre| puts " #{pre}" }
+ end
+ end
+
+ # Return a list of the command line options supported by the
+ # program.
+ def command_line_options
+ OPTIONS.collect { |lst| lst[0..-2] }
+ end
+
+ # Do the option defined by +opt+ and +value+.
+ def do_option(opt, value)
+ case opt
+ when '--dry-run'
+ $dryrun = true
+ $trace = true
+ when '--help'
+ help
+ exit
+ when '--libdir'
+ $:.push(value)
+ when '--nosearch'
+ @nosearch = true
+ when '--quiet'
+ $verbose = false
+ when '--rakefile'
+ RAKEFILES.clear
+ RAKEFILES << value
+ when '--require'
+ require value
+ when '--tasks'
+ $show_tasks = true
+ when '--pull-gems'
+ $pull_gems = true
+ when '--trace'
+ $trace = true
+ when '--usage'
+ usage
+ exit
+ when '--verbose'
+ $verbose = true
+ when '--version'
+ puts "rake, version #{RAKEVERSION}"
+ exit
+ when '--directory'
+ Dir.chdir value
+ else
+ fail "Unknown option: #{opt}"
+ end
+ end
+
+ # Read and handle the command line options.
+ def handle_options
+ $verbose = false
+ $pull_gems = false
+ opts = GetoptLong.new(*command_line_options)
+ opts.each { |opt, value| do_option(opt, value) }
+ end
+
+ # Run the +rake+ application.
+ def run
+ handle_options
+ begin
+ here = Dir.pwd
+ while ! have_rakefile
+ Dir.chdir("..")
+ if Dir.pwd == here || @nosearch
+ fail "No Rakefile found (looking for: #{RAKEFILES.join(', ')})"
+ end
+ here = Dir.pwd
+ end
+ tasks = []
+ ARGV.each do |task_name|
+ if /^(\w+)=(.*)/.match(task_name)
+ ENV[$1] = $2
+ else
+ tasks << task_name
+ end
+ end
+ puts "(in #{Dir.pwd})"
+ $rakefile = @rakefile
+ load @rakefile
+ if $show_tasks
+ display_tasks
+ else
+ tasks.push("default") if tasks.size == 0
+ tasks.each do |task_name|
+ MiniRake::Task[task_name].invoke
+ end
+ end
+ rescue Exception => ex
+ puts "rake aborted!"
+ puts ex.message
+ if $trace
+ puts ex.backtrace.join("\n")
+ else
+ puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
+ end
+ exit 1
+ end
+ end
+end
+
+if __FILE__ == $0 then
+ RakeApp.new.run
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/default.gembox b/web/server/h2o/libh2o/deps/mruby/mrbgems/default.gembox
new file mode 100644
index 00000000..64f05de1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/default.gembox
@@ -0,0 +1,79 @@
+MRuby::GemBox.new do |conf|
+ # Use standard Kernel#sprintf method
+ conf.gem :core => "mruby-sprintf"
+
+ # Use standard print/puts/p
+ conf.gem :core => "mruby-print"
+
+ # Use standard Math module
+ conf.gem :core => "mruby-math"
+
+ # Use standard Time class
+ conf.gem :core => "mruby-time"
+
+ # Use standard Struct class
+ conf.gem :core => "mruby-struct"
+
+ # Use Enumerable module extension
+ conf.gem :core => "mruby-enum-ext"
+
+ # Use String class extension
+ conf.gem :core => "mruby-string-ext"
+
+ # Use Numeric class extension
+ conf.gem :core => "mruby-numeric-ext"
+
+ # Use Array class extension
+ conf.gem :core => "mruby-array-ext"
+
+ # Use Hash class extension
+ conf.gem :core => "mruby-hash-ext"
+
+ # Use Range class extension
+ conf.gem :core => "mruby-range-ext"
+
+ # Use Proc class extension
+ conf.gem :core => "mruby-proc-ext"
+
+ # Use Symbol class extension
+ conf.gem :core => "mruby-symbol-ext"
+
+ # Use Random class
+ conf.gem :core => "mruby-random"
+
+ # Use Object class extension
+ conf.gem :core => "mruby-object-ext"
+
+ # Use ObjectSpace class
+ conf.gem :core => "mruby-objectspace"
+
+ # Use Fiber class
+ conf.gem :core => "mruby-fiber"
+
+ # Use Enumerator class (require mruby-fiber)
+ conf.gem :core => "mruby-enumerator"
+
+ # Use Enumerator::Lazy class (require mruby-enumerator)
+ conf.gem :core => "mruby-enum-lazy"
+
+ # Use toplevel object (main) methods extension
+ conf.gem :core => "mruby-toplevel-ext"
+
+ # Generate mirb command
+ conf.gem :core => "mruby-bin-mirb"
+
+ # Generate mruby command
+ conf.gem :core => "mruby-bin-mruby"
+
+ # Generate mruby-strip command
+ conf.gem :core => "mruby-bin-strip"
+
+ # Use Kernel module extension
+ conf.gem :core => "mruby-kernel-ext"
+
+ # Use class/module extension
+ conf.gem :core => "mruby-class-ext"
+
+ # Use mruby-compiler to build other mrbgems
+ conf.gem :core => "mruby-compiler"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/full-core.gembox b/web/server/h2o/libh2o/deps/mruby/mrbgems/full-core.gembox
new file mode 100644
index 00000000..9a5b7081
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/full-core.gembox
@@ -0,0 +1,9 @@
+MRuby::GemBox.new do |conf|
+ conf.gem :core => "mruby-sprintf"
+ conf.gem :core => "mruby-print"
+
+ Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x|
+ g = File.basename File.dirname x
+ conf.gem :core => g unless g =~ /^mruby-(print|sprintf|bin-debugger|test)$/
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrbgem.rake
new file mode 100644
index 00000000..882caf1a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Array class extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrblib/array.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrblib/array.rb
new file mode 100644
index 00000000..e28e5238
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -0,0 +1,811 @@
+class Array
+ ##
+ # call-seq:
+ # Array.try_convert(obj) -> array or nil
+ #
+ # Tries to convert +obj+ into an array, using +to_ary+ method.
+ # converted array or +nil+ if +obj+ cannot be converted for any reason.
+ # This method can be used to check if an argument is an array.
+ #
+ # Array.try_convert([1]) #=> [1]
+ # Array.try_convert("1") #=> nil
+ #
+ # if tmp = Array.try_convert(arg)
+ # # the argument is an array
+ # elsif tmp = String.try_convert(arg)
+ # # the argument is a string
+ # end
+ #
+ def self.try_convert(obj)
+ if obj.respond_to?(:to_ary)
+ obj.to_ary
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
+ # ary.uniq! -> ary or nil
+ # ary.uniq! { |item| ... } -> ary or nil
+ #
+ # Removes duplicate elements from +self+.
+ # Returns <code>nil</code> if no changes are made (that is, no
+ # duplicates are found).
+ #
+ # a = [ "a", "a", "b", "b", "c" ]
+ # a.uniq! #=> ["a", "b", "c"]
+ # b = [ "a", "b", "c" ]
+ # b.uniq! #=> nil
+ # c = [["student","sam"], ["student","george"], ["teacher","matz"]]
+ # c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
+ #
+ def uniq!(&block)
+ ary = self.dup
+ result = []
+ if block
+ hash = {}
+ while ary.size > 0
+ val = ary.shift
+ key = block.call(val)
+ hash[key] = val unless hash.has_key?(key)
+ end
+ hash.each_value do |value|
+ result << value
+ end
+ else
+ while ary.size > 0
+ result << ary.shift
+ ary.delete(result.last)
+ end
+ end
+ if result.size == self.size
+ nil
+ else
+ self.replace(result)
+ end
+ end
+
+ ##
+ # call-seq:
+ # ary.uniq -> new_ary
+ # ary.uniq { |item| ... } -> new_ary
+ #
+ # Returns a new array by removing duplicate values in +self+.
+ #
+ # a = [ "a", "a", "b", "b", "c" ]
+ # a.uniq #=> ["a", "b", "c"]
+ #
+ # b = [["student","sam"], ["student","george"], ["teacher","matz"]]
+ # b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
+ #
+ def uniq(&block)
+ ary = self.dup
+ ary.uniq!(&block)
+ ary
+ end
+
+ ##
+ # call-seq:
+ # ary - other_ary -> new_ary
+ #
+ # Array Difference---Returns a new array that is a copy of
+ # the original array, removing any items that also appear in
+ # <i>other_ary</i>. (If you need set-like behavior, see the
+ # library class Set.)
+ #
+ # [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
+ #
+ def -(elem)
+ raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
+
+ hash = {}
+ array = []
+ idx = 0
+ len = elem.size
+ while idx < len
+ hash[elem[idx]] = true
+ idx += 1
+ end
+ idx = 0
+ len = size
+ while idx < len
+ v = self[idx]
+ array << v unless hash[v]
+ idx += 1
+ end
+ array
+ end
+
+ ##
+ # call-seq:
+ # ary | other_ary -> new_ary
+ #
+ # Set Union---Returns a new array by joining this array with
+ # <i>other_ary</i>, removing duplicates.
+ #
+ # [ "a", "b", "c" ] | [ "c", "d", "a" ]
+ # #=> [ "a", "b", "c", "d" ]
+ #
+ def |(elem)
+ raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
+
+ ary = self + elem
+ ary.uniq! or ary
+ end
+
+ ##
+ # call-seq:
+ # ary & other_ary -> new_ary
+ #
+ # Set Intersection---Returns a new array
+ # containing elements common to the two arrays, with no duplicates.
+ #
+ # [ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]
+ #
+ def &(elem)
+ raise TypeError, "can't convert #{elem.class} into Array" unless elem.class == Array
+
+ hash = {}
+ array = []
+ idx = 0
+ len = elem.size
+ while idx < len
+ hash[elem[idx]] = true
+ idx += 1
+ end
+ idx = 0
+ len = size
+ while idx < len
+ v = self[idx]
+ if hash[v]
+ array << v
+ hash.delete v
+ end
+ idx += 1
+ end
+ array
+ end
+
+ ##
+ # call-seq:
+ # ary.flatten -> new_ary
+ # ary.flatten(level) -> new_ary
+ #
+ # Returns a new array that is a one-dimensional flattening of this
+ # array (recursively). That is, for every element that is an array,
+ # extract its elements into the new array. If the optional
+ # <i>level</i> argument determines the level of recursion to flatten.
+ #
+ # s = [ 1, 2, 3 ] #=> [1, 2, 3]
+ # t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
+ # a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
+ # a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ # a = [ 1, 2, [3, [4, 5] ] ]
+ # a.flatten(1) #=> [1, 2, 3, [4, 5]]
+ #
+ def flatten(depth=nil)
+ res = dup
+ res.flatten! depth
+ res
+ end
+
+ ##
+ # call-seq:
+ # ary.flatten! -> ary or nil
+ # ary.flatten!(level) -> array or nil
+ #
+ # Flattens +self+ in place.
+ # Returns <code>nil</code> if no modifications were made (i.e.,
+ # <i>ary</i> contains no subarrays.) If the optional <i>level</i>
+ # argument determines the level of recursion to flatten.
+ #
+ # a = [ 1, 2, [3, [4, 5] ] ]
+ # a.flatten! #=> [1, 2, 3, 4, 5]
+ # a.flatten! #=> nil
+ # a #=> [1, 2, 3, 4, 5]
+ # a = [ 1, 2, [3, [4, 5] ] ]
+ # a.flatten!(1) #=> [1, 2, 3, [4, 5]]
+ #
+ def flatten!(depth=nil)
+ modified = false
+ ar = []
+ idx = 0
+ len = size
+ while idx < len
+ e = self[idx]
+ if e.is_a?(Array) && (depth.nil? || depth > 0)
+ ar += e.flatten(depth.nil? ? nil : depth - 1)
+ modified = true
+ else
+ ar << e
+ end
+ idx += 1
+ end
+ if modified
+ self.replace(ar)
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
+ # ary.compact -> new_ary
+ #
+ # Returns a copy of +self+ with all +nil+ elements removed.
+ #
+ # [ "a", nil, "b", nil, "c", nil ].compact
+ # #=> [ "a", "b", "c" ]
+ #
+ def compact
+ result = self.dup
+ result.compact!
+ result
+ end
+
+ ##
+ # call-seq:
+ # ary.compact! -> ary or nil
+ #
+ # Removes +nil+ elements from the array.
+ # Returns +nil+ if no changes were made, otherwise returns
+ # <i>ary</i>.
+ #
+ # [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
+ # [ "a", "b", "c" ].compact! #=> nil
+ #
+ def compact!
+ result = self.select { |e| !e.nil? }
+ if result.size == self.size
+ nil
+ else
+ self.replace(result)
+ end
+ end
+
+ # for efficiency
+ def reverse_each(&block)
+ return to_enum :reverse_each unless block
+
+ i = self.size - 1
+ while i>=0
+ block.call(self[i])
+ i -= 1
+ end
+ self
+ end
+
+ NONE=Object.new
+ ##
+ # call-seq:
+ # ary.fetch(index) -> obj
+ # ary.fetch(index, default) -> obj
+ # ary.fetch(index) { |index| block } -> obj
+ #
+ # Tries to return the element at position +index+, but throws an IndexError
+ # exception if the referenced +index+ lies outside of the array bounds. This
+ # error can be prevented by supplying a second argument, which will act as a
+ # +default+ value.
+ #
+ # Alternatively, if a block is given it will only be executed when an
+ # invalid +index+ is referenced.
+ #
+ # Negative values of +index+ count from the end of the array.
+ #
+ # a = [ 11, 22, 33, 44 ]
+ # a.fetch(1) #=> 22
+ # a.fetch(-1) #=> 44
+ # a.fetch(4, 'cat') #=> "cat"
+ # a.fetch(100) { |i| puts "#{i} is out of bounds" }
+ # #=> "100 is out of bounds"
+ #
+
+ def fetch(n=nil, ifnone=NONE, &block)
+ warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
+
+ idx = n
+ if idx < 0
+ idx += size
+ end
+ if idx < 0 || size <= idx
+ return block.call(n) if block
+ if ifnone == NONE
+ raise IndexError, "index #{n} outside of array bounds: #{-size}...#{size}"
+ end
+ return ifnone
+ end
+ self[idx]
+ end
+
+ ##
+ # call-seq:
+ # ary.fill(obj) -> ary
+ # ary.fill(obj, start [, length]) -> ary
+ # ary.fill(obj, range ) -> ary
+ # ary.fill { |index| block } -> ary
+ # ary.fill(start [, length] ) { |index| block } -> ary
+ # ary.fill(range) { |index| block } -> ary
+ #
+ # The first three forms set the selected elements of +self+ (which
+ # may be the entire array) to +obj+.
+ #
+ # A +start+ of +nil+ is equivalent to zero.
+ #
+ # A +length+ of +nil+ is equivalent to the length of the array.
+ #
+ # The last three forms fill the array with the value of the given block,
+ # which is passed the absolute index of each element to be filled.
+ #
+ # Negative values of +start+ count from the end of the array, where +-1+ is
+ # the last element.
+ #
+ # a = [ "a", "b", "c", "d" ]
+ # a.fill("x") #=> ["x", "x", "x", "x"]
+ # a.fill("w", -1) #=> ["x", "x", "x", "w"]
+ # a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
+ # a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
+ # a.fill { |i| i*i } #=> [0, 1, 4, 9]
+ # a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
+ # a.fill(1, 2) { |i| i+1 } #=> [0, 2, 3, 27]
+ # a.fill(0..1) { |i| i+1 } #=> [1, 2, 3, 27]
+ #
+
+ def fill(arg0=nil, arg1=nil, arg2=nil, &block)
+ if arg0.nil? && arg1.nil? && arg2.nil? && !block
+ raise ArgumentError, "wrong number of arguments (0 for 1..3)"
+ end
+
+ beg = len = 0
+ ary = []
+ if block
+ if arg0.nil? && arg1.nil? && arg2.nil?
+ # ary.fill { |index| block } -> ary
+ beg = 0
+ len = self.size
+ elsif !arg0.nil? && arg0.kind_of?(Range)
+ # ary.fill(range) { |index| block } -> ary
+ beg = arg0.begin
+ beg += self.size if beg < 0
+ len = arg0.end
+ len += self.size if len < 0
+ len += 1 unless arg0.exclude_end?
+ elsif !arg0.nil?
+ # ary.fill(start [, length] ) { |index| block } -> ary
+ beg = arg0
+ beg += self.size if beg < 0
+ if arg1.nil?
+ len = self.size
+ else
+ len = arg0 + arg1
+ end
+ end
+ else
+ if !arg0.nil? && arg1.nil? && arg2.nil?
+ # ary.fill(obj) -> ary
+ beg = 0
+ len = self.size
+ elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range)
+ # ary.fill(obj, range ) -> ary
+ beg = arg1.begin
+ beg += self.size if beg < 0
+ len = arg1.end
+ len += self.size if len < 0
+ len += 1 unless arg1.exclude_end?
+ elsif !arg0.nil? && !arg1.nil?
+ # ary.fill(obj, start [, length]) -> ary
+ beg = arg1
+ beg += self.size if beg < 0
+ if arg2.nil?
+ len = self.size
+ else
+ len = beg + arg2
+ end
+ end
+ end
+
+ i = beg
+ if block
+ while i < len
+ self[i] = block.call(i)
+ i += 1
+ end
+ else
+ while i < len
+ self[i] = arg0
+ i += 1
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.rotate(count=1) -> new_ary
+ #
+ # Returns a new array by rotating +self+ so that the element at +count+ is
+ # the first element of the new array.
+ #
+ # If +count+ is negative then it rotates in the opposite direction, starting
+ # from the end of +self+ where +-1+ is the last element.
+ #
+ # a = [ "a", "b", "c", "d" ]
+ # a.rotate #=> ["b", "c", "d", "a"]
+ # a #=> ["a", "b", "c", "d"]
+ # a.rotate(2) #=> ["c", "d", "a", "b"]
+ # a.rotate(-3) #=> ["b", "c", "d", "a"]
+
+ def rotate(count=1)
+ ary = []
+ len = self.length
+
+ if len > 0
+ idx = (count < 0) ? (len - (~count % len) - 1) : (count % len) # rotate count
+ len.times do
+ ary << self[idx]
+ idx += 1
+ idx = 0 if idx > len-1
+ end
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # ary.rotate!(count=1) -> ary
+ #
+ # Rotates +self+ in place so that the element at +count+ comes first, and
+ # returns +self+.
+ #
+ # If +count+ is negative then it rotates in the opposite direction, starting
+ # from the end of the array where +-1+ is the last element.
+ #
+ # a = [ "a", "b", "c", "d" ]
+ # a.rotate! #=> ["b", "c", "d", "a"]
+ # a #=> ["b", "c", "d", "a"]
+ # a.rotate!(2) #=> ["d", "a", "b", "c"]
+ # a.rotate!(-3) #=> ["a", "b", "c", "d"]
+
+ def rotate!(count=1)
+ self.replace(self.rotate(count))
+ end
+
+ ##
+ # call-seq:
+ # ary.delete_if { |item| block } -> ary
+ # ary.delete_if -> Enumerator
+ #
+ # Deletes every element of +self+ for which block evaluates to +true+.
+ #
+ # The array is changed instantly every time the block is called, not after
+ # the iteration is over.
+ #
+ # See also Array#reject!
+ #
+ # If no block is given, an Enumerator is returned instead.
+ #
+ # scores = [ 97, 42, 75 ]
+ # scores.delete_if {|score| score < 80 } #=> [97]
+
+ def delete_if(&block)
+ return to_enum :delete_if unless block
+
+ idx = 0
+ while idx < self.size do
+ if block.call(self[idx])
+ self.delete_at(idx)
+ else
+ idx += 1
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.reject! { |item| block } -> ary or nil
+ # ary.reject! -> Enumerator
+ #
+ # Equivalent to Array#delete_if, deleting elements from +self+ for which the
+ # block evaluates to +true+, but returns +nil+ if no changes were made.
+ #
+ # The array is changed instantly every time the block is called, not after
+ # the iteration is over.
+ #
+ # See also Enumerable#reject and Array#delete_if.
+ #
+ # If no block is given, an Enumerator is returned instead.
+
+ def reject!(&block)
+ return to_enum :reject! unless block
+
+ len = self.size
+ idx = 0
+ while idx < self.size do
+ if block.call(self[idx])
+ self.delete_at(idx)
+ else
+ idx += 1
+ end
+ end
+ if self.size == len
+ nil
+ else
+ self
+ end
+ end
+
+ ##
+ # call-seq:
+ # ary.insert(index, obj...) -> ary
+ #
+ # Inserts the given values before the element with the given +index+.
+ #
+ # Negative indices count backwards from the end of the array, where +-1+ is
+ # the last element.
+ #
+ # a = %w{ a b c d }
+ # a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
+ # a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
+
+ def insert(idx, *args)
+ idx += self.size + 1 if idx < 0
+ self[idx, 0] = args
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.bsearch {|x| block } -> elem
+ #
+ # By using binary search, finds a value from this array which meets
+ # the given condition in O(log n) where n is the size of the array.
+ #
+ # You can use this method in two use cases: a find-minimum mode and
+ # a find-any mode. In either case, the elements of the array must be
+ # monotone (or sorted) with respect to the block.
+ #
+ # In find-minimum mode (this is a good choice for typical use case),
+ # the block must return true or false, and there must be an index i
+ # (0 <= i <= ary.size) so that:
+ #
+ # - the block returns false for any element whose index is less than
+ # i, and
+ # - the block returns true for any element whose index is greater
+ # than or equal to i.
+ #
+ # This method returns the i-th element. If i is equal to ary.size,
+ # it returns nil.
+ #
+ # ary = [0, 4, 7, 10, 12]
+ # ary.bsearch {|x| x >= 4 } #=> 4
+ # ary.bsearch {|x| x >= 6 } #=> 7
+ # ary.bsearch {|x| x >= -1 } #=> 0
+ # ary.bsearch {|x| x >= 100 } #=> nil
+ #
+ # In find-any mode (this behaves like libc's bsearch(3)), the block
+ # must return a number, and there must be two indices i and j
+ # (0 <= i <= j <= ary.size) so that:
+ #
+ # - the block returns a positive number for ary[k] if 0 <= k < i,
+ # - the block returns zero for ary[k] if i <= k < j, and
+ # - the block returns a negative number for ary[k] if
+ # j <= k < ary.size.
+ #
+ # Under this condition, this method returns any element whose index
+ # is within i...j. If i is equal to j (i.e., there is no element
+ # that satisfies the block), this method returns nil.
+ #
+ # ary = [0, 4, 7, 10, 12]
+ # # try to find v such that 4 <= v < 8
+ # ary.bsearch {|x| 1 - (x / 4).truncate } #=> 4 or 7
+ # # try to find v such that 8 <= v < 10
+ # ary.bsearch {|x| 4 - (x / 2).truncate } #=> nil
+ #
+ # You must not mix the two modes at a time; the block must always
+ # return either true/false, or always return a number. It is
+ # undefined which value is actually picked up at each iteration.
+
+ def bsearch(&block)
+ return to_enum :bsearch unless block
+
+ if idx = bsearch_index(&block)
+ self[idx]
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
+ # ary.bsearch_index {|x| block } -> int or nil
+ #
+ # By using binary search, finds an index of a value from this array which
+ # meets the given condition in O(log n) where n is the size of the array.
+ #
+ # It supports two modes, depending on the nature of the block and they are
+ # exactly the same as in the case of #bsearch method with the only difference
+ # being that this method returns the index of the element instead of the
+ # element itself. For more details consult the documentation for #bsearch.
+
+ def bsearch_index(&block)
+ return to_enum :bsearch_index unless block
+
+ low = 0
+ high = size
+ satisfied = false
+
+ while low < high
+ mid = ((low+high)/2).truncate
+ res = block.call self[mid]
+
+ case res
+ when 0 # find-any mode: Found!
+ return mid
+ when Numeric # find-any mode: Continue...
+ in_lower_half = res < 0
+ when true # find-min mode
+ in_lower_half = true
+ satisfied = true
+ when false, nil # find-min mode
+ in_lower_half = false
+ else
+ raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
+ end
+
+ if in_lower_half
+ high = mid
+ else
+ low = mid + 1
+ end
+ end
+
+ satisfied ? low : nil
+ end
+
+ ##
+ # call-seq:
+ # ary.delete_if { |item| block } -> ary
+ # ary.delete_if -> Enumerator
+ #
+ # Deletes every element of +self+ for which block evaluates to +true+.
+ #
+ # The array is changed instantly every time the block is called, not after
+ # the iteration is over.
+ #
+ # See also Array#reject!
+ #
+ # If no block is given, an Enumerator is returned instead.
+ #
+ # scores = [ 97, 42, 75 ]
+ # scores.delete_if {|score| score < 80 } #=> [97]
+
+ def delete_if(&block)
+ return to_enum :delete_if unless block
+
+ idx = 0
+ while idx < self.size do
+ if block.call(self[idx])
+ self.delete_at(idx)
+ else
+ idx += 1
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.keep_if { |item| block } -> ary
+ # ary.keep_if -> Enumerator
+ #
+ # Deletes every element of +self+ for which the given block evaluates to
+ # +false+.
+ #
+ # See also Array#select!
+ #
+ # If no block is given, an Enumerator is returned instead.
+ #
+ # a = [1, 2, 3, 4, 5]
+ # a.keep_if { |val| val > 3 } #=> [4, 5]
+
+ def keep_if(&block)
+ return to_enum :keep_if unless block
+
+ idx = 0
+ len = self.size
+ while idx < self.size do
+ if block.call(self[idx])
+ idx += 1
+ else
+ self.delete_at(idx)
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.select! {|item| block } -> ary or nil
+ # ary.select! -> Enumerator
+ #
+ # Invokes the given block passing in successive elements from +self+,
+ # deleting elements for which the block returns a +false+ value.
+ #
+ # If changes were made, it will return +self+, otherwise it returns +nil+.
+ #
+ # See also Array#keep_if
+ #
+ # If no block is given, an Enumerator is returned instead.
+
+ def select!(&block)
+ return to_enum :select! unless block
+
+ result = []
+ idx = 0
+ len = size
+ while idx < len
+ elem = self[idx]
+ result << elem if block.call(elem)
+ idx += 1
+ end
+ return nil if len == result.size
+ self.replace(result)
+ end
+
+ ##
+ # call-seq:
+ # ary.index(val) -> int or nil
+ # ary.index {|item| block } -> int or nil
+ #
+ # Returns the _index_ of the first object in +ary+ such that the object is
+ # <code>==</code> to +obj+.
+ #
+ # If a block is given instead of an argument, returns the _index_ of the
+ # first object for which the block returns +true+. Returns +nil+ if no
+ # match is found.
+ #
+ # ISO 15.2.12.5.14
+ def index(val=NONE, &block)
+ return to_enum(:find_index, val) if !block && val == NONE
+
+ if block
+ idx = 0
+ len = size
+ while idx < len
+ return idx if block.call self[idx]
+ idx += 1
+ end
+ else
+ return self.__ary_index(val)
+ end
+ nil
+ end
+
+ ##
+ # call-seq:
+ # ary.to_ary -> ary
+ #
+ # Returns +self+.
+ #
+ def to_ary
+ self
+ end
+
+ ##
+ # call-seq:
+ # ary.dig(idx, ...) -> object
+ #
+ # Extracts the nested value specified by the sequence of <i>idx</i>
+ # objects by calling +dig+ at each step, returning +nil+ if any
+ # intermediate step is +nil+.
+ #
+ def dig(idx,*args)
+ n = self[idx]
+ if args.size > 0
+ n&.dig(*args)
+ else
+ n
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/src/array.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/src/array.c
new file mode 100644
index 00000000..e99599b0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/src/array.c
@@ -0,0 +1,244 @@
+#include <mruby.h>
+#include <mruby/value.h>
+#include <mruby/array.h>
+#include <mruby/range.h>
+#include <mruby/hash.h>
+
+/*
+ * call-seq:
+ * ary.assoc(obj) -> new_ary or nil
+ *
+ * Searches through an array whose elements are also arrays
+ * comparing _obj_ with the first element of each contained array
+ * using obj.==.
+ * Returns the first contained array that matches (that
+ * is, the first associated array),
+ * or +nil+ if no match is found.
+ * See also <code>Array#rassoc</code>.
+ *
+ * s1 = [ "colors", "red", "blue", "green" ]
+ * s2 = [ "letters", "a", "b", "c" ]
+ * s3 = "foo"
+ * a = [ s1, s2, s3 ]
+ * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
+ * a.assoc("foo") #=> nil
+ */
+
+static mrb_value
+mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value v, k;
+
+ mrb_get_args(mrb, "o", &k);
+
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
+ if (!mrb_nil_p(v) && RARRAY_LEN(v) > 0 &&
+ mrb_equal(mrb, RARRAY_PTR(v)[0], k))
+ return v;
+ }
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * ary.rassoc(obj) -> new_ary or nil
+ *
+ * Searches through the array whose elements are also arrays. Compares
+ * _obj_ with the second element of each contained array using
+ * <code>==</code>. Returns the first contained array that matches. See
+ * also <code>Array#assoc</code>.
+ *
+ * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
+ * a.rassoc("two") #=> [2, "two"]
+ * a.rassoc("four") #=> nil
+ */
+
+static mrb_value
+mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value v, value;
+
+ mrb_get_args(mrb, "o", &value);
+
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ v = RARRAY_PTR(ary)[i];
+ if (mrb_type(v) == MRB_TT_ARRAY &&
+ RARRAY_LEN(v) > 1 &&
+ mrb_equal(mrb, RARRAY_PTR(v)[1], value))
+ return v;
+ }
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * ary.at(index) -> obj or nil
+ *
+ * Returns the element at _index_. A
+ * negative index counts from the end of +self+. Returns +nil+
+ * if the index is out of range. See also <code>Array#[]</code>.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a.at(0) #=> "a"
+ * a.at(-1) #=> "e"
+ */
+
+static mrb_value
+mrb_ary_at(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int pos;
+ mrb_get_args(mrb, "i", &pos);
+
+ return mrb_ary_entry(ary, pos);
+}
+
+static mrb_value
+mrb_ary_values_at(mrb_state *mrb, mrb_value self)
+{
+ mrb_int argc;
+ mrb_value *argv;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
+}
+
+/*
+ * call-seq:
+ * ary.to_h -> Hash
+ *
+ * Returns the result of interpreting <i>aray</i> as an array of
+ * <tt>[key, value]</tt> paris.
+ *
+ * [[:foo, :bar], [1, 2]].to_h
+ * # => {:foo => :bar, 1 => 2}
+ *
+ */
+
+static mrb_value
+mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mrb_value v, hash;
+
+ hash = mrb_hash_new_capa(mrb, 0);
+
+ for (i = 0; i < RARRAY_LEN(ary); ++i) {
+ mrb_value elt = RARRAY_PTR(ary)[i];
+ v = mrb_check_array_type(mrb, elt);
+
+ if (mrb_nil_p(v)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
+ mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, elt)),
+ mrb_fixnum_value(i)
+ );
+ }
+
+ if (RARRAY_LEN(v) != 2) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
+ mrb_fixnum_value(i),
+ mrb_fixnum_value(RARRAY_LEN(v))
+ );
+ }
+
+ mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
+ }
+
+ return hash;
+}
+
+/*
+ * call-seq:
+ * ary.slice!(index) -> obj or nil
+ * ary.slice!(start, length) -> new_ary or nil
+ * ary.slice!(range) -> new_ary or nil
+ *
+ * Deletes the element(s) given by an +index+ (optionally up to +length+
+ * elements) or by a +range+.
+ *
+ * Returns the deleted object (or objects), or +nil+ if the +index+ is out of
+ * range.
+ *
+ * a = [ "a", "b", "c" ]
+ * a.slice!(1) #=> "b"
+ * a #=> ["a", "c"]
+ * a.slice!(-1) #=> "c"
+ * a #=> ["a"]
+ * a.slice!(100) #=> nil
+ * a #=> ["a"]
+ */
+
+static mrb_value
+mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int i, j, k, len, alen = ARY_LEN(a);
+ mrb_value index;
+ mrb_value val;
+ mrb_value *ptr;
+ mrb_value ary;
+
+ mrb_ary_modify(mrb, a);
+
+ if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
+ switch (mrb_type(index)) {
+ case MRB_TT_RANGE:
+ if (mrb_range_beg_len(mrb, index, &i, &len, alen, TRUE) == 1) {
+ goto delete_pos_len;
+ }
+ else {
+ return mrb_nil_value();
+ }
+ case MRB_TT_FIXNUM:
+ val = mrb_funcall(mrb, self, "delete_at", 1, index);
+ return val;
+ default:
+ val = mrb_funcall(mrb, self, "delete_at", 1, index);
+ return val;
+ }
+ }
+
+ i = mrb_fixnum(index);
+ delete_pos_len:
+ if (i < 0) i += alen;
+ if (i < 0 || alen < i) return mrb_nil_value();
+ if (len < 0) return mrb_nil_value();
+ if (alen == i) return mrb_ary_new(mrb);
+ if (len > alen - i) len = alen - i;
+
+ ary = mrb_ary_new_capa(mrb, len);
+ ptr = ARY_PTR(a);
+ for (j = i, k = 0; k < len; ++j, ++k) {
+ mrb_ary_push(mrb, ary, ptr[j]);
+ }
+
+ ptr += i;
+ for (j = i; j < alen - len; ++j) {
+ *ptr = *(ptr+len);
+ ++ptr;
+ }
+
+ mrb_ary_resize(mrb, self, alen - len);
+ return ary;
+}
+
+void
+mrb_mruby_array_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass * a = mrb->array_class;
+
+ mrb_define_method(mrb, a, "assoc", mrb_ary_assoc, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
+ mrb_define_method(mrb, a, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0));
+ mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ANY());
+}
+
+void
+mrb_mruby_array_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/test/array.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/test/array.rb
new file mode 100644
index 00000000..c0db1b1c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-array-ext/test/array.rb
@@ -0,0 +1,383 @@
+##
+# Array(Ext) Test
+
+assert("Array.try_convert") do
+ assert_nil Array.try_convert(0)
+ assert_nil Array.try_convert(nil)
+ assert_equal [], Array.try_convert([])
+ assert_equal [1,2,3], Array.try_convert([1,2,3])
+end
+
+assert("Array#assoc") do
+ s1 = [ "colors", "red", "blue", "green" ]
+ s2 = [ "letters", "a", "b", "c" ]
+ s3 = "foo"
+ a = [ s1, s2, s3 ]
+
+ assert_equal [ "letters", "a", "b", "c" ], a.assoc("letters")
+ assert_nil a.assoc("foo")
+end
+
+assert("Array#at") do
+ a = [ "a", "b", "c", "d", "e" ]
+ assert_equal "a", a.at(0)
+ assert_equal "e", a.at(-1)
+end
+
+assert("Array#rassoc") do
+ a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
+
+ assert_equal [2, "two"], a.rassoc("two")
+ assert_nil a.rassoc("four")
+end
+
+assert("Array#uniq!") do
+ a = [1, 2, 3, 1]
+ a.uniq!
+ assert_equal [1, 2, 3], a
+
+ b = [ "a", "b", "c" ]
+ assert_nil b.uniq!
+
+ c = [["student","sam"], ["student","george"], ["teacher","matz"]]
+ assert_equal [["student", "sam"], ["teacher", "matz"]], c.uniq! { |s| s.first }
+
+ d = [["student","sam"], ["teacher","matz"]]
+ assert_nil d.uniq! { |s| s.first }
+end
+
+assert("Array#uniq") do
+ a = [1, 2, 3, 1]
+ assert_equal [1, 2, 3], a.uniq
+ assert_equal [1, 2, 3, 1], a
+
+ b = [["student","sam"], ["student","george"], ["teacher","matz"]]
+ assert_equal [["student", "sam"], ["teacher", "matz"]], b.uniq { |s| s.first }
+end
+
+assert("Array#-") do
+ a = [1, 2, 3, 1]
+ b = [1]
+ c = 1
+
+ assert_raise(TypeError) { a - c }
+ assert_equal [2, 3], (a - b)
+ assert_equal [1, 2, 3, 1], a
+end
+
+assert("Array#|") do
+ a = [1, 2, 3, 1]
+ b = [1, 4]
+ c = 1
+
+ assert_raise(TypeError) { a | c }
+ assert_equal [1, 2, 3, 4], (a | b)
+ assert_equal [1, 2, 3, 1], a
+end
+
+assert("Array#&") do
+ a = [1, 2, 3, 1]
+ b = [1, 4]
+ c = 1
+
+ assert_raise(TypeError) { a & c }
+ assert_equal [1], (a & b)
+ assert_equal [1, 2, 3, 1], a
+end
+
+assert("Array#flatten") do
+ assert_equal [1, 2, "3", {4=>5}, :'6'], [1, 2, "3", {4=>5}, :'6'].flatten
+ assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, 4, 5], 6].flatten
+ assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, [4, 5], 6]].flatten
+ assert_equal [1, [2, [3, [4, [5, [6]]]]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(0)
+ assert_equal [1, 2, [3, [4, [5, [6]]]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(1)
+ assert_equal [1, 2, 3, [4, [5, [6]]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(2)
+ assert_equal [1, 2, 3, 4, [5, [6]]], [1, [2, [3, [4, [5, [6]]]]]].flatten(3)
+ assert_equal [1, 2, 3, 4, 5, [6]], [1, [2, [3, [4, [5, [6]]]]]].flatten(4)
+ assert_equal [1, 2, 3, 4, 5, 6], [1, [2, [3, [4, [5, [6]]]]]].flatten(5)
+end
+
+assert("Array#flatten!") do
+ assert_equal [1, 2, 3, 4, 5, 6], [1, 2, [3, [4, 5], 6]].flatten!
+end
+
+assert("Array#compact") do
+ a = [1, nil, "2", nil, :t, false, nil]
+ assert_equal [1, "2", :t, false], a.compact
+ assert_equal [1, nil, "2", nil, :t, false, nil], a
+end
+
+assert("Array#compact!") do
+ a = [1, nil, "2", nil, :t, false, nil]
+ a.compact!
+ assert_equal [1, "2", :t, false], a
+end
+
+assert("Array#fetch") do
+ a = [ 11, 22, 33, 44 ]
+ assert_equal 22, a.fetch(1)
+ assert_equal 44, a.fetch(-1)
+ assert_equal 'cat', a.fetch(4, 'cat')
+ ret = 0
+ a.fetch(100) { |i| ret = i }
+ assert_equal 100, ret
+ assert_raise(IndexError) { a.fetch(100) }
+end
+
+assert("Array#fill") do
+ a = [ "a", "b", "c", "d" ]
+ assert_equal ["x", "x", "x", "x"], a.fill("x")
+ assert_equal ["x", "x", "x", "w"], a.fill("w", -1)
+ assert_equal ["x", "x", "z", "z"], a.fill("z", 2, 2)
+ assert_equal ["y", "y", "z", "z"], a.fill("y", 0..1)
+ assert_equal [0, 1, 4, 9], a.fill { |i| i*i }
+ assert_equal [0, 1, 8, 27], a.fill(-2) { |i| i*i*i }
+ assert_equal [0, 2, 3, 27], a.fill(1, 2) { |i| i+1 }
+ assert_equal [1, 2, 3, 27], a.fill(0..1) { |i| i+1 }
+ assert_raise(ArgumentError) { a.fill }
+
+ assert_equal([0, 1, 2, 3, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, -2, 1))
+ assert_equal([0, 1, 2, 3, -1, -1, -1], [0, 1, 2, 3, 4, 5].fill(-1, -2, 3))
+ assert_equal([0, 1, 2, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3..4))
+ assert_equal([0, 1, 2, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 3...4))
+ assert_equal([0, 1, -1, -1, -1, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2..-2))
+ assert_equal([0, 1, -1, -1, 4, 5], [0, 1, 2, 3, 4, 5].fill(-1, 2...-2))
+ assert_equal([0, 1, 2, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(3..4){|i| i+10})
+ assert_equal([0, 1, 2, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(3...4){|i| i+10})
+ assert_equal([0, 1, 12, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(2..-2){|i| i+10})
+ assert_equal([0, 1, 12, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(2...-2){|i| i+10})
+
+ assert_equal [1, 2, 3, 4, 'x', 'x'], [1, 2, 3, 4, 5, 6].fill('x', -2..-1)
+ assert_equal [1, 2, 3, 4, 'x', 6], [1, 2, 3, 4, 5, 6].fill('x', -2...-1)
+ assert_equal [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6].fill('x', -2...-2)
+ assert_equal [1, 2, 3, 4, 'x', 6], [1, 2, 3, 4, 5, 6].fill('x', -2..-2)
+ assert_equal [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6].fill('x', -2..0)
+end
+
+assert("Array#reverse_each") do
+ a = [ "a", "b", "c", "d" ]
+ b = []
+ a.reverse_each do |i|
+ b << i
+ end
+ assert_equal [ "d", "c", "b", "a" ], b
+
+ if Object.const_defined?(:Enumerator)
+ assert_equal [ "d", "c", "b", "a" ], a.reverse_each.to_a
+ else
+ true
+ end
+end
+
+assert("Array#rotate") do
+ a = ["a", "b", "c", "d"]
+ assert_equal ["b", "c", "d", "a"], a.rotate
+ assert_equal ["a", "b", "c", "d"], a
+ assert_equal ["c", "d", "a", "b"], a.rotate(2)
+ assert_equal ["b", "c", "d", "a"], a.rotate(-3)
+ assert_equal ["c", "d", "a", "b"], a.rotate(10)
+ assert_equal [], [].rotate
+end
+
+assert("Array#rotate!") do
+ a = ["a", "b", "c", "d"]
+ assert_equal ["b", "c", "d", "a"], a.rotate!
+ assert_equal ["b", "c", "d", "a"], a
+ assert_equal ["d", "a", "b", "c"], a.rotate!(2)
+ assert_equal ["a", "b", "c", "d"], a.rotate!(-3)
+ assert_equal ["c", "d", "a", "b"], a.rotate(10)
+ assert_equal [], [].rotate!
+end
+
+assert("Array#delete_if") do
+ a = [1, 2, 3, 4, 5]
+ assert_equal [1, 2, 3, 4, 5], a.delete_if { false }
+ assert_equal [1, 2, 3, 4, 5], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [], a.delete_if { true }
+ assert_equal [], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [1, 2, 3], a.delete_if { |i| i > 3 }
+ assert_equal [1, 2, 3], a
+end
+
+assert("Array#reject!") do
+ a = [1, 2, 3, 4, 5]
+ assert_nil a.reject! { false }
+ assert_equal [1, 2, 3, 4, 5], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [], a.reject! { true }
+ assert_equal [], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [1, 2, 3], a.reject! { |val| val > 3 }
+ assert_equal [1, 2, 3], a
+end
+
+assert("Array#insert") do
+ a = ["a", "b", "c", "d"]
+ assert_equal ["a", "b", 99, "c", "d"], a.insert(2, 99)
+ assert_equal ["a", "b", 99, "c", 1, 2, 3, "d"], a.insert(-2, 1, 2, 3)
+
+ b = ["a", "b", "c", "d"]
+ assert_equal ["a", "b", "c", "d", nil, nil, 99], b.insert(6, 99)
+end
+
+assert("Array#bsearch") do
+ # Find minimum mode
+ a = [0, 2, 4]
+ assert_equal 0, a.bsearch{ |x| x >= -1 }
+ assert_equal 0, a.bsearch{ |x| x >= 0 }
+ assert_equal 2, a.bsearch{ |x| x >= 1 }
+ assert_equal 2, a.bsearch{ |x| x >= 2 }
+ assert_equal 4, a.bsearch{ |x| x >= 3 }
+ assert_equal 4, a.bsearch{ |x| x >= 4 }
+ assert_nil a.bsearch{ |x| x >= 5 }
+
+ # Find any mode
+ a = [0, 4, 8]
+ def between(lo, x, hi)
+ if x < lo
+ 1
+ elsif x > hi
+ -1
+ else
+ 0
+ end
+ end
+ assert_nil a.bsearch{ |x| between(-3, x, -1) }
+ assert_equal 0, a.bsearch{ |x| between(-1, x, 1) }
+ assert_nil a.bsearch{ |x| between( 1, x, 3) }
+ assert_equal 4, a.bsearch{ |x| between( 3, x, 5) }
+ assert_nil a.bsearch{ |x| between( 5, x, 7) }
+ assert_equal 8, a.bsearch{ |x| between( 7, x, 9) }
+ assert_nil a.bsearch{ |x| between( 9, x, 11) }
+
+ assert_equal 0, a.bsearch{ |x| between( 0, x, 3) }
+ assert_equal 4, a.bsearch{ |x| between( 0, x, 4) }
+ assert_equal 4, a.bsearch{ |x| between( 4, x, 8) }
+ assert_equal 8, a.bsearch{ |x| between( 5, x, 8) }
+
+ # Invalid block result
+ assert_raise TypeError, 'invalid block result (must be numeric, true, false or nil)' do
+ a.bsearch{ 'I like to watch the world burn' }
+ end
+end
+
+assert("Array#bsearch_index") do
+ # tested through Array#bsearch
+end
+
+assert("Array#delete_if") do
+ a = [1, 2, 3, 4, 5]
+ assert_equal [1, 2, 3, 4, 5], a.delete_if { false }
+ assert_equal [1, 2, 3, 4, 5], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [], a.delete_if { true }
+ assert_equal [], a
+
+ a = [ 1, 2, 3, 4, 5 ]
+ assert_equal [1, 2, 3], a.delete_if { |val| val > 3 }
+end
+
+assert("Array#keep_if") do
+ a = [1, 2, 3, 4, 5]
+ assert_equal [1, 2, 3, 4, 5], a.keep_if { true }
+ assert_equal [1, 2, 3, 4, 5], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [], a.keep_if { false }
+ assert_equal [], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [4, 5], a.keep_if { |val| val > 3 }
+ assert_equal [4, 5], a
+end
+
+assert("Array#select!") do
+ a = [1, 2, 3, 4, 5]
+ assert_nil a.select! { true }
+ assert_equal [1, 2, 3, 4, 5], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [], a.select! { false }
+ assert_equal [], a
+
+ a = [1, 2, 3, 4, 5]
+ assert_equal [4, 5], a.select! { |val| val > 3 }
+ assert_equal [4, 5], a
+end
+
+assert('Array#values_at') do
+ a = %w{red green purple white none}
+
+ assert_equal %w{red purple none}, a.values_at(0, 2, 4)
+ assert_equal ['green', 'white', nil, nil], a.values_at(1, 3, 5, 7)
+ assert_equal ['none', 'white', 'white', nil], a.values_at(-1, -2, -2, -7)
+ assert_equal ['none', nil, nil, 'red', 'green', 'purple'], a.values_at(4..6, 0...3)
+ assert_raise(TypeError) { a.values_at 'tt' }
+end
+
+assert('Array#to_h') do
+ assert_equal({}, [].to_h)
+ assert_equal({a: 1, b:2}, [[:a, 1], [:b, 2]].to_h)
+
+ assert_raise(TypeError) { [1].to_h }
+ assert_raise(ArgumentError) { [[1]].to_h }
+end
+
+assert('Array#to_h (Modified)') do
+ class A
+ def to_ary
+ $a.clear
+ nil
+ end
+ end
+ $a = [A.new]
+ assert_raise(TypeError) { $a.to_h }
+end
+
+assert("Array#index (block)") do
+ assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
+ assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
+end
+
+assert("Array#to_ary") do
+ assert_equal [], [].to_ary
+ assert_equal [1,2,3], [1,2,3].to_ary
+end
+
+assert("Array#dig") do
+ h = [[[1]], 0]
+ assert_equal(1, h.dig(0, 0, 0))
+ assert_nil(h.dig(2, 0))
+ assert_raise(TypeError) {h.dig(:a)}
+end
+
+assert("Array#slice!") do
+ a = [1, 2, 3]
+ b = a.slice!(0)
+ c = [1, 2, 3, 4, 5]
+ d = c.slice!(0, 2)
+ e = [1, 2, 3, 4, 5]
+ f = e.slice!(1..3)
+ g = [1, 2, 3]
+ h = g.slice!(-1)
+ i = [1, 2, 3]
+ j = i.slice!(0, -1)
+
+ assert_equal(a, [2, 3])
+ assert_equal(b, 1)
+ assert_equal(c, [3, 4, 5])
+ assert_equal(d, [1, 2])
+ assert_equal(e, [1, 5])
+ assert_equal(f, [2, 3, 4])
+ assert_equal(g, [1, 2])
+ assert_equal(h, 3)
+ assert_equal(i, [1, 2, 3])
+ assert_equal(j, nil)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb
new file mode 100644
index 00000000..26f3138a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb
@@ -0,0 +1,286 @@
+require 'open3'
+require 'tempfile'
+
+class BinTest_MrubyBinDebugger
+ @debug1=false
+ @debug2=true
+ @debug3=true
+ def self.test(rubysource, testcase)
+ script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
+
+ # .rb
+ script.write rubysource
+ script.flush
+
+ # compile
+ `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"`
+
+ # add mrdb quit
+ testcase << {:cmd=>"quit"}
+
+ stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
+
+ ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
+ o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
+
+ exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
+ unexp_vals = testcase.map{|t| t.fetch(:unexp, nil)}
+
+if @debug1
+ o.split("\n").each_with_index do |i,actual|
+ p [i,actual]
+ end
+end
+ # compare actual / expected
+ o.split("\n").each do |actual|
+ next if actual.empty?
+ exp = exp_vals.shift
+if @debug2
+ a = true
+ a = actual.include?(exp) unless exp.nil?
+ p [actual, exp] unless a
+end
+ assert_true actual.include?(exp) unless exp.nil?
+ end
+ # compare actual / unexpected
+ o.split("\n").each do |actual|
+ next if actual.empty?
+ unexp = unexp_vals.shift
+if @debug3
+ a = false
+ a = actual.include?(unexp) unless unexp.nil?
+ p [actual, unexp] if a
+end
+ assert_false actual.include?(unexp) unless unexp.nil?
+ end
+ end
+ end
+end
+
+INVCMD = "invalid command"
+
+assert('mruby-bin-debugger(mrdb) command line') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ str = ""
+ 103.times {
+ str += "1234567890"
+ }
+ cmd = "p a=#{str}"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1023], :unexp=>'command line too long.'}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1024], :unexp=>'command line too long.'}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1025], :exp=>'command line too long.'}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "break"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"b", :unexp=>INVCMD}
+ tc << {:cmd=>"br", :unexp=>INVCMD}
+ tc << {:cmd=>"brea", :unexp=>INVCMD}
+ tc << {:cmd=>"break", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"bl", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"breaka", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "continue"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"c", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"co", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continu", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continue", :unexp=>INVCMD}])
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"cn", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continuee", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "delete"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"d 1", :unexp=>INVCMD}
+ tc << {:cmd=>"de 1", :unexp=>INVCMD}
+ tc << {:cmd=>"delet 1", :unexp=>INVCMD}
+ tc << {:cmd=>"delete 1", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"dd 1", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"deletee 1", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "disable"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"dis", :unexp=>INVCMD}
+ tc << {:cmd=>"disa", :unexp=>INVCMD}
+ tc << {:cmd=>"disabl", :unexp=>INVCMD}
+ tc << {:cmd=>"disable", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"di", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"disb", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"disablee", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "enable"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"en", :unexp=>INVCMD}
+ tc << {:cmd=>"ena", :unexp=>INVCMD}
+ tc << {:cmd=>"enabl", :unexp=>INVCMD}
+ tc << {:cmd=>"enable", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"e", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"enb", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"enablee", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "eval"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"ev", :unexp=>INVCMD}
+ tc << {:cmd=>"eva", :unexp=>INVCMD}
+ tc << {:cmd=>"eval", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"e", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"evl", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"evall", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "help"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"h", :unexp=>INVCMD}
+ tc << {:cmd=>"he", :unexp=>INVCMD}
+ tc << {:cmd=>"hel", :unexp=>INVCMD}
+ tc << {:cmd=>"help", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"hl", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"helpp", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "info breakpoints"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"i b", :unexp=>INVCMD}
+ tc << {:cmd=>"in b", :unexp=>INVCMD}
+ tc << {:cmd=>"i br", :unexp=>INVCMD}
+ tc << {:cmd=>"inf breakpoint", :unexp=>INVCMD}
+ tc << {:cmd=>"info breakpoints", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ii b", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"i bb", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"infoo breakpoints", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"info breakpointss", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "list"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"l", :unexp=>INVCMD}
+ tc << {:cmd=>"li", :unexp=>INVCMD}
+ tc << {:cmd=>"lis", :unexp=>INVCMD}
+ tc << {:cmd=>"list", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ll", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"listt", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "print"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p", :unexp=>INVCMD}
+ tc << {:cmd=>"pr", :unexp=>INVCMD}
+ tc << {:cmd=>"prin", :unexp=>INVCMD}
+ tc << {:cmd=>"print", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"pp", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"printt", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "quit"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"q", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qu", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qui", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"quit", :unexp=>INVCMD}])
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qq", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"quitt", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "run"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"r", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ru", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"run", :unexp=>INVCMD}])
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"rr", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"runn", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "step"') do
+ # ruby source
+ src = <<"SRC"
+while true
+ foo = 'foo'
+end
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s", :unexp=>INVCMD}
+ tc << {:cmd=>"st", :unexp=>INVCMD}
+ tc << {:cmd=>"ste", :unexp=>INVCMD}
+ tc << {:cmd=>"step", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ss", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"stepp", :exp=>INVCMD}])
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb
new file mode 100644
index 00000000..1bc96c47
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb
@@ -0,0 +1,701 @@
+require 'open3'
+require 'tempfile'
+
+class BinTest_MrubyBinDebugger
+ @debug1=false
+ @debug2=true
+ def self.test(rubysource, testcase)
+ script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
+
+ # .rb
+ script.write rubysource
+ script.flush
+
+ # compile
+ `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"`
+
+ # add mrdb quit
+ testcase << {:cmd=>"quit"}
+
+ stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
+
+ ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
+ o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
+
+ exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
+=begin
+if @debug1
+ o.split("\n").each_with_index do |i,actual|
+ p [i,actual]
+ end
+end
+ # compare actual / expected
+ o.split("\n").each do |actual|
+ next if actual.empty?
+ exp = exp_vals.shift
+if @debug2
+ a = true
+ a = actual.include?(exp) unless exp.nil?
+ p [actual, exp] unless a
+end
+ assert_true actual.include?(exp) unless exp.nil?
+ end
+=end
+ idx = 0
+ exp_vals.each do |exp|
+ next if exp.nil?
+ idx = o.index(exp, idx)
+ assert_false idx.nil?
+ break unless idx
+ idx += 1
+ end
+ end
+ end
+end
+
+assert('mruby-bin-debugger(print) invalid arguments') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p", :exp=>"Parameter not specified."}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) nomal') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = foo
+baz = bar
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p (1+2)", :exp=>'$1 = 3'}
+ tc << {:cmd=>"p foo", :exp=>'$2 = "foo"'}
+ tc << {:cmd=>"p foo*=2", :exp=>'$3 = "foofoo"'}
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p bar", :exp=>'$4 = "foofoo"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) error') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'}
+ tc << {:cmd=>"p bar", :exp=>'$2 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+# Kernel#instance_eval(string) does't work multiple statements.
+=begin
+assert('mruby-bin-debugger(print) multiple statements') do
+ # ruby source
+ src = <<"SRC"
+x = 0
+y = 0
+z = 0
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s",}
+ tc << {:cmd=>"p x=1;x+=2", :exp=>"3"}
+ tc << {:cmd=>"s",}
+ tc << {:cmd=>"p x", :exp=>"3"}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+=end
+
+assert('mruby-bin-debugger(print) scope:top') do
+ # ruby source (bp is break point)
+ src = "bp=nil\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p self", :exp=>'$1 = main'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:class') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestClassScope
+ bp = nil
+end
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p self", :exp=>'$1 = TestClassScope'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:module') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestModuleScope
+ bp = nil
+end
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p self", :exp=>'$1 = TestModuleScope'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:instance method') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestMethodScope
+ def m
+ bp = nil
+ end
+end
+TestMethodScope.new.m
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 3"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p self", :exp=>'$1 = #<TestMethodScope:'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:class method') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestClassMethodScope
+ def self.cm
+ bp = nil
+ end
+end
+TestClassMethodScope.cm
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 3"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p self", :exp=>'$1 = TestClassMethodScope'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:block') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+1.times do
+ bp = nil
+end
+class TestBlockScope
+ 1.times do
+ bp = nil
+ end
+ def m
+ 1.times do
+ bp = nil
+ end
+ end
+end
+TestBlockScope.new.m
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 2"}
+ tc << {:cmd=>"b 6"}
+ tc << {:cmd=>"b 10"}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p self", :exp=>'$1 = main'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p self", :exp=>'$2 = TestBlockScope'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p self", :exp=>'$3 = #<TestBlockScope:'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) same name:local variabe') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+lv = 'top'
+class TestLocalVariableName
+ lv = 'class'
+ def m
+ lv = 'instance method'
+ bp = nil
+ end
+ bp = nil
+end
+TestLocalVariableName.new.m
+bp = nil
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 6"}
+ tc << {:cmd=>"b 8"}
+ tc << {:cmd=>"b 11"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p lv", :exp=>'$1 = "class"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p lv", :exp=>'$2 = "instance method"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p lv", :exp=>'$3 = "top"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) same name:instance variabe') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+@iv = 'top'
+class TestInstanceVariableName
+ def initialize(v)
+ @iv = v
+ end
+ def m
+ bp = nil
+ end
+end
+i1 = TestInstanceVariableName.new('instance1')
+i2 = TestInstanceVariableName.new('instance2')
+i1.m
+i2.m
+bp = nil
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 7"}
+ tc << {:cmd=>"b 14"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p @iv", :exp=>'$1 = "instance1"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p @iv", :exp=>'$2 = "instance2"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p @iv", :exp=>'$3 = "top"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+# Kernel#instance_eval(string) does't work const.
+=begin
+assert('mruby-bin-debugger(print) same name:const') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+CONST='top'
+class TestConstNameSuperClass
+ CONST='super class'
+ def m
+ bp = nil
+ end
+end
+class TestConstNameSubClass < TestConstNameSuperClass
+ CONST='sub class'
+ def m
+ bp = nil
+ end
+end
+
+TestConstNameSuperClass.new.m()
+TestConstNameSubClass.new.m()
+bp = nil
+SRC
+
+ # todo: wait for 'break' to be implimented
+ tc = []
+ 9.times { tc << {:cmd=>"s"} }
+ tc << {:cmd=>"p CONST", :exp=>"super class"}
+ 3.times { tc << {:cmd=>"s"} }
+ tc << {:cmd=>"p CONST", :exp=>"sub class"}
+ 1.times { tc << {:cmd=>"s"} }
+ tc << {:cmd=>"p CONST", :exp=>"top"}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+=end
+
+assert('mruby-bin-debugger(print) Literal:Numeric') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p 100", :exp=>'$1 = 100'}
+ tc << {:cmd=>"p -0b100", :exp=>'$2 = -4'}
+ tc << {:cmd=>"p +0100", :exp=>'$3 = 64'}
+ tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'}
+ tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'}
+ tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000}"}
+ tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000}"}
+
+ tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'}
+ tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'}
+ tc << {:cmd=>"p +12.000", :exp=>'$10 = 12.0'}
+ tc << {:cmd=>"p 1e4", :exp=>'$11 = 10000.0'}
+ tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:String') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p "str"', :exp=>'$1 = "str"'}
+ tc << {:cmd=>'p "s\tt\rr\n"', :exp=>'$2 = "s\\tt\\rr\\n"'}
+ tc << {:cmd=>'p "\C-a\C-z"', :exp=>'$3 = "\\001\\032"'}
+ tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'}
+
+ tc << {:cmd=>'p \'str\'', :exp=>'$5 = "str"'}
+ tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'}
+ tc << {:cmd=>'p \'\\C-a\\C-z\'', :exp=>'$7 = "\\\\C-a\\\\C-z"'}
+ tc << {:cmd=>'p \'#{foo+bar}\'', :exp=>'$8 = "#{foo+bar}"'}
+
+ tc << {:cmd=>'p %!str!', :exp=>'$9 = "str"'}
+ tc << {:cmd=>'p %!s\tt\rr\n!', :exp=>'$10 = "s\\tt\\rr\\n"'}
+ tc << {:cmd=>'p %!\C-a\C-z!', :exp=>'$11 = "\\001\\032"'}
+ tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'}
+
+ tc << {:cmd=>'p %Q!str!', :exp=>'$13 = "str"'}
+ tc << {:cmd=>'p %Q!s\tt\rr\n!', :exp=>'$14 = "s\\tt\\rr\\n"'}
+ tc << {:cmd=>'p %Q!\C-a\C-z!', :exp=>'$15 = "\\001\\032"'}
+ tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'}
+
+ tc << {:cmd=>'p %q!str!', :exp=>'$17 = "str"'}
+ tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'}
+ tc << {:cmd=>'p %q!\\C-a\\C-z!', :exp=>'$19 = "\\\\C-a\\\\C-z"'}
+ tc << {:cmd=>'p %q!#{foo+bar}!', :exp=>'$20 = "#{foo+bar}"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Array') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p []', :exp=>'$1 = []'}
+ tc << {:cmd=>'p [ 5, 12, 8, 10, ]', :exp=>'$2 = [5, 12, 8, 10]'}
+ tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]', :exp=>'$3 = [1, 2.5, "foobar"]'}
+ tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "#{foo}"]'}
+ tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Hash') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p {}', :exp=>'$1 = {}'}
+ tc << {:cmd=>'p {"one"=>1,"two"=>2}', :exp=>'$2 = {"one"=>1, "two"=>2}'}
+ tc << {:cmd=>'p {:eins=>"1", :zwei=>"2", }', :exp=>'$3 = {:eins=>"1", :zwei=>"2"}'}
+ tc << {:cmd=>'p {uno:"one", dos: 2}', :exp=>'$4 = {:uno=>"one", :dos=>2}'}
+ tc << {:cmd=>'p {"one"=>1, :zwei=>2, tres:3}', :exp=>'$5 = {"one"=>1, :zwei=>2, :tres=>3}'}
+ tc << {:cmd=>'p {:foo=>"#{foo}",:bar=>"#{bar}"}', :exp=>'$6 = {:foo=>"foo", :bar=>"bar"}'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Range') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>'p 1..10', :exp=>'$1 = 1..10'}
+ tc << {:cmd=>'p 1...10', :exp=>'$2 = 1...10'}
+ tc << {:cmd=>'p 100..10', :exp=>'$3 = 100..10'}
+ tc << {:cmd=>'p 1 ... 10', :exp=>'$4 = 1...10'}
+
+ tc << {:cmd=>'p "1" .. "9"', :exp=>'$5 = "1".."9"'}
+ tc << {:cmd=>'p "A" ... "Z"', :exp=>'$6 = "A"..."Z"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Symbol') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p :sym', :exp=>'$1 = :sym'}
+ tc << {:cmd=>'p :"sd"', :exp=>'$2 = :sd'}
+ tc << {:cmd=>"p :'ss'", :exp=>'$3 = :ss'}
+ tc << {:cmd=>'p :"123"', :exp=>'$4 = :"123"'}
+ tc << {:cmd=>'p :"#{foo} baz"', :exp=>'$5 = :"foo baz"'}
+ tc << {:cmd=>'p %s!symsym!', :exp=>'$6 = :symsym'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Unary operation') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>'p +10', :exp=>'$1 = 10'}
+ tc << {:cmd=>'p -100', :exp=>'$2 = -100'}
+ tc << {:cmd=>'p !true', :exp=>'$3 = false'}
+ tc << {:cmd=>'p !false', :exp=>'$4 = true'}
+ tc << {:cmd=>'p !nil', :exp=>'$5 = true'}
+ tc << {:cmd=>'p !1', :exp=>'$6 = false'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Binary operation') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, 8
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a+1', :exp=>'$1 = 2'}
+ tc << {:cmd=>'p 2-b', :exp=>'$2 = -3'}
+ tc << {:cmd=>'p c * 3', :exp=>'$3 = 24'}
+ tc << {:cmd=>'p a/b', :exp=>'$4 = 0.2'}
+ tc << {:cmd=>'p c%b', :exp=>'$5 = 3'}
+ tc << {:cmd=>'p 2**10', :exp=>'$6 = 1024'}
+ tc << {:cmd=>'p ~3', :exp=>'$7 = -4'}
+
+ tc << {:cmd=>'p 1<<2', :exp=>'$8 = 4'}
+ tc << {:cmd=>'p 64>>5', :exp=>'$9 = 2'}
+
+ tc << {:cmd=>'p a|c', :exp=>'$10 = 9'}
+ tc << {:cmd=>'p a&b', :exp=>'$11 = 1'}
+ tc << {:cmd=>'p a^b', :exp=>'$12 = 4'}
+
+ tc << {:cmd=>'p a>b', :exp=>'$13 = false'}
+ tc << {:cmd=>'p a<b', :exp=>'$14 = true'}
+ tc << {:cmd=>'p b>=5', :exp=>'$15 = true'}
+ tc << {:cmd=>'p b<=5', :exp=>'$16 = true'}
+
+ tc << {:cmd=>'p "A"<=>"B"', :exp=>'$17 = -1'}
+ tc << {:cmd=>'p "A"=="B"', :exp=>'$18 = false'}
+ tc << {:cmd=>'p "A"==="B"', :exp=>'$19 = false'}
+ tc << {:cmd=>'p "A"!="B"', :exp=>'$20 = true'}
+
+ tc << {:cmd=>'p false || true', :exp=>'$21 = true'}
+ tc << {:cmd=>'p false && true', :exp=>'$22 = false'}
+
+ tc << {:cmd=>'p not nil', :exp=>'$23 = true'}
+ tc << {:cmd=>'p false or true', :exp=>'$24 = true'}
+ tc << {:cmd=>'p false and true', :exp=>'$25 = false'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Ternary operation') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p (a < b) ? a : b', :exp=>'$1 = 1'}
+ tc << {:cmd=>'p (a > b) ? a : b', :exp=>'$2 = 5'}
+ tc << {:cmd=>'p true ? "true" : "false"', :exp=>'$3 = "true"'}
+ tc << {:cmd=>'p false ? "true" : "false"', :exp=>'$4 = "false"'}
+ tc << {:cmd=>'p nil ? "true" : "false"', :exp=>'$5 = "false"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:simple') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a=2', :exp=>'$1 = 2'}
+ tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'}
+
+ tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'}
+ tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:self') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'}
+ tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'}
+ tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'}
+ tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'}
+ tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'}
+
+ tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'}
+ tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'}
+
+ tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'}
+ tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'}
+
+ tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'}
+ tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'}
+ tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'}
+ tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
+
+ tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
+ tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:multiple') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a,b=[10,20]', :exp=>'$1 = [10, 20]'}
+ tc << {:cmd=>'p [a,b,c]', :exp=>'$2 = [10, 20, -10]'}
+
+ tc << {:cmd=>'p foo,bar=["FOO","BAR","BAZ"]', :exp=>'$3 = ["FOO", "BAR", "BAZ"]'}
+ tc << {:cmd=>'p [foo,bar,baz]', :exp=>'$4 = ["FOO", "BAR", "baz"]'}
+
+ tc << {:cmd=>'p a,foo=foo,a', :exp=>'$5 = ["FOO", 10]'}
+ tc << {:cmd=>'p [a,foo]', :exp=>'$6 = ["FOO", 10]'}
+
+# tc << {:cmd=>'p a,*b=[123, 456, 789]'}
+# tc << {:cmd=>'p [a,b]', :exp=>'[123, [456, 789]]'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:self') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'}
+ tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'}
+ tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'}
+ tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'}
+ tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'}
+
+ tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'}
+ tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'}
+
+ tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'}
+ tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'}
+
+ tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'}
+ tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'}
+ tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'}
+ tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
+
+ tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
+ tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake
new file mode 100644
index 00000000..764f431a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake
@@ -0,0 +1,9 @@
+MRuby::Gem::Specification.new('mruby-bin-debugger') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mruby debugger command'
+
+ spec.add_dependency('mruby-eval', :core => 'mruby-eval')
+
+ spec.bins = %w(mrdb)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
new file mode 100644
index 00000000..dead4b2a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
@@ -0,0 +1,507 @@
+/*
+** apibreak.c
+**
+*/
+
+#include <string.h>
+#include <mruby.h>
+#include <mruby/irep.h>
+#include "mrdb.h"
+#include <mruby/debug.h>
+#include <mruby/opcode.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/variable.h>
+#include "mrdberror.h"
+#include "apibreak.h"
+
+#define MAX_BREAKPOINTNO (MAX_BREAKPOINT * 1024)
+#define MRB_DEBUG_BP_FILE_OK (0x0001)
+#define MRB_DEBUG_BP_LINENO_OK (0x0002)
+
+static uint16_t
+check_lineno(mrb_irep_debug_info_file *info_file, uint16_t lineno)
+{
+ uint32_t count = info_file->line_entry_count;
+ uint16_t l_idx;
+
+ if (info_file->line_type == mrb_debug_line_ary) {
+ for (l_idx = 0; l_idx < count; ++l_idx) {
+ if (lineno == info_file->lines.ary[l_idx]) {
+ return lineno;
+ }
+ }
+ }
+ else {
+ for (l_idx = 0; l_idx < count; ++l_idx) {
+ if (lineno == info_file->lines.flat_map[l_idx].line) {
+ return lineno;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int32_t
+get_break_index(mrb_debug_context *dbg, uint32_t bpno)
+{
+ uint32_t i;
+ int32_t index;
+ char hit = FALSE;
+
+ for(i = 0 ; i < dbg->bpnum; i++) {
+ if (dbg->bp[i].bpno == bpno) {
+ hit = TRUE;
+ index = i;
+ break;
+ }
+ }
+
+ if (hit == FALSE) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ return index;
+}
+
+static void
+free_breakpoint(mrb_state *mrb, mrb_debug_breakpoint *bp)
+{
+ switch(bp->type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ mrb_free(mrb, (void*)bp->point.linepoint.file);
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ mrb_free(mrb, (void*)bp->point.methodpoint.method_name);
+ if (bp->point.methodpoint.class_name != NULL) {
+ mrb_free(mrb, (void*)bp->point.methodpoint.class_name);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static uint16_t
+check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
+{
+ mrb_irep_debug_info_file *info_file;
+ uint16_t result = 0;
+ uint16_t f_idx;
+ uint16_t fix_lineno;
+ uint16_t i;
+
+ for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
+ info_file = irep->debug_info->files[f_idx];
+ if (!strcmp(info_file->filename, file)) {
+ result = MRB_DEBUG_BP_FILE_OK;
+
+ fix_lineno = check_lineno(info_file, lineno);
+ if (fix_lineno != 0) {
+ return result | MRB_DEBUG_BP_LINENO_OK;
+ }
+ }
+ for (i=0; i < irep->rlen; ++i) {
+ result |= check_file_lineno(irep->reps[i], file, lineno);
+ if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
+ return result;
+ }
+ }
+ }
+ return result;
+}
+
+static int32_t
+compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
+{
+ const char* class_name;
+ const char* method_name;
+ struct RProc* m;
+ struct RClass* sc;
+ const char* sn;
+ mrb_sym ssym;
+ mrb_debug_methodpoint *method_p;
+ mrb_bool is_defined;
+
+ method_name = mrb_sym2name(mrb, method_sym);
+
+ method_p = &bp->point.methodpoint;
+ if (strcmp(method_p->method_name, method_name) == 0) {
+ class_name = mrb_class_name(mrb, class_obj);
+ if (class_name == NULL) {
+ if (method_p->class_name == NULL) {
+ return bp->bpno;
+ }
+ }
+ else if (method_p->class_name != NULL) {
+ m = mrb_method_search_vm(mrb, &class_obj, method_sym);
+ if (m == NULL) {
+ return MRB_DEBUG_OK;
+ }
+ if (MRB_PROC_CFUNC_P(m)) {
+ *isCfunc = TRUE;
+ }
+
+ is_defined = mrb_class_defined(mrb, method_p->class_name);
+ if (is_defined == FALSE) {
+ return MRB_DEBUG_OK;
+ }
+
+ sc = mrb_class_get(mrb, method_p->class_name);
+ ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
+ m = mrb_method_search_vm(mrb, &sc, ssym);
+ if (m == NULL) {
+ return MRB_DEBUG_OK;
+ }
+
+ class_name = mrb_class_name(mrb, class_obj);
+ sn = mrb_class_name(mrb, sc);
+ if (strcmp(sn, class_name) == 0) {
+ return bp->bpno;
+ }
+ }
+ }
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t lineno)
+{
+ int32_t index;
+ char* set_file;
+ uint16_t result;
+
+ if ((mrb == NULL)||(dbg == NULL)||(file == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (dbg->bpnum >= MAX_BREAKPOINT) {
+ return MRB_DEBUG_BREAK_NUM_OVER;
+ }
+
+ if (dbg->next_bpno > MAX_BREAKPOINTNO) {
+ return MRB_DEBUG_BREAK_NO_OVER;
+ }
+
+ /* file and lineno check (line type mrb_debug_line_ary only.) */
+ result = check_file_lineno(dbg->root_irep, file, lineno);
+ if (result == 0) {
+ return MRB_DEBUG_BREAK_INVALID_FILE;
+ }
+ else if (result == MRB_DEBUG_BP_FILE_OK) {
+ return MRB_DEBUG_BREAK_INVALID_LINENO;
+ }
+
+ set_file = mrb_malloc(mrb, strlen(file) + 1);
+
+ index = dbg->bpnum;
+ dbg->bp[index].bpno = dbg->next_bpno;
+ dbg->next_bpno++;
+ dbg->bp[index].enable = TRUE;
+ dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE;
+ dbg->bp[index].point.linepoint.lineno = lineno;
+ dbg->bpnum++;
+
+ strncpy(set_file, file, strlen(file) + 1);
+
+ dbg->bp[index].point.linepoint.file = set_file;
+
+ return dbg->bp[index].bpno;
+}
+
+int32_t
+mrb_debug_set_break_method(mrb_state *mrb, mrb_debug_context *dbg, const char *class_name, const char *method_name)
+{
+ int32_t index;
+ char* set_class;
+ char* set_method;
+
+ if ((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (dbg->bpnum >= MAX_BREAKPOINT) {
+ return MRB_DEBUG_BREAK_NUM_OVER;
+ }
+
+ if (dbg->next_bpno > MAX_BREAKPOINTNO) {
+ return MRB_DEBUG_BREAK_NO_OVER;
+ }
+
+ if (class_name != NULL) {
+ set_class = mrb_malloc(mrb, strlen(class_name) + 1);
+ strncpy(set_class, class_name, strlen(class_name) + 1);
+ }
+ else {
+ set_class = NULL;
+ }
+
+ set_method = mrb_malloc(mrb, strlen(method_name) + 1);
+
+ strncpy(set_method, method_name, strlen(method_name) + 1);
+
+ index = dbg->bpnum;
+ dbg->bp[index].bpno = dbg->next_bpno;
+ dbg->next_bpno++;
+ dbg->bp[index].enable = TRUE;
+ dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD;
+ dbg->bp[index].point.methodpoint.method_name = set_method;
+ dbg->bp[index].point.methodpoint.class_name = set_class;
+ dbg->bpnum++;
+
+ return dbg->bp[index].bpno;
+}
+
+int32_t
+mrb_debug_get_breaknum(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ return dbg->bpnum;
+}
+
+int32_t
+mrb_debug_get_break_all(mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint *bp)
+{
+ uint32_t get_size = 0;
+
+ if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (dbg->bpnum >= size) {
+ get_size = size;
+ }
+ else {
+ get_size = dbg->bpnum;
+ }
+
+ memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size);
+
+ return get_size;
+}
+
+int32_t
+mrb_debug_get_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno, mrb_debug_breakpoint *bp)
+{
+ int32_t index;
+
+ if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ bp->bpno = dbg->bp[index].bpno;
+ bp->enable = dbg->bp[index].enable;
+ bp->point = dbg->bp[index].point;
+ bp->type = dbg->bp[index].type;
+
+ return 0;
+}
+
+int32_t
+mrb_debug_delete_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
+{
+ uint32_t i;
+ int32_t index;
+
+ if ((mrb == NULL) ||(dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ free_breakpoint(mrb, &dbg->bp[index]);
+
+ for(i = index ; i < dbg->bpnum; i++) {
+ if ((i + 1) == dbg->bpnum) {
+ memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint));
+ }
+ else {
+ memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint));
+ }
+ }
+
+ dbg->bpnum--;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_delete_break_all(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ for(i = 0 ; i < dbg->bpnum ; i++) {
+ free_breakpoint(mrb, &dbg->bp[i]);
+ }
+
+ dbg->bpnum = 0;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_enable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
+{
+ int32_t index = 0;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ dbg->bp[index].enable = TRUE;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_enable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ for(i = 0 ; i < dbg->bpnum; i++) {
+ dbg->bp[i].enable = TRUE;
+ }
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_disable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
+{
+ int32_t index = 0;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ dbg->bp[index].enable = FALSE;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ for(i = 0 ; i < dbg->bpnum; i++) {
+ dbg->bp[i].enable = FALSE;
+ }
+
+ return MRB_DEBUG_OK;
+}
+
+static mrb_bool
+check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
+{
+ if (pc > irep->iseq) {
+ if (line == mrb_debug_get_line(irep, pc - irep->iseq - 1)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+int32_t
+mrb_debug_check_breakpoint_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t line)
+{
+ mrb_debug_breakpoint *bp;
+ mrb_debug_linepoint *line_p;
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (!check_start_pc_for_line(dbg->irep, dbg->pc, line)) {
+ return MRB_DEBUG_OK;
+ }
+
+ bp = dbg->bp;
+ for(i=0; i<dbg->bpnum; i++) {
+ switch (bp->type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ if (bp->enable == TRUE) {
+ line_p = &bp->point.linepoint;
+ if ((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) {
+ return bp->bpno;
+ }
+ }
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ break;
+ case MRB_DEBUG_BPTYPE_NONE:
+ default:
+ return MRB_DEBUG_OK;
+ }
+ bp++;
+ }
+ return MRB_DEBUG_OK;
+}
+
+
+int32_t
+mrb_debug_check_breakpoint_method(mrb_state *mrb, mrb_debug_context *dbg, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
+{
+ mrb_debug_breakpoint *bp;
+ int32_t bpno;
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ bp = dbg->bp;
+ for(i=0; i<dbg->bpnum; i++) {
+ if (bp->type == MRB_DEBUG_BPTYPE_METHOD) {
+ if (bp->enable == TRUE) {
+ bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc);
+ if (bpno > 0) {
+ return bpno;
+ }
+ }
+ }
+ else if (bp->type == MRB_DEBUG_BPTYPE_NONE) {
+ break;
+ }
+ bp++;
+ }
+
+ return 0;
+}
+
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
new file mode 100644
index 00000000..08f1d808
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
@@ -0,0 +1,26 @@
+/*
+** apibreak.h
+**
+*/
+
+#ifndef APIBREAK_H_
+#define APIBREAK_H_
+
+#include <mruby.h>
+#include "mrdb.h"
+
+int32_t mrb_debug_set_break_line(mrb_state *, mrb_debug_context *, const char *, uint16_t);
+int32_t mrb_debug_set_break_method(mrb_state *, mrb_debug_context *, const char *, const char *);
+int32_t mrb_debug_get_breaknum(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_get_break_all(mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint bp[]);
+int32_t mrb_debug_get_break(mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint *);
+int32_t mrb_debug_delete_break(mrb_state *, mrb_debug_context *, uint32_t);
+int32_t mrb_debug_delete_break_all(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_enable_break(mrb_state *, mrb_debug_context *, uint32_t);
+int32_t mrb_debug_enable_break_all(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_disable_break(mrb_state *, mrb_debug_context *, uint32_t);
+int32_t mrb_debug_disable_break_all(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_check_breakpoint_line(mrb_state *, mrb_debug_context *, const char *, uint16_t);
+int32_t mrb_debug_check_breakpoint_method(mrb_state *, mrb_debug_context *, struct RClass *, mrb_sym, mrb_bool*);
+
+#endif /* APIBREAK_H_ */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
new file mode 100644
index 00000000..8aaa30bc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
@@ -0,0 +1,239 @@
+/*
+ * apilist.c
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mrdb.h"
+#include "mrdberror.h"
+#include "apilist.h"
+#include <mruby/compile.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
+
+#define LINE_BUF_SIZE MAX_COMMAND_LINE
+
+typedef struct source_file {
+ char *path;
+ uint16_t lineno;
+ FILE *fp;
+} source_file;
+
+static void
+source_file_free(mrb_state *mrb, source_file *file)
+{
+ if (file != NULL) {
+ if (file->path != NULL) {
+ mrb_free(mrb, file->path);
+ }
+ if (file->fp != NULL) {
+ fclose(file->fp);
+ file->fp = NULL;
+ }
+ mrb_free(mrb, file);
+ }
+}
+
+static char*
+build_path(mrb_state *mrb, const char *dir, const char *base)
+{
+ int len;
+ char *path = NULL;
+
+ len = strlen(base) + 1;
+
+ if (strcmp(dir, ".")) {
+ len += strlen(dir) + sizeof("/") - 1;
+ }
+
+ path = mrb_malloc(mrb, len);
+ memset(path, 0, len);
+
+ if (strcmp(dir, ".")) {
+ strcat(path, dir);
+ strcat(path, "/");
+ }
+ strcat(path, base);
+
+ return path;
+}
+
+static char*
+dirname(mrb_state *mrb, const char *path)
+{
+ size_t len;
+ char *p, *dir;
+
+ if (path == NULL) {
+ return NULL;
+ }
+
+ p = strrchr(path, '/');
+ len = p != NULL ? (size_t)(p - path) : strlen(path);
+
+ dir = mrb_malloc(mrb, len + 1);
+ strncpy(dir, path, len);
+ dir[len] = '\0';
+
+ return dir;
+}
+
+static source_file*
+source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
+{
+ source_file *file = NULL;
+
+ file = mrb_malloc(mrb, sizeof(source_file));
+
+ memset(file, '\0', sizeof(source_file));
+ file->fp = fopen(filename, "rb");
+
+ if (file->fp == NULL) {
+ source_file_free(mrb, file);
+ return NULL;
+ }
+
+ file->lineno = 1;
+ file->path = mrb_malloc(mrb, strlen(filename) + 1);
+ strcpy(file->path, filename);
+ return file;
+}
+
+static mrb_bool
+remove_newlines(char *s, FILE *fp)
+{
+ int c;
+ char *p;
+ size_t len;
+
+ if ((len = strlen(s)) == 0) {
+ return FALSE;
+ }
+
+ p = s + len - 1;
+
+ if (*p != '\r' && *p != '\n') {
+ return FALSE;
+ }
+
+ if (*p == '\r') {
+ /* peek the next character and skip '\n' */
+ if ((c = fgetc(fp)) != '\n') {
+ ungetc(c, fp);
+ }
+ }
+
+ /* remove trailing newline characters */
+ while (s <= p && (*p == '\r' || *p == '\n')) {
+ *p-- = '\0';
+ }
+
+ return TRUE;
+}
+
+static void
+show_lines(source_file *file, uint16_t line_min, uint16_t line_max)
+{
+ char buf[LINE_BUF_SIZE];
+ int show_lineno = 1, found_newline = 0, is_printed = 0;
+
+ if (file->fp == NULL) {
+ return;
+ }
+
+ while (fgets(buf, sizeof(buf), file->fp) != NULL) {
+ found_newline = remove_newlines(buf, file->fp);
+
+ if (line_min <= file->lineno) {
+ if (show_lineno) {
+ printf("%-8d", file->lineno);
+ }
+ show_lineno = found_newline;
+ printf(found_newline ? "%s\n" : "%s", buf);
+ is_printed = 1;
+ }
+
+ if (found_newline) {
+ if (line_max < ++file->lineno) {
+ break;
+ }
+ }
+ }
+
+ if (is_printed && !found_newline) {
+ printf("\n");
+ }
+}
+
+char*
+mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, const char *filename)
+{
+ int i;
+ FILE *fp;
+ const char *search_path[3];
+ char *path = NULL;
+ const char *srcname = strrchr(filename, '/');
+
+ if (srcname) srcname++;
+ else srcname = filename;
+
+ search_path[0] = srcpath;
+ search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->irep, 0));
+ search_path[2] = ".";
+
+ for (i = 0; i < 3; i++) {
+ if (search_path[i] == NULL) {
+ continue;
+ }
+
+ if ((path = build_path(mrb, search_path[i], srcname)) == NULL) {
+ continue;
+ }
+
+ if ((fp = fopen(path, "rb")) == NULL) {
+ mrb_free(mrb, path);
+ path = NULL;
+ continue;
+ }
+ fclose(fp);
+ break;
+ }
+
+ mrb_free(mrb, (void *)search_path[1]);
+
+ return path;
+}
+
+int32_t
+mrb_debug_list(mrb_state *mrb, mrb_debug_context *dbg, char *filename, uint16_t line_min, uint16_t line_max)
+{
+ char *ext;
+ source_file *file;
+
+ if (mrb == NULL || dbg == NULL || filename == NULL) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ ext = strrchr(filename, '.');
+
+ if (ext == NULL || strcmp(ext, ".rb")) {
+ printf("List command only supports .rb file.\n");
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (line_min > line_max) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if ((file = source_file_new(mrb, dbg, filename)) != NULL) {
+ show_lines(file, line_min, line_max);
+ source_file_free(mrb, file);
+ return MRB_DEBUG_OK;
+ }
+ else {
+ printf("Invalid source file named %s.\n", filename);
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
new file mode 100644
index 00000000..6c410788
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
@@ -0,0 +1,14 @@
+/*
+ * apilist.h
+ */
+
+#ifndef APILIST_H_
+#define APILIST_H_
+
+#include <mruby.h>
+#include "mrdb.h"
+
+int32_t mrb_debug_list(mrb_state *, mrb_debug_context *, char *, uint16_t, uint16_t);
+char* mrb_debug_get_source(mrb_state *, mrdb_state *, const char *, const char *);
+
+#endif /* APILIST_H_ */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
new file mode 100644
index 00000000..a9c895b5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
@@ -0,0 +1,78 @@
+/*
+** apiprint.c
+**
+*/
+
+#include <string.h>
+#include "mrdb.h"
+#include <mruby/value.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include "apiprint.h"
+
+static void
+mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len)
+{
+ mrbc_context *c;
+
+ c = mrbc_context_new(mrb);
+ c->no_exec = TRUE;
+ c->capture_errors = TRUE;
+ c->filename = (char*)dbg->prvfile;
+ c->lineno = dbg->prvline;
+
+ /* Load program */
+ mrb_load_nstring_cxt(mrb, expr, len, c);
+
+ mrbc_context_free(mrb, c);
+}
+
+mrb_value
+mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc)
+{
+ void (*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *);
+ mrb_value ruby_code;
+ mrb_value s;
+ mrb_value v;
+ mrb_value recv;
+
+ /* disable code_fetch_hook */
+ tmp = mrb->code_fetch_hook;
+ mrb->code_fetch_hook = NULL;
+
+ mrdb_check_syntax(mrb, dbg, expr, len);
+ if (mrb->exc) {
+ v = mrb_obj_value(mrb->exc);
+ mrb->exc = 0;
+ }
+ else {
+ /*
+ * begin
+ * expr
+ * rescue => e
+ * e
+ * end
+ */
+ ruby_code = mrb_str_new_lit(mrb, "begin\n");
+ ruby_code = mrb_str_cat(mrb, ruby_code, expr, len);
+ ruby_code = mrb_str_cat_lit(mrb, ruby_code, "\nrescue => e\ne\nend");
+
+ recv = dbg->regs[0];
+
+ v = mrb_funcall(mrb, recv, "instance_eval", 1, ruby_code);
+ }
+
+ if (exc) {
+ *exc = mrb_obj_is_kind_of(mrb, v, mrb->eException_class);
+ }
+
+ s = mrb_funcall(mrb, v, "inspect", 0);
+
+ /* enable code_fetch_hook */
+ mrb->code_fetch_hook = tmp;
+
+ return s;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
new file mode 100644
index 00000000..e256f626
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
@@ -0,0 +1,13 @@
+/*
+ * apiprint.h
+ */
+
+#ifndef APIPRINT_H_
+#define APIPRINT_H_
+
+#include <mruby.h>
+#include "mrdb.h"
+
+mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*);
+
+#endif /* APIPRINT_H_ */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
new file mode 100644
index 00000000..8e590175
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
@@ -0,0 +1,436 @@
+/*
+** cmdbreak.c
+**
+*/
+
+#include <ctype.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <mruby/debug.h>
+#include <mruby/string.h>
+#include "mrdb.h"
+#include "mrdberror.h"
+#include "apibreak.h"
+
+#define BREAK_SET_MSG_LINE "Breakpoint %d: file %s, line %d.\n"
+#define BREAK_SET_MSG_METHOD "Breakpoint %d: method %s.\n"
+#define BREAK_SET_MSG_CLASS_METHOD "Breakpoint %d: class %s, method %s.\n"
+#define BREAK_INFO_MSG_HEADER "Num Type Enb What"
+#define BREAK_INFO_MSG_LINEBREAK "%-8ubreakpoint %s at %s:%u\n"
+#define BREAK_INFO_MSG_METHODBREAK "%-8ubreakpoint %s in %s:%s\n"
+#define BREAK_INFO_MSG_METHODBREAK_NOCLASS "%-8ubreakpoint %s in %s\n"
+#define BREAK_INFO_MSG_ENABLE "y"
+#define BREAK_INFO_MSG_DISABLE "n"
+
+#define BREAK_ERR_MSG_INVALIDARG "Internal error."
+#define BREAK_ERR_MSG_BLANK "Try \'help break\' for more information."
+#define BREAK_ERR_MSG_RANGEOVER "The line number range is from 1 to 65535."
+#define BREAK_ERR_MSG_NUMOVER "Exceeded the setable number of breakpoint."
+#define BREAK_ERR_MSG_NOOVER "Breakno is over the available number.Please 'quit' and restart mrdb."
+#define BREAK_ERR_MSG_INVALIDSTR "String \'%s\' is invalid.\n"
+#define BREAK_ERR_MSG_INVALIDLINENO "Line %d in file \"%s\" is unavailable.\n"
+#define BREAK_ERR_MSG_INVALIDCLASS "Class name \'%s\' is invalid.\n"
+#define BREAK_ERR_MSG_INVALIDMETHOD "Method name \'%s\' is invalid.\n"
+#define BREAK_ERR_MSG_INVALIDFILE "Source file named \"%s\" is unavailable.\n"
+#define BREAK_ERR_MSG_INVALIDBPNO "warning: bad breakpoint number at or near '%s'\n"
+#define BREAK_ERR_MSG_INVALIDBPNO_INFO "Args must be numbers variables."
+#define BREAK_ERR_MSG_NOBPNO "No breakpoint number %d.\n"
+#define BREAK_ERR_MSG_NOBPNO_INFO "No breakpoint matching '%d'\n"
+#define BREAK_ERR_MSG_NOBPNO_INFOALL "No breakpoints."
+
+#define LINENO_MAX_DIGIT 6
+#define BPNO_LETTER_NUM 9
+
+typedef int32_t (*all_command_func)(mrb_state *, mrb_debug_context *);
+typedef int32_t (*select_command_func)(mrb_state *, mrb_debug_context *, uint32_t);
+
+static void
+print_api_common_error(int32_t error)
+{
+ switch(error) {
+ case MRB_DEBUG_INVALID_ARGUMENT:
+ puts(BREAK_ERR_MSG_INVALIDARG);
+ break;
+ default:
+ break;
+ }
+}
+
+#undef STRTOUL
+#define STRTOUL(ul,s) { \
+ int i; \
+ ul = 0; \
+ for(i=0; ISDIGIT(s[i]); i++) ul = 10*ul + (s[i] -'0'); \
+}
+
+static int32_t
+parse_breakpoint_no(char* args)
+{
+ char* ps = args;
+ uint32_t l;
+
+ if ((*ps == '0')||(strlen(ps) >= BPNO_LETTER_NUM)) {
+ return 0;
+ }
+
+ while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
+ if (!ISDIGIT(*ps)) {
+ return 0;
+ }
+ ps++;
+ }
+
+ STRTOUL(l, args);
+ return l;
+}
+
+static mrb_bool
+exe_set_command_all(mrb_state *mrb, mrdb_state *mrdb, all_command_func func)
+{
+ int32_t ret = MRB_DEBUG_OK;
+
+ if (mrdb->wcnt == 1) {
+ ret = func(mrb, mrdb->dbg);
+ print_api_common_error(ret);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+exe_set_command_select(mrb_state *mrb, mrdb_state *mrdb, select_command_func func)
+{
+ char* ps;
+ int32_t ret = MRB_DEBUG_OK;
+ int32_t bpno = 0;
+ int32_t i;
+
+ for(i=1; i<mrdb->wcnt; i++) {
+ ps = mrdb->words[i];
+ bpno = parse_breakpoint_no(ps);
+ if (bpno == 0) {
+ printf(BREAK_ERR_MSG_INVALIDBPNO, ps);
+ break;
+ }
+ ret = func(mrb, mrdb->dbg, (uint32_t)bpno);
+ if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
+ printf(BREAK_ERR_MSG_NOBPNO, bpno);
+ }
+ else if (ret != MRB_DEBUG_OK) {
+ print_api_common_error(ret);
+ }
+ }
+}
+
+mrb_debug_bptype
+check_bptype(char* args)
+{
+ char* ps = args;
+
+ if (ISBLANK(*ps)||ISCNTRL(*ps)) {
+ puts(BREAK_ERR_MSG_BLANK);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+
+ if (!ISDIGIT(*ps)) {
+ return MRB_DEBUG_BPTYPE_METHOD;
+ }
+
+ while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
+ if (!ISDIGIT(*ps)) {
+ printf(BREAK_ERR_MSG_INVALIDSTR, args);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+ ps++;
+ }
+
+ if ((*args == '0')||(strlen(args) >= LINENO_MAX_DIGIT)) {
+ puts(BREAK_ERR_MSG_RANGEOVER);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+
+ return MRB_DEBUG_BPTYPE_LINE;
+}
+
+static void
+print_breakpoint(mrb_debug_breakpoint *bp)
+{
+ const char* enable_letter[] = {BREAK_INFO_MSG_DISABLE, BREAK_INFO_MSG_ENABLE};
+
+ if (bp->type == MRB_DEBUG_BPTYPE_LINE) {
+ printf(BREAK_INFO_MSG_LINEBREAK,
+ bp->bpno, enable_letter[bp->enable], bp->point.linepoint.file, bp->point.linepoint.lineno);
+ }
+ else {
+ if (bp->point.methodpoint.class_name == NULL) {
+ printf(BREAK_INFO_MSG_METHODBREAK_NOCLASS,
+ bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.method_name);
+ }
+ else {
+ printf(BREAK_INFO_MSG_METHODBREAK,
+ bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.class_name, bp->point.methodpoint.method_name);
+ }
+ }
+}
+
+static void
+info_break_all(mrb_state *mrb, mrdb_state *mrdb)
+{
+ int32_t bpnum = 0;
+ int32_t i = 0;
+ int32_t ret = MRB_DEBUG_OK;
+ mrb_debug_breakpoint *bp_list;
+
+ bpnum = mrb_debug_get_breaknum(mrb, mrdb->dbg);
+ if (bpnum < 0) {
+ print_api_common_error(bpnum);
+ return;
+ }
+ else if (bpnum == 0) {
+ puts(BREAK_ERR_MSG_NOBPNO_INFOALL);
+ return;
+ }
+ bp_list = (mrb_debug_breakpoint*)mrb_malloc(mrb, bpnum * sizeof(mrb_debug_breakpoint));
+
+ ret = mrb_debug_get_break_all(mrb, mrdb->dbg, (uint32_t)bpnum, bp_list);
+ if (ret < 0) {
+ print_api_common_error(ret);
+ return;
+ }
+ puts(BREAK_INFO_MSG_HEADER);
+ for(i = 0 ; i < bpnum ; i++) {
+ print_breakpoint(&bp_list[i]);
+ }
+
+ mrb_free(mrb, bp_list);
+}
+
+static void
+info_break_select(mrb_state *mrb, mrdb_state *mrdb)
+{
+ int32_t ret = MRB_DEBUG_OK;
+ int32_t bpno = 0;
+ char* ps = mrdb->command;
+ mrb_debug_breakpoint bp;
+ mrb_bool isFirst = TRUE;
+ int32_t i;
+
+ for(i=2; i<mrdb->wcnt; i++) {
+ ps = mrdb->words[i];
+ bpno = parse_breakpoint_no(ps);
+ if (bpno == 0) {
+ puts(BREAK_ERR_MSG_INVALIDBPNO_INFO);
+ break;
+ }
+
+ ret = mrb_debug_get_break(mrb, mrdb->dbg, bpno, &bp);
+ if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
+ printf(BREAK_ERR_MSG_NOBPNO_INFO, bpno);
+ break;
+ }
+ else if (ret != MRB_DEBUG_OK) {
+ print_api_common_error(ret);
+ break;
+ }
+ else if (isFirst == TRUE) {
+ isFirst = FALSE;
+ puts(BREAK_INFO_MSG_HEADER);
+ }
+ print_breakpoint(&bp);
+ }
+}
+
+mrb_debug_bptype
+parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
+{
+ mrb_debug_context *dbg = mrdb->dbg;
+ char *args;
+ char *body;
+ mrb_debug_bptype type;
+ uint32_t l;
+
+ if (mrdb->wcnt <= 1) {
+ puts(BREAK_ERR_MSG_BLANK);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+
+ args = mrdb->words[1];
+ if ((body = strrchr(args, ':')) == NULL) {
+ body = args;
+ type = check_bptype(body);
+ }
+ else {
+ if (body == args) {
+ printf(BREAK_ERR_MSG_INVALIDSTR, args);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+ *body = '\0';
+ type = check_bptype(++body);
+ }
+
+ switch(type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ STRTOUL(l, body);
+ if (l <= 65535) {
+ *line = l;
+ *file = (body == args)? mrb_debug_get_filename(dbg->irep, dbg->pc - dbg->irep->iseq): args;
+ }
+ else {
+ puts(BREAK_ERR_MSG_RANGEOVER);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ }
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ if (body == args) {
+ /* method only */
+ if (ISUPPER(*body)||ISLOWER(*body)||(*body == '_')) {
+ *method = body;
+ *cname = NULL;
+ }
+ else {
+ printf(BREAK_ERR_MSG_INVALIDMETHOD, args);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ }
+ }
+ else {
+ if (ISUPPER(*args)) {
+ switch(*body) {
+ case '@': case '$': case '?': case '.': case ',': case ':':
+ case ';': case '#': case '\\': case '\'': case '\"':
+ printf(BREAK_ERR_MSG_INVALIDMETHOD, body);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ break;
+ default:
+ *method = body;
+ *cname = args;
+ break;
+ }
+ }
+ else {
+ printf(BREAK_ERR_MSG_INVALIDCLASS, args);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ }
+ }
+ break;
+ case MRB_DEBUG_BPTYPE_NONE:
+ default:
+ break;
+ }
+
+ return type;
+}
+
+dbgcmd_state
+dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_bptype type;
+ mrb_debug_context *dbg = mrdb->dbg;
+ const char *file = NULL;
+ uint32_t line = 0;
+ char *cname = NULL;
+ char *method = NULL;
+ int32_t ret;
+
+ type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
+ switch (type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ ret = mrb_debug_set_break_line(mrb, dbg, file, line);
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ ret = mrb_debug_set_break_method(mrb, dbg, cname, method);
+ break;
+ case MRB_DEBUG_BPTYPE_NONE:
+ default:
+ return DBGST_PROMPT;
+ }
+
+ if (ret >= 0) {
+ if (type == MRB_DEBUG_BPTYPE_LINE) {
+ printf(BREAK_SET_MSG_LINE, ret, file, line);
+ }
+ else if ((type == MRB_DEBUG_BPTYPE_METHOD)&&(cname == NULL)) {
+ printf(BREAK_SET_MSG_METHOD, ret, method);
+ }
+ else {
+ printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method);
+ }
+ }
+ else {
+ switch (ret) {
+ case MRB_DEBUG_BREAK_INVALID_LINENO:
+ printf(BREAK_ERR_MSG_INVALIDLINENO, line, file);
+ break;
+ case MRB_DEBUG_BREAK_INVALID_FILE:
+ printf(BREAK_ERR_MSG_INVALIDFILE, file);
+ break;
+ case MRB_DEBUG_BREAK_NUM_OVER:
+ puts(BREAK_ERR_MSG_NUMOVER);
+ break;
+ case MRB_DEBUG_BREAK_NO_OVER:
+ puts(BREAK_ERR_MSG_NOOVER);
+ break;
+ case MRB_DEBUG_INVALID_ARGUMENT:
+ puts(BREAK_ERR_MSG_INVALIDARG);
+ break;
+ case MRB_DEBUG_NOBUF:
+ puts("T.B.D.");
+ break;
+ default:
+ break;
+ }
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_info_break(mrb_state *mrb, mrdb_state *mrdb)
+{
+ if (mrdb->wcnt == 2) {
+ info_break_all(mrb, mrdb);
+ }
+ else {
+ info_break_select(mrb, mrdb);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_delete(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool ret = FALSE;
+
+ ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all);
+ if (ret != TRUE) {
+ exe_set_command_select(mrb, mrdb, mrb_debug_delete_break);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_enable(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool ret = FALSE;
+
+ ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all);
+ if (ret != TRUE) {
+ exe_set_command_select(mrb, mrdb, mrb_debug_enable_break);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_disable(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool ret = FALSE;
+
+ ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all);
+ if (ret != TRUE) {
+ exe_set_command_select(mrb, mrdb, mrb_debug_disable_break);
+ }
+ return DBGST_PROMPT;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
new file mode 100644
index 00000000..5984b623
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
@@ -0,0 +1,501 @@
+/*
+** cmdmisc.c - mruby debugger miscellaneous command functions
+**
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "apilist.h"
+#include <mruby/compile.h>
+
+typedef struct help_msg {
+ const char *cmd1;
+ const char *cmd2;
+ const char *short_msg;
+ const char *long_msg;
+} help_msg;
+
+static help_msg help_msg_list[] = {
+ {
+ "b[reak]", NULL, "Set breakpoint",
+ "Usage: break [file:]line\n"
+ " break [class:]method\n"
+ "\n"
+ "Set breakpoint at specified line or method.\n"
+ "If \'[file:]line\' is specified, break at start of code for that line (in a file).\n"
+ "If \'[class:]method\' is specified, break at start of code for that method (of the class).\n"
+ },
+ {
+ "c[ontinue]", NULL, "Continue program being debugged",
+ "Usage: continue [N]\n"
+ "\n"
+ "Continue program stopped by a breakpoint.\n"
+ "If N, which is non negative value, is passed,\n"
+ "proceed program until the N-th breakpoint is coming.\n"
+ "If N is not passed, N is assumed 1.\n"
+ },
+ {
+ "d[elete]", NULL, "Delete some breakpoints",
+ "Usage: delete [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Delete some breakpoints.\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ "To delete all breakpoints, give no argument.\n"
+ },
+ {
+ "dis[able]", NULL, "Disable some breakpoints",
+ "Usage: disable [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Disable some breakpoints.\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ "To disable all breakpoints, give no argument.\n"
+ },
+ {
+ "en[able]", NULL, "Enable some breakpoints",
+ "Usage: enable [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Enable some breakpoints.\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ "To enable all breakpoints, give no argument.\n"
+ },
+ {
+ "ev[al]", NULL, "Evaluate expression",
+ "Usage: eval expr\n"
+ "\n"
+ "It evaluates and prints the value of the mruby expression.\n"
+ "This is equivalent to the \'print\' command.\n"
+ },
+ {
+ "h[elp]", NULL, "Print this help",
+ "Usage: help [command]\n"
+ "\n"
+ "With no arguments, help displays a short list of commands.\n"
+ "With a command name as help argument, help displays how to use that command.\n"
+ },
+ {
+ "i[nfo]", "b[reakpoints]", "Status of breakpoints",
+ "Usage: info breakpoints [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Status of specified breakpoints (all user-settable breakpoints if no argument).\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ },
+ {
+ "l[ist]", NULL, "List specified line",
+ "Usage: list\n"
+ " list first[,last]\n"
+ " list filename:first[,last]\n"
+ "\n"
+ "Print lines from a source file.\n"
+ "\n"
+ "With first and last, list prints lines from first to last.\n"
+ "When last is empty, it stands for ten lines away from first.\n"
+ "With filename, list prints lines in the specified source file.\n"
+ },
+ {
+ "p[rint]", NULL, "Print value of expression",
+ "Usage: print expr\n"
+ "\n"
+ "It evaluates and prints the value of the mruby expression.\n"
+ "This is equivalent to the \'eval\' command.\n"
+ },
+ {
+ "q[uit]", NULL, "Exit mrdb",
+ "Usage: quit\n"
+ "\n"
+ "Exit mrdb.\n"
+ },
+ {
+ "r[un]", NULL, "Start debugged program",
+ "Usage: run\n"
+ "\n"
+ "Start debugged program.\n"
+ },
+ {
+ "s[tep]", NULL, "Step program until it reaches a different source line",
+ "Usage: step\n"
+ "\n"
+ "Step program until it reaches a different source line.\n"
+ },
+ { NULL, NULL, NULL, NULL }
+};
+
+typedef struct listcmd_parser_state {
+ mrb_bool parse_error;
+ mrb_bool has_line_min;
+ mrb_bool has_line_max;
+ char *filename;
+ uint16_t line_min;
+ uint16_t line_max;
+} listcmd_parser_state;
+
+static listcmd_parser_state*
+listcmd_parser_state_new(mrb_state *mrb)
+{
+ listcmd_parser_state *st = mrb_malloc(mrb, sizeof(listcmd_parser_state));
+ memset(st, 0, sizeof(listcmd_parser_state));
+ return st;
+}
+
+static void
+listcmd_parser_state_free(mrb_state *mrb, listcmd_parser_state *st)
+{
+ if (st != NULL) {
+ if (st->filename != NULL) {
+ mrb_free(mrb, st->filename);
+ }
+ mrb_free(mrb, st);
+ }
+}
+
+static mrb_bool
+parse_uint(char **sp, uint16_t *n)
+{
+ char *p;
+ int i;
+
+ if (*sp == NULL || **sp == '\0') {
+ return FALSE;
+ }
+
+ for (p = *sp; *p != '\0' && ISDIGIT(*p); p++) ;
+
+ if (p != *sp && (i = atoi(*sp)) >= 0) {
+ *n = (uint16_t)i;
+ *sp = p;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static mrb_bool
+skip_char(char **sp, char c)
+{
+ if (*sp != NULL && **sp == c) {
+ ++*sp;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static mrb_bool
+parse_lineno(mrb_state *mrb, char **sp, listcmd_parser_state *st)
+{
+ if (*sp == NULL || **sp == '\0') {
+ return FALSE;
+ }
+
+ st->has_line_min = FALSE;
+ st->has_line_max = FALSE;
+
+ if (parse_uint(sp, &st->line_min)) {
+ st->has_line_min = TRUE;
+ }
+ else {
+ return FALSE;
+ }
+
+ if (skip_char(sp, ',')) {
+ if (parse_uint(sp, &st->line_max)) {
+ st->has_line_max = TRUE;
+ }
+ else {
+ st->parse_error = TRUE;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static mrb_bool
+parse_filename(mrb_state *mrb, char **sp, listcmd_parser_state *st)
+{
+ char *p;
+ int len;
+
+ if (st->filename != NULL) {
+ mrb_free(mrb, st->filename);
+ st->filename = NULL;
+ }
+
+ if ((p = strchr(*sp, ':')) != NULL) {
+ len = p - *sp;
+ }
+ else {
+ len = strlen(*sp);
+ }
+
+ if (len > 0) {
+ st->filename = mrb_malloc(mrb, len + 1);
+ strncpy(st->filename, *sp, len);
+ st->filename[len] = '\0';
+ *sp += len;
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+char*
+replace_ext(mrb_state *mrb, const char *filename, const char *ext)
+{
+ size_t len;
+ char *p, *s;
+
+ if (filename == NULL) {
+ return NULL;
+ }
+
+ if ((p = strrchr(filename, '.')) != NULL && strchr(p, '/') == NULL) {
+ len = p - filename;
+ }
+ else {
+ len = strlen(filename);
+ }
+
+ s = mrb_malloc(mrb, len + strlen(ext) + 1);
+ memset(s, '\0', len + strlen(ext) + 1);
+ strncpy(s, filename, len);
+ strcat(s, ext);
+
+ return s;
+}
+
+static mrb_bool
+parse_listcmd_args(mrb_state *mrb, mrdb_state *mrdb, listcmd_parser_state *st)
+{
+ char *p;
+
+ switch (mrdb->wcnt) {
+ case 2:
+ p = mrdb->words[1];
+
+ /* mrdb->words[1] ::= <lineno> | <filename> ':' <lineno> | <filename> */
+ if (!parse_lineno(mrb, &p, st)) {
+ if (parse_filename(mrb, &p, st)) {
+ if (skip_char(&p, ':')) {
+ if (!parse_lineno(mrb, &p, st)) {
+ st->parse_error = TRUE;
+ }
+ }
+ }
+ else {
+ st->parse_error = TRUE;
+ }
+ }
+ if (*p != '\0') {
+ st->parse_error = TRUE;
+ }
+ break;
+ case 1:
+ case 0:
+ /* do nothing */
+ break;
+ default:
+ st->parse_error = TRUE;
+ printf("too many arguments\n");
+ break;
+ }
+
+ if (!st->parse_error) {
+ if (!st->has_line_min) {
+ st->line_min = (!st->filename && mrdb->dbg->prvline > 0) ? mrdb->dbg->prvline : 1;
+ }
+
+ if (!st->has_line_max) {
+ st->line_max = st->line_min + 9;
+ }
+
+ if (st->filename == NULL) {
+ if (mrdb->dbg->prvfile && strcmp(mrdb->dbg->prvfile, "-")) {
+ st->filename = replace_ext(mrb, mrdb->dbg->prvfile, ".rb");
+ }
+ }
+ }
+
+ if (st->parse_error || st->filename == NULL) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static mrb_bool
+check_cmd_pattern(const char *pattern, const char *cmd)
+{
+ char *lbracket, *rbracket, *p, *q;
+
+ if (pattern == NULL && cmd == NULL) {
+ return TRUE;
+ }
+ if (pattern == NULL || cmd == NULL) {
+ return FALSE;
+ }
+ if ((lbracket = strchr(pattern, '[')) == NULL) {
+ return !strcmp(pattern, cmd);
+ }
+ if ((rbracket = strchr(pattern, ']')) == NULL) {
+ return FALSE;
+ }
+ if (strncmp(pattern, cmd, lbracket - pattern)) {
+ return FALSE;
+ }
+
+ p = lbracket + 1;
+ q = (char *)cmd + (lbracket - pattern);
+
+ for ( ; p < rbracket && *q != '\0'; p++, q++) {
+ if (*p != *q) {
+ break;
+ }
+ }
+ return *q == '\0';
+}
+
+static help_msg*
+get_help_msg(char *cmd1, char *cmd2)
+{
+ help_msg *p;
+
+ if (cmd1 == NULL) {
+ return NULL;
+ }
+ for (p = help_msg_list; p->cmd1 != NULL; p++) {
+ if (check_cmd_pattern(p->cmd1, cmd1) && check_cmd_pattern(p->cmd2, cmd2)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+static mrb_bool
+show_short_help(void)
+{
+ help_msg *p;
+
+ printf("Commands\n");
+
+ for (p = help_msg_list; p->cmd1 != NULL; p++) {
+ if (p->cmd2 == NULL) {
+ printf(" %s -- %s\n", p->cmd1, p->short_msg);
+ }
+ else {
+ printf(" %s %s -- %s\n", p->cmd1, p->cmd2, p->short_msg);
+ }
+ }
+ return TRUE;
+}
+
+static mrb_bool
+show_long_help(char *cmd1, char *cmd2)
+{
+ help_msg *help;
+
+ if ((help = get_help_msg(cmd1, cmd2)) == NULL) {
+ return FALSE;
+ }
+ printf("%s", help->long_msg);
+ return TRUE;
+}
+
+dbgcmd_state
+dbgcmd_list(mrb_state *mrb, mrdb_state *mrdb)
+{
+ char *filename;
+ listcmd_parser_state *st = listcmd_parser_state_new(mrb);
+
+ if (parse_listcmd_args(mrb, mrdb, st)) {
+ if ((filename = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, st->filename)) == NULL) {
+ filename = st->filename;
+ }
+ mrb_debug_list(mrb, mrdb->dbg, filename, st->line_min, st->line_max);
+
+ if (filename != NULL && filename != st->filename) {
+ mrb_free(mrb, filename);
+ }
+ listcmd_parser_state_free(mrb, st);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_help(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool is_valid;
+ int i;
+
+ switch (mrdb->wcnt) {
+ case 0:
+ case 1:
+ is_valid = show_short_help();
+ break;
+ case 2:
+ is_valid = show_long_help(mrdb->words[1], NULL);
+ break;
+ case 3:
+ is_valid = show_long_help(mrdb->words[1], mrdb->words[2]);
+ break;
+ default:
+ is_valid = FALSE;
+ break;
+ }
+
+ if (!is_valid) {
+ printf("Invalid command \"");
+ for (i = 1; i < mrdb->wcnt; i++) {
+ printf("%s%s", i == 1 ? "" : " ", mrdb->words[i]);
+ }
+ printf("\". Try \"help\".\n");
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_quit(mrb_state *mrb, mrdb_state *mrdb)
+{
+ switch (mrdb->dbg->xm) {
+ case DBG_RUN:
+ case DBG_STEP:
+ case DBG_NEXT:
+ while (1) {
+ char c;
+ int buf;
+
+ printf("The program is running. Exit anyway? (y or n) ");
+ fflush(stdout);
+
+ if ((buf = getchar()) == EOF) {
+ mrdb->dbg->xm = DBG_QUIT;
+ break;
+ }
+ c = buf;
+ while (buf != '\n' && (buf = getchar()) != EOF) ;
+
+ if (c == 'y' || c == 'Y') {
+ mrdb->dbg->xm = DBG_QUIT;
+ break;
+ }
+ else if (c == 'n' || c == 'N') {
+ break;
+ }
+ else {
+ printf("Please answer y or n.\n");
+ }
+ }
+ break;
+ default:
+ mrdb->dbg->xm = DBG_QUIT;
+ break;
+ }
+
+ if (mrdb->dbg->xm == DBG_QUIT) {
+ struct RClass *exc;
+ exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception"));
+ mrb_raise(mrb, exc, "Exit mrdb.");
+ }
+ return DBGST_PROMPT;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
new file mode 100644
index 00000000..cca63671
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
@@ -0,0 +1,58 @@
+/*
+** cmdprint.c - mruby debugger print command functions
+**
+*/
+
+#include <string.h>
+#include "mrdb.h"
+#include <mruby/value.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include "apiprint.h"
+
+dbgcmd_state
+dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_value expr;
+ mrb_value result;
+ mrb_value s;
+ uint8_t wcnt;
+ int ai;
+
+ if (mrdb->wcnt <= 1) {
+ puts("Parameter not specified.");
+ return DBGST_PROMPT;
+ }
+
+ ai = mrb_gc_arena_save(mrb);
+
+ /* eval expr */
+ expr = mrb_str_new_cstr(mrb, NULL);
+ for (wcnt=1; wcnt<mrdb->wcnt; wcnt++) {
+ expr = mrb_str_cat_lit(mrb, expr, " ");
+ expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]);
+ }
+
+ result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL);
+
+ /* $print_no = result */
+ s = mrb_str_cat_lit(mrb, result, "\0");
+ printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
+
+ if (mrdb->print_no == 0) {
+ mrdb->print_no = 1;
+ }
+
+ mrb_gc_arena_restore(mrb, ai);
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_eval(mrb_state *mrb, mrdb_state *mrdb)
+{
+ return dbgcmd_print(mrb, mrdb);
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
new file mode 100644
index 00000000..cb4c738f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
@@ -0,0 +1,64 @@
+/*
+** cmdrun.c - mruby debugger run command functions
+**
+*/
+
+#include <mruby/opcode.h>
+#include "mrdb.h"
+
+dbgcmd_state
+dbgcmd_run(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_context *dbg = mrdb->dbg;
+
+ if (dbg->xm == DBG_INIT){
+ dbg->xm = DBG_RUN;
+ }
+ else {
+ dbg->xm = DBG_QUIT;
+ if (dbg->xphase == DBG_PHASE_RUNNING){
+ struct RClass *exc;
+ puts("Start it from the beginning.");
+ exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception"));
+ mrb_raise(mrb, exc, "Restart mrdb.");
+ }
+ }
+
+ return DBGST_RESTART;
+}
+
+dbgcmd_state
+dbgcmd_continue(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_context *dbg = mrdb->dbg;
+ int ccnt = 1;
+
+ if (mrdb->wcnt > 1){
+ sscanf(mrdb->words[1], "%d", &ccnt);
+ }
+ dbg->ccnt = (uint16_t)(ccnt > 0 ? ccnt : 1); /* count of continue */
+
+ if (dbg->xphase == DBG_PHASE_AFTER_RUN){
+ puts("The program is not running.");
+ dbg->xm = DBG_QUIT;
+ }
+ else {
+ dbg->xm = DBG_RUN;
+ }
+ return DBGST_CONTINUE;
+}
+
+dbgcmd_state
+dbgcmd_step(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrdb->dbg->xm = DBG_STEP;
+ return DBGST_CONTINUE;
+}
+
+dbgcmd_state
+dbgcmd_next(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrdb->dbg->xm = DBG_NEXT;
+ mrdb->dbg->prvci = mrb->c->ci;
+ return DBGST_CONTINUE;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
new file mode 100644
index 00000000..d12dcd5d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
@@ -0,0 +1,759 @@
+/*
+** mrdb.c - mruby debugger
+**
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <mruby/debug.h>
+#include <mruby/class.h>
+#include <mruby/opcode.h>
+#include <mruby/variable.h>
+
+#include "mrdb.h"
+#include "apibreak.h"
+#include "apilist.h"
+
+void mrdb_state_free(mrb_state *);
+
+static mrb_debug_context *_debug_context = NULL;
+static mrdb_state *_mrdb_state = NULL;
+
+struct _args {
+ FILE *rfp;
+ char* fname;
+ char* srcpath;
+ int argc;
+ char** argv;
+ mrb_bool mrbfile : 1;
+};
+
+typedef struct debug_command {
+ const char *cmd1;
+ const char *cmd2;
+ uint8_t len1;
+ uint8_t len2;
+ uint8_t div;
+ debug_command_id id;
+ debug_command_func func;
+} debug_command;
+
+static const debug_command debug_command_list[] = {
+ {"break", NULL, 1, 0, 0, DBGCMD_BREAK, dbgcmd_break}, /* b[reak] */
+ {"continue", NULL, 1, 0, 0, DBGCMD_CONTINUE, dbgcmd_continue}, /* c[ontinue] */
+ {"delete", NULL, 1, 0, 1, DBGCMD_DELETE, dbgcmd_delete}, /* d[elete] */
+ {"disable", NULL, 3, 0, 1, DBGCMD_DISABLE, dbgcmd_disable}, /* dis[able] */
+ {"enable", NULL, 2, 0, 1, DBGCMD_ENABLE, dbgcmd_enable}, /* en[able] */
+ {"eval", NULL, 2, 0, 0, DBGCMD_EVAL, dbgcmd_eval}, /* ev[al] */
+ {"help", NULL, 1, 0, 1, DBGCMD_HELP, dbgcmd_help}, /* h[elp] */
+ {"info", "breakpoints", 1, 1, 1, DBGCMD_INFO_BREAK, dbgcmd_info_break}, /* i[nfo] b[reakpoints] */
+ {"list", NULL, 1, 0, 1, DBGCMD_LIST, dbgcmd_list}, /* l[ist] */
+ {"print", NULL, 1, 0, 0, DBGCMD_PRINT, dbgcmd_print}, /* p[rint] */
+ {"quit", NULL, 1, 0, 0, DBGCMD_QUIT, dbgcmd_quit}, /* q[uit] */
+ {"run", NULL, 1, 0, 0, DBGCMD_RUN, dbgcmd_run}, /* r[un] */
+ {"step", NULL, 1, 0, 1, DBGCMD_STEP, dbgcmd_step}, /* s[tep] */
+ {"next", NULL, 1, 0, 1, DBGCMD_NEXT, dbgcmd_next}, /* n[ext] */
+ {NULL}
+};
+
+
+static void
+usage(const char *name)
+{
+ static const char *const usage_msg[] = {
+ "switches:",
+ "-b load and execute RiteBinary (mrb) file",
+ "-d specify source directory",
+ "--version print the version",
+ "--copyright print the copyright",
+ NULL
+ };
+ const char *const *p = usage_msg;
+
+ printf("Usage: %s [switches] programfile\n", name);
+ while (*p) {
+ printf(" %s\n", *p++);
+ }
+}
+
+static int
+parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
+{
+ char **origargv = argv;
+ static const struct _args args_zero = { 0 };
+
+ *args = args_zero;
+
+ for (argc--,argv++; argc > 0; argc--,argv++) {
+ char *item;
+ if (argv[0][0] != '-') break;
+
+ item = argv[0] + 1;
+ switch (*item++) {
+ case 'b':
+ args->mrbfile = TRUE;
+ break;
+ case 'd':
+ if (item[0]) {
+ goto append_srcpath;
+ }
+ else if (argc > 1) {
+ argc--; argv++;
+ item = argv[0];
+append_srcpath:
+ if (!args->srcpath) {
+ size_t buflen;
+ char *buf;
+
+ buflen = strlen(item) + 1;
+ buf = (char *)mrb_malloc(mrb, buflen);
+ memcpy(buf, item, buflen);
+ args->srcpath = buf;
+ }
+ else {
+ size_t srcpathlen;
+ size_t itemlen;
+
+ srcpathlen = strlen(args->srcpath);
+ itemlen = strlen(item);
+ args->srcpath =
+ (char *)mrb_realloc(mrb, args->srcpath, srcpathlen + itemlen + 2);
+ args->srcpath[srcpathlen] = '\n';
+ memcpy(args->srcpath + srcpathlen + 1, item, itemlen + 1);
+ }
+ }
+ else {
+ printf("%s: No path specified for -d\n", *origargv);
+ return EXIT_SUCCESS;
+ }
+ break;
+ case '-':
+ if (strcmp((*argv) + 2, "version") == 0) {
+ mrb_show_version(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp((*argv) + 2, "copyright") == 0) {
+ mrb_show_copyright(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ default:
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (args->rfp == NULL) {
+ if (*argv == NULL) {
+ printf("%s: Program file not specified.\n", *origargv);
+ return EXIT_FAILURE;
+ }
+ else {
+ args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
+ if (args->rfp == NULL) {
+ printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
+ return EXIT_FAILURE;
+ }
+ args->fname = argv[0];
+ argc--; argv++;
+ }
+ }
+ args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
+ memcpy(args->argv, argv, (argc+1) * sizeof(char*));
+ args->argc = argc;
+
+ return EXIT_SUCCESS;
+}
+
+static void
+cleanup(mrb_state *mrb, struct _args *args)
+{
+ if (args->rfp)
+ fclose(args->rfp);
+ if (args->srcpath)
+ mrb_free(mrb, args->srcpath);
+ if (args->argv)
+ mrb_free(mrb, args->argv);
+ mrdb_state_free(mrb);
+ mrb_close(mrb);
+}
+
+static mrb_debug_context*
+mrb_debug_context_new(mrb_state *mrb)
+{
+ mrb_debug_context *dbg = mrb_malloc(mrb, sizeof(mrb_debug_context));
+
+ memset(dbg, 0, sizeof(mrb_debug_context));
+
+ dbg->xm = DBG_INIT;
+ dbg->xphase = DBG_PHASE_BEFORE_RUN;
+ dbg->next_bpno = 1;
+
+ return dbg;
+}
+
+mrb_debug_context*
+mrb_debug_context_get(mrb_state *mrb)
+{
+ if (!_debug_context) {
+ _debug_context = mrb_debug_context_new(mrb);
+ }
+ return _debug_context;
+}
+
+void
+mrb_debug_context_set(mrb_debug_context *dbg)
+{
+ _debug_context = dbg;
+}
+
+void
+mrb_debug_context_free(mrb_state *mrb)
+{
+ if (_debug_context) {
+ mrb_debug_delete_break_all(mrb, _debug_context);
+ mrb_free(mrb, _debug_context);
+ _debug_context = NULL;
+ }
+}
+
+static mrdb_state*
+mrdb_state_new(mrb_state *mrb)
+{
+ mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state));
+
+ memset(mrdb, 0, sizeof(mrdb_state));
+
+ mrdb->dbg = mrb_debug_context_get(mrb);
+ mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1);
+ mrdb->print_no = 1;
+
+ return mrdb;
+}
+
+mrdb_state*
+mrdb_state_get(mrb_state *mrb)
+{
+ if (!_mrdb_state) {
+ _mrdb_state = mrdb_state_new(mrb);
+ }
+ return _mrdb_state;
+}
+
+void
+mrdb_state_set(mrdb_state *mrdb)
+{
+ _mrdb_state = mrdb;
+}
+
+void
+mrdb_state_free(mrb_state *mrb)
+{
+ mrb_debug_context_free(mrb);
+ if (_mrdb_state) {
+ mrb_free(mrb, _mrdb_state->command);
+ mrb_free(mrb, _mrdb_state);
+ _mrdb_state = NULL;
+ }
+}
+
+static char*
+get_command(mrb_state *mrb, mrdb_state *mrdb)
+{
+ int i;
+ int c;
+
+ for (i=0; i<MAX_COMMAND_LINE; i++) {
+ if ((c=getchar()) == EOF || c == '\n') break;
+ mrdb->command[i] = c;
+ }
+
+ if (i == 0 && feof(stdin)) {
+ clearerr(stdin);
+ strcpy(mrdb->command, "quit");
+ i += sizeof("quit") - 1;
+ }
+
+ if (i == MAX_COMMAND_LINE) {
+ for ( ; (c=getchar()) != EOF && c !='\n'; i++) ;
+ }
+
+ if (i > MAX_COMMAND_LINE) {
+ printf("command line too long.\n");
+ i = 0; /* discard command data */
+ }
+ mrdb->command[i] = '\0';
+
+ return mrdb->command;
+}
+
+static char*
+pick_out_word(mrb_state *mrb, char **pp)
+{
+ char *ps;
+
+ for (ps=*pp; ISBLANK(*ps); ps++) ;
+ if (*ps == '\0') {
+ return NULL;
+ }
+
+ if (*ps == '\"' || *ps == '\'') {
+ *pp = strchr(ps+1, *ps);
+ if (*pp) (*pp)++;
+ }
+ else {
+ *pp = strpbrk(ps, " \t");
+ }
+
+ if (!*pp) {
+ *pp = ps + strlen(ps);
+ }
+
+ if (**pp != '\0') {
+ **pp = '\0';
+ (*pp)++;
+ }
+
+ return ps;
+}
+
+static debug_command*
+parse_command(mrb_state *mrb, mrdb_state *mrdb, char *buf)
+{
+ debug_command *cmd = NULL;
+ char *p = buf;
+ size_t wlen;
+
+ /* get word #1 */
+ mrdb->words[0] = pick_out_word(mrb, &p);
+ if (!mrdb->words[0]) {
+ return NULL;
+ }
+ mrdb->wcnt = 1;
+ /* set remain parameter */
+ for ( ; *p && ISBLANK(*p); p++) ;
+ if (*p) {
+ mrdb->words[mrdb->wcnt++] = p;
+ }
+
+ /* check word #1 */
+ for (cmd=(debug_command*)debug_command_list; cmd->cmd1; cmd++) {
+ wlen = strlen(mrdb->words[0]);
+ if (wlen >= cmd->len1 &&
+ strncmp(mrdb->words[0], cmd->cmd1, wlen) == 0) {
+ break;
+ }
+ }
+
+ if (cmd->cmd2) {
+ if (mrdb->wcnt > 1) {
+ /* get word #2 */
+ mrdb->words[1] = pick_out_word(mrb, &p);
+ if (mrdb->words[1]) {
+ /* update remain parameter */
+ for ( ; *p && ISBLANK(*p); p++) ;
+ if (*p) {
+ mrdb->words[mrdb->wcnt++] = p;
+ }
+ }
+ }
+
+ /* check word #1,#2 */
+ for ( ; cmd->cmd1; cmd++) {
+ wlen = strlen(mrdb->words[0]);
+ if (wlen < cmd->len1 ||
+ strncmp(mrdb->words[0], cmd->cmd1, wlen)) {
+ continue;
+ }
+
+ if (!cmd->cmd2) break; /* word #1 only */
+
+ if (mrdb->wcnt == 1) continue; /* word #2 not specified */
+
+ wlen = strlen(mrdb->words[1]);
+ if (wlen >= cmd->len2 &&
+ strncmp(mrdb->words[1], cmd->cmd2, wlen) == 0) {
+ break; /* word #1 and #2 */
+ }
+ }
+ }
+
+ /* divide remain parameters */
+ if (cmd->cmd1 && cmd->div) {
+ p = mrdb->words[--mrdb->wcnt];
+ for ( ; mrdb->wcnt<MAX_COMMAND_WORD; mrdb->wcnt++) {
+ mrdb->words[mrdb->wcnt] = pick_out_word(mrb, &p);
+ if (!mrdb->words[mrdb->wcnt]) {
+ break;
+ }
+ }
+ }
+
+ return cmd->cmd1 ? cmd : NULL;
+}
+
+static void
+print_info_stopped_break(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_breakpoint bp;
+ int32_t ret;
+ uint16_t lineno;
+ const char *file;
+ const char *method_name;
+ const char *class_name;
+
+ ret = mrb_debug_get_break(mrb, mrdb->dbg, mrdb->dbg->stopped_bpno, &bp);
+ if (ret == 0) {
+ switch(bp.type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ file = bp.point.linepoint.file;
+ lineno = bp.point.linepoint.lineno;
+ printf("Breakpoint %d, at %s:%d\n", bp.bpno, file, lineno);
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ method_name = bp.point.methodpoint.method_name;
+ class_name = bp.point.methodpoint.class_name;
+ if (class_name == NULL) {
+ printf("Breakpoint %d, %s\n", bp.bpno, method_name);
+ }
+ else {
+ printf("Breakpoint %d, %s:%s\n", bp.bpno, class_name, method_name);
+ }
+ if (mrdb->dbg->isCfunc) {
+ printf("Stopped before calling the C function.\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+print_info_stopped_step_next(mrb_state *mrb, mrdb_state *mrdb)
+{
+ const char* file = mrdb->dbg->prvfile;
+ uint16_t lineno = mrdb->dbg->prvline;
+ printf("%s:%d\n", file, lineno);
+}
+
+static void
+print_info_stopped_code(mrb_state *mrb, mrdb_state *mrdb)
+{
+ char* file = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, mrdb->dbg->prvfile);
+ uint16_t lineno = mrdb->dbg->prvline;
+ if (file != NULL) {
+ mrb_debug_list(mrb, mrdb->dbg, file, lineno, lineno);
+ mrb_free(mrb, file);
+ }
+}
+
+static void
+print_info_stopped(mrb_state *mrb, mrdb_state *mrdb)
+{
+ switch(mrdb->dbg->bm) {
+ case BRK_BREAK:
+ print_info_stopped_break(mrb, mrdb);
+ print_info_stopped_code(mrb, mrdb);
+ break;
+ case BRK_STEP:
+ case BRK_NEXT:
+ print_info_stopped_step_next(mrb, mrdb);
+ print_info_stopped_code(mrb, mrdb);
+ break;
+ default:
+ break;
+ }
+}
+
+static debug_command*
+get_and_parse_command(mrb_state *mrb, mrdb_state *mrdb)
+{
+ debug_command *cmd = NULL;
+ char *p;
+ int i;
+
+ while (!cmd) {
+ for (p=NULL; !p || *p=='\0'; ) {
+ printf("(%s:%d) ", mrdb->dbg->prvfile, mrdb->dbg->prvline);
+ fflush(stdout);
+ p = get_command(mrb, mrdb);
+ }
+
+ cmd = parse_command(mrb, mrdb, p);
+#ifdef _DBG_MRDB_PARSER_
+ for (i=0; i<mrdb->wcnt; i++) {
+ printf("%d: %s\n", i, mrdb->words[i]);
+ }
+#endif
+ if (!cmd) {
+ printf("invalid command (");
+ for (i=0; i<mrdb->wcnt; i++) {
+ if (i>0) {
+ printf(" ");
+ }
+ printf("%s", mrdb->words[i]);
+ }
+ puts(")");
+ }
+ }
+ return cmd;
+}
+
+static int32_t
+check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
+{
+ struct RClass* c;
+ mrb_sym sym;
+ int32_t bpno;
+ mrb_bool isCfunc;
+
+ mrb_debug_context *dbg = mrb_debug_context_get(mrb);
+
+ isCfunc = FALSE;
+ bpno = dbg->method_bpno;
+ dbg->method_bpno = 0;
+
+ switch(GET_OPCODE(*pc)) {
+ case OP_SEND:
+ case OP_SENDB:
+ c = mrb_class(mrb, regs[GETARG_A(*pc)]);
+ sym = irep->syms[GETARG_B(*pc)];
+ break;
+ case OP_SUPER:
+ c = mrb->c->ci->target_class->super;
+ sym = mrb->c->ci->mid;
+ break;
+ default:
+ sym = 0;
+ break;
+ }
+ if (sym != 0) {
+ dbg->method_bpno = mrb_debug_check_breakpoint_method(mrb, dbg, c, sym, &isCfunc);
+ if (isCfunc) {
+ bpno = dbg->method_bpno;
+ dbg->method_bpno = 0;
+ }
+ }
+ dbg->isCfunc = isCfunc;
+ return bpno;
+}
+
+static void
+mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
+{
+ const char *file;
+ int32_t line;
+ int32_t bpno;
+
+ mrb_debug_context *dbg = mrb_debug_context_get(mrb);
+
+ mrb_assert(dbg);
+
+ dbg->irep = irep;
+ dbg->pc = pc;
+ dbg->regs = regs;
+
+ if (dbg->xphase == DBG_PHASE_RESTART) {
+ dbg->root_irep = irep;
+ dbg->prvfile = NULL;
+ dbg->prvline = 0;
+ dbg->prvci = NULL;
+ dbg->xm = DBG_RUN;
+ dbg->xphase = DBG_PHASE_RUNNING;
+ }
+
+ file = mrb_debug_get_filename(irep, pc - irep->iseq);
+ line = mrb_debug_get_line(irep, pc - irep->iseq);
+
+ switch (dbg->xm) {
+ case DBG_STEP:
+ if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
+ return;
+ }
+ dbg->method_bpno = 0;
+ dbg->bm = BRK_STEP;
+ break;
+
+ case DBG_NEXT:
+ if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
+ return;
+ }
+ if ((intptr_t)(dbg->prvci) < (intptr_t)(mrb->c->ci)) {
+ return;
+ }
+ dbg->prvci = NULL;
+ dbg->method_bpno = 0;
+ dbg->bm = BRK_NEXT;
+ break;
+
+ case DBG_RUN:
+ bpno = check_method_breakpoint(mrb, irep, pc, regs);
+ if (bpno > 0) {
+ dbg->stopped_bpno = bpno;
+ dbg->bm = BRK_BREAK;
+ break;
+ }
+ if (dbg->prvfile != file || dbg->prvline != line) {
+ bpno = mrb_debug_check_breakpoint_line(mrb, dbg, file, line);
+ if (bpno > 0) {
+ dbg->stopped_bpno = bpno;
+ dbg->bm = BRK_BREAK;
+ break;
+ }
+ }
+ dbg->prvfile = file;
+ dbg->prvline = line;
+ return;
+ case DBG_INIT:
+ dbg->root_irep = irep;
+ dbg->bm = BRK_INIT;
+ if (!file || line < 0) {
+ puts("Cannot get debugging information.");
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ dbg->prvfile = file;
+ dbg->prvline = line;
+
+ if (dbg->bm == BRK_BREAK && --dbg->ccnt > 0) {
+ return;
+ }
+ dbg->break_hook(mrb, dbg);
+
+ dbg->xphase = DBG_PHASE_RUNNING;
+}
+
+static mrdb_exemode
+mrb_debug_break_hook(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ debug_command *cmd;
+ dbgcmd_state st = DBGST_CONTINUE;
+ mrdb_state *mrdb = mrdb_state_get(mrb);
+
+ print_info_stopped(mrb, mrdb);
+
+ while (1) {
+ cmd = get_and_parse_command(mrb, mrdb);
+ mrb_assert(cmd);
+
+ st = cmd->func(mrb, mrdb);
+
+ if ((st == DBGST_CONTINUE) || (st == DBGST_RESTART)) break;
+ }
+ return dbg->xm;
+}
+
+int
+main(int argc, char **argv)
+{
+ mrb_state *mrb = mrb_open();
+ int n = -1;
+ struct _args args;
+ mrb_value v;
+ mrdb_state *mrdb;
+ mrdb_state *mrdb_backup;
+ mrb_debug_context* dbg_backup;
+ debug_command *cmd;
+
+ l_restart:
+
+ if (mrb == NULL) {
+ fputs("Invalid mrb_state, exiting mruby\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ /* parse command parameters */
+ n = parse_args(mrb, argc, argv, &args);
+ if (n == EXIT_FAILURE || args.rfp == NULL) {
+ cleanup(mrb, &args);
+ usage(argv[0]);
+ return n;
+ }
+
+ /* initialize debugger information */
+ mrdb = mrdb_state_get(mrb);
+ mrb_assert(mrdb && mrdb->dbg);
+ mrdb->srcpath = args.srcpath;
+
+ if (mrdb->dbg->xm == DBG_QUIT) {
+ mrdb->dbg->xphase = DBG_PHASE_RESTART;
+ }
+ else {
+ mrdb->dbg->xphase = DBG_PHASE_BEFORE_RUN;
+ }
+ mrdb->dbg->xm = DBG_INIT;
+ mrdb->dbg->ccnt = 1;
+
+ /* setup hook functions */
+ mrb->code_fetch_hook = mrb_code_fetch_hook;
+ mrdb->dbg->break_hook = mrb_debug_break_hook;
+
+ if (args.mrbfile) { /* .mrb */
+ v = mrb_load_irep_file(mrb, args.rfp);
+ }
+ else { /* .rb */
+ mrbc_context *cc = mrbc_context_new(mrb);
+ mrbc_filename(mrb, cc, args.fname);
+ v = mrb_load_file_cxt(mrb, args.rfp, cc);
+ mrbc_context_free(mrb, cc);
+ }
+ if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) {
+ const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc));
+ if (!strcmp(classname, "DebuggerExit")) {
+ cleanup(mrb, &args);
+ return 0;
+ }
+ if (!strcmp(classname, "DebuggerRestart")) {
+ mrdb_backup = mrdb_state_get(mrb);
+ dbg_backup = mrb_debug_context_get(mrb);
+
+ mrdb_state_set(NULL);
+ mrb_debug_context_set(NULL);
+
+ cleanup(mrb, &args);
+ mrb = mrb_open();
+
+ mrdb_state_set(mrdb_backup);
+ mrb_debug_context_set(dbg_backup);
+
+ goto l_restart;
+ }
+ }
+ puts("mruby application exited.");
+ mrdb->dbg->xphase = DBG_PHASE_AFTER_RUN;
+ if (!mrb_undef_p(v)) {
+ if (mrb->exc) {
+ mrb_print_error(mrb);
+ }
+ else {
+ printf(" => ");
+ mrb_p(mrb, v);
+ }
+ }
+
+ mrdb->dbg->prvfile = "-";
+ mrdb->dbg->prvline = 0;
+
+ while (1) {
+ cmd = get_and_parse_command(mrb, mrdb);
+ mrb_assert(cmd);
+
+ if (cmd->id == DBGCMD_QUIT) {
+ break;
+ }
+
+ if ( cmd->func(mrb, mrdb) == DBGST_RESTART ) goto l_restart;
+ }
+
+ cleanup(mrb, &args);
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
new file mode 100644
index 00000000..5ac12c1c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
@@ -0,0 +1,165 @@
+/*
+** mrdb.h - mruby debugger
+**
+*/
+
+#ifndef MRDB_H
+#define MRDB_H
+
+#include <mruby.h>
+
+#include "mrdbconf.h"
+
+#ifdef _MSC_VER
+# define __func__ __FUNCTION__
+#endif
+
+#define MAX_COMMAND_WORD (16)
+
+typedef enum debug_command_id {
+ DBGCMD_RUN,
+ DBGCMD_CONTINUE,
+ DBGCMD_NEXT,
+ DBGCMD_STEP,
+ DBGCMD_BREAK,
+ DBGCMD_INFO_BREAK,
+ DBGCMD_WATCH,
+ DBGCMD_INFO_WATCH,
+ DBGCMD_ENABLE,
+ DBGCMD_DISABLE,
+ DBGCMD_DELETE,
+ DBGCMD_PRINT,
+ DBGCMD_DISPLAY,
+ DBGCMD_INFO_DISPLAY,
+ DBGCMD_DELETE_DISPLAY,
+ DBGCMD_EVAL,
+ DBGCMD_BACKTRACE,
+ DBGCMD_LIST,
+ DBGCMD_HELP,
+ DBGCMD_QUIT,
+ DBGCMD_UNKNOWN
+} debug_command_id;
+
+typedef enum dbgcmd_state {
+ DBGST_CONTINUE,
+ DBGST_PROMPT,
+ DBGST_COMMAND_ERROR,
+ DBGST_MAX,
+ DBGST_RESTART
+} dbgcmd_state;
+
+typedef enum mrdb_exemode {
+ DBG_INIT,
+ DBG_RUN,
+ DBG_STEP,
+ DBG_NEXT,
+ DBG_QUIT,
+} mrdb_exemode;
+
+typedef enum mrdb_exephase {
+ DBG_PHASE_BEFORE_RUN,
+ DBG_PHASE_RUNNING,
+ DBG_PHASE_AFTER_RUN,
+ DBG_PHASE_RESTART,
+} mrdb_exephase;
+
+typedef enum mrdb_brkmode {
+ BRK_INIT,
+ BRK_BREAK,
+ BRK_STEP,
+ BRK_NEXT,
+ BRK_QUIT,
+} mrdb_brkmode;
+
+typedef enum {
+ MRB_DEBUG_BPTYPE_NONE,
+ MRB_DEBUG_BPTYPE_LINE,
+ MRB_DEBUG_BPTYPE_METHOD,
+} mrb_debug_bptype;
+
+struct mrb_irep;
+struct mrbc_context;
+struct mrb_debug_context;
+
+typedef struct mrb_debug_linepoint {
+ const char *file;
+ uint16_t lineno;
+} mrb_debug_linepoint;
+
+typedef struct mrb_debug_methodpoint {
+ const char *class_name;
+ const char *method_name;
+} mrb_debug_methodpoint;
+
+typedef struct mrb_debug_breakpoint {
+ uint32_t bpno;
+ uint8_t enable;
+ mrb_debug_bptype type;
+ union point {
+ mrb_debug_linepoint linepoint;
+ mrb_debug_methodpoint methodpoint;
+ } point;
+} mrb_debug_breakpoint;
+
+typedef struct mrb_debug_context {
+ struct mrb_irep *root_irep;
+ struct mrb_irep *irep;
+ mrb_code *pc;
+ mrb_value *regs;
+
+ const char *prvfile;
+ int32_t prvline;
+ mrb_callinfo *prvci;
+
+ mrdb_exemode xm;
+ mrdb_exephase xphase;
+ mrdb_brkmode bm;
+ int16_t bmi;
+
+ uint16_t ccnt;
+ uint16_t scnt;
+
+ mrb_debug_breakpoint bp[MAX_BREAKPOINT];
+ uint32_t bpnum;
+ int32_t next_bpno;
+ int32_t method_bpno;
+ int32_t stopped_bpno;
+ mrb_bool isCfunc;
+
+ mrdb_exemode (*break_hook)(mrb_state *mrb, struct mrb_debug_context *dbg);
+
+} mrb_debug_context;
+
+typedef struct mrdb_state {
+ char *command;
+ uint8_t wcnt;
+ uint8_t pi;
+ char *words[MAX_COMMAND_WORD];
+ const char *srcpath;
+ uint32_t print_no;
+
+ mrb_debug_context *dbg;
+} mrdb_state;
+
+typedef dbgcmd_state (*debug_command_func)(mrb_state*, mrdb_state*);
+
+/* cmdrun.c */
+dbgcmd_state dbgcmd_run(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_continue(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_step(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_next(mrb_state*, mrdb_state*);
+/* cmdbreak.c */
+dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_delete(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_enable(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_disable(mrb_state*, mrdb_state*);
+/* cmdprint.c */
+dbgcmd_state dbgcmd_print(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_eval(mrb_state*, mrdb_state*);
+/* cmdmisc.c */
+dbgcmd_state dbgcmd_list(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_help(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_quit(mrb_state*, mrdb_state*);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
new file mode 100644
index 00000000..f17f9c57
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
@@ -0,0 +1,16 @@
+/*
+** mrdbconf.h - mruby debugger configuration
+**
+*/
+
+#ifndef MRDBCONF_H
+#define MRDBCONF_H
+
+/* configuration options: */
+/* maximum size for command buffer */
+#define MAX_COMMAND_LINE 1024
+
+/* maximum number of setable breakpoint */
+#define MAX_BREAKPOINT 5
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
new file mode 100644
index 00000000..c7812b0d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
@@ -0,0 +1,20 @@
+/*
+** mrdberror.h - mruby debugger error code
+**
+*/
+
+#ifndef MRDBERROR_H
+#define MRDBERROR_H
+
+#define MRB_DEBUG_OK (0)
+#define MRB_DEBUG_NOBUF (-1)
+#define MRB_DEBUG_INVALID_ARGUMENT (-2)
+
+#define MRB_DEBUG_BREAK_INVALID_LINENO (-11)
+#define MRB_DEBUG_BREAK_INVALID_FILE (-12)
+#define MRB_DEBUG_BREAK_INVALID_NO (-13)
+#define MRB_DEBUG_BREAK_NUM_OVER (-14)
+#define MRB_DEBUG_BREAK_NO_OVER (-15)
+
+#endif
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb
new file mode 100644
index 00000000..ed53321b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb
@@ -0,0 +1,12 @@
+require 'open3'
+
+assert('mirb normal operations') do
+ o, s = Open3.capture2('bin/mirb', :stdin_data => "a=1\nb=2\na+b\n")
+ assert_true o.include?('=> 3')
+ assert_true o.include?('=> 2')
+end
+
+assert('regression for #1563') do
+ o, s = Open3.capture2('bin/mirb', :stdin_data => "a=1;b=2;c=3\nb\nc")
+ assert_true o.include?('=> 3')
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake
new file mode 100644
index 00000000..a74871d8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake
@@ -0,0 +1,33 @@
+MRuby::Gem::Specification.new('mruby-bin-mirb') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mirb command'
+
+ if spec.build.cc.search_header_path 'readline/readline.h'
+ spec.cc.defines << "ENABLE_READLINE"
+ if spec.build.cc.search_header_path 'termcap.h'
+ if MRUBY_BUILD_HOST_IS_CYGWIN || MRUBY_BUILD_HOST_IS_OPENBSD
+ if spec.build.cc.search_header_path 'termcap.h'
+ if MRUBY_BUILD_HOST_IS_CYGWIN then
+ spec.linker.libraries << 'ncurses'
+ else
+ spec.linker.libraries << 'termcap'
+ end
+ end
+ end
+ end
+ if RUBY_PLATFORM.include?('netbsd')
+ spec.linker.libraries << 'edit'
+ else
+ spec.linker.libraries << 'readline'
+ if spec.build.cc.search_header_path 'curses.h'
+ spec.linker.libraries << 'ncurses'
+ end
+ end
+ elsif spec.build.cc.search_header_path 'linenoise.h'
+ spec.cc.defines << "ENABLE_LINENOISE"
+ end
+
+ spec.bins = %w(mirb)
+ spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
new file mode 100644
index 00000000..fe311d83
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c
@@ -0,0 +1,584 @@
+/*
+** mirb - Embeddable Interactive Ruby Shell
+**
+** This program takes code from the user in
+** an interactive way and executes it
+** immediately. It's a REPL...
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <signal.h>
+#include <setjmp.h>
+
+#ifdef ENABLE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#define MIRB_ADD_HISTORY(line) add_history(line)
+#define MIRB_READLINE(ch) readline(ch)
+#define MIRB_WRITE_HISTORY(path) write_history(path)
+#define MIRB_READ_HISTORY(path) read_history(path)
+#define MIRB_USING_HISTORY() using_history()
+#elif defined(ENABLE_LINENOISE)
+#define ENABLE_READLINE
+#include <linenoise.h>
+#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
+#define MIRB_READLINE(ch) linenoise(ch)
+#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
+#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
+#define MIRB_USING_HISTORY()
+#endif
+
+#ifndef _WIN32
+#define MIRB_SIGSETJMP(env) sigsetjmp(env, 1)
+#define MIRB_SIGLONGJMP(env, val) siglongjmp(env, val)
+#define SIGJMP_BUF sigjmp_buf
+#else
+#define MIRB_SIGSETJMP(env) setjmp(env)
+#define MIRB_SIGLONGJMP(env, val) longjmp(env, val)
+#define SIGJMP_BUF jmp_buf
+#endif
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/proc.h>
+#include <mruby/compile.h>
+#include <mruby/string.h>
+
+#ifdef ENABLE_READLINE
+
+static const char history_file_name[] = ".mirb_history";
+
+static char *
+get_history_path(mrb_state *mrb)
+{
+ char *path = NULL;
+ const char *home = getenv("HOME");
+
+#ifdef _WIN32
+ if (home != NULL) {
+ home = getenv("USERPROFILE");
+ }
+#endif
+
+ if (home != NULL) {
+ int len = snprintf(NULL, 0, "%s/%s", home, history_file_name);
+ if (len >= 0) {
+ size_t size = len + 1;
+ path = (char *)mrb_malloc_simple(mrb, size);
+ if (path != NULL) {
+ int n = snprintf(path, size, "%s/%s", home, history_file_name);
+ if (n != len) {
+ mrb_free(mrb, path);
+ path = NULL;
+ }
+ }
+ }
+ }
+
+ return path;
+}
+
+#endif
+
+static void
+p(mrb_state *mrb, mrb_value obj, int prompt)
+{
+ mrb_value val;
+
+ val = mrb_funcall(mrb, obj, "inspect", 0);
+ if (prompt) {
+ if (!mrb->exc) {
+ fputs(" => ", stdout);
+ }
+ else {
+ val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
+ }
+ }
+ if (!mrb_string_p(val)) {
+ val = mrb_obj_as_string(mrb, obj);
+ }
+ fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
+ putc('\n', stdout);
+}
+
+/* Guess if the user might want to enter more
+ * or if he wants an evaluation of his code now */
+static mrb_bool
+is_code_block_open(struct mrb_parser_state *parser)
+{
+ mrb_bool code_block_open = FALSE;
+
+ /* check for heredoc */
+ if (parser->parsing_heredoc != NULL) return TRUE;
+ if (parser->heredoc_end_now) {
+ parser->heredoc_end_now = FALSE;
+ return FALSE;
+ }
+
+ /* check for unterminated string */
+ if (parser->lex_strterm) return TRUE;
+
+ /* check if parser error are available */
+ if (0 < parser->nerr) {
+ const char unexpected_end[] = "syntax error, unexpected $end";
+ const char *message = parser->error_buffer[0].message;
+
+ /* a parser error occur, we have to check if */
+ /* we need to read one more line or if there is */
+ /* a different issue which we have to show to */
+ /* the user */
+
+ if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) {
+ code_block_open = TRUE;
+ }
+ else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) {
+ code_block_open = FALSE;
+ }
+ else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) {
+ code_block_open = FALSE;
+ }
+ return code_block_open;
+ }
+
+ switch (parser->lstate) {
+
+ /* all states which need more code */
+
+ case EXPR_BEG:
+ /* beginning of a statement, */
+ /* that means previous line ended */
+ code_block_open = FALSE;
+ break;
+ case EXPR_DOT:
+ /* a message dot was the last token, */
+ /* there has to come more */
+ code_block_open = TRUE;
+ break;
+ case EXPR_CLASS:
+ /* a class keyword is not enough! */
+ /* we need also a name of the class */
+ code_block_open = TRUE;
+ break;
+ case EXPR_FNAME:
+ /* a method name is necessary */
+ code_block_open = TRUE;
+ break;
+ case EXPR_VALUE:
+ /* if, elsif, etc. without condition */
+ code_block_open = TRUE;
+ break;
+
+ /* now all the states which are closed */
+
+ case EXPR_ARG:
+ /* an argument is the last token */
+ code_block_open = FALSE;
+ break;
+
+ /* all states which are unsure */
+
+ case EXPR_CMDARG:
+ break;
+ case EXPR_END:
+ /* an expression was ended */
+ break;
+ case EXPR_ENDARG:
+ /* closing parenthese */
+ break;
+ case EXPR_ENDFN:
+ /* definition end */
+ break;
+ case EXPR_MID:
+ /* jump keyword like break, return, ... */
+ break;
+ case EXPR_MAX_STATE:
+ /* don't know what to do with this token */
+ break;
+ default:
+ /* this state is unexpected! */
+ break;
+ }
+
+ return code_block_open;
+}
+
+struct _args {
+ FILE *rfp;
+ mrb_bool verbose : 1;
+ int argc;
+ char** argv;
+};
+
+static void
+usage(const char *name)
+{
+ static const char *const usage_msg[] = {
+ "switches:",
+ "-v print version number, then run in verbose mode",
+ "--verbose run in verbose mode",
+ "--version print the version",
+ "--copyright print the copyright",
+ NULL
+ };
+ const char *const *p = usage_msg;
+
+ printf("Usage: %s [switches]\n", name);
+ while (*p)
+ printf(" %s\n", *p++);
+}
+
+static int
+parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
+{
+ static const struct _args args_zero = { 0 };
+
+ *args = args_zero;
+
+ for (argc--,argv++; argc > 0; argc--,argv++) {
+ char *item;
+ if (argv[0][0] != '-') break;
+
+ item = argv[0] + 1;
+ switch (*item++) {
+ case 'v':
+ if (!args->verbose) mrb_show_version(mrb);
+ args->verbose = TRUE;
+ break;
+ case '-':
+ if (strcmp((*argv) + 2, "version") == 0) {
+ mrb_show_version(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp((*argv) + 2, "verbose") == 0) {
+ args->verbose = TRUE;
+ break;
+ }
+ else if (strcmp((*argv) + 2, "copyright") == 0) {
+ mrb_show_copyright(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ default:
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (args->rfp == NULL) {
+ if (*argv != NULL) {
+ args->rfp = fopen(argv[0], "r");
+ if (args->rfp == NULL) {
+ printf("Cannot open program file. (%s)\n", *argv);
+ return EXIT_FAILURE;
+ }
+ argc--; argv++;
+ }
+ }
+ args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
+ memcpy(args->argv, argv, (argc+1) * sizeof(char*));
+ args->argc = argc;
+
+ return EXIT_SUCCESS;
+}
+
+static void
+cleanup(mrb_state *mrb, struct _args *args)
+{
+ if (args->rfp)
+ fclose(args->rfp);
+ mrb_free(mrb, args->argv);
+ mrb_close(mrb);
+}
+
+/* Print a short remark for the user */
+static void
+print_hint(void)
+{
+ printf("mirb - Embeddable Interactive Ruby Shell\n\n");
+}
+
+#ifndef ENABLE_READLINE
+/* Print the command line prompt of the REPL */
+static void
+print_cmdline(int code_block_open)
+{
+ if (code_block_open) {
+ printf("* ");
+ }
+ else {
+ printf("> ");
+ }
+ fflush(stdout);
+}
+#endif
+
+void mrb_codedump_all(mrb_state*, struct RProc*);
+
+static int
+check_keyword(const char *buf, const char *word)
+{
+ const char *p = buf;
+ size_t len = strlen(word);
+
+ /* skip preceding spaces */
+ while (*p && isspace((unsigned char)*p)) {
+ p++;
+ }
+ /* check keyword */
+ if (strncmp(p, word, len) != 0) {
+ return 0;
+ }
+ p += len;
+ /* skip trailing spaces */
+ while (*p) {
+ if (!isspace((unsigned char)*p)) return 0;
+ p++;
+ }
+ return 1;
+}
+
+
+#ifndef ENABLE_READLINE
+volatile sig_atomic_t input_canceled = 0;
+void
+ctrl_c_handler(int signo)
+{
+ input_canceled = 1;
+}
+#else
+SIGJMP_BUF ctrl_c_buf;
+void
+ctrl_c_handler(int signo)
+{
+ MIRB_SIGLONGJMP(ctrl_c_buf, 1);
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ char ruby_code[4096] = { 0 };
+ char last_code_line[1024] = { 0 };
+#ifndef ENABLE_READLINE
+ int last_char;
+ size_t char_index;
+#else
+ char *history_path;
+ char* line;
+#endif
+ mrbc_context *cxt;
+ struct mrb_parser_state *parser;
+ mrb_state *mrb;
+ mrb_value result;
+ struct _args args;
+ mrb_value ARGV;
+ int n;
+ int i;
+ mrb_bool code_block_open = FALSE;
+ int ai;
+ unsigned int stack_keep = 0;
+
+ /* new interpreter instance */
+ mrb = mrb_open();
+ if (mrb == NULL) {
+ fputs("Invalid mrb interpreter, exiting mirb\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ n = parse_args(mrb, argc, argv, &args);
+ if (n == EXIT_FAILURE) {
+ cleanup(mrb, &args);
+ usage(argv[0]);
+ return n;
+ }
+
+ ARGV = mrb_ary_new_capa(mrb, args.argc);
+ for (i = 0; i < args.argc; i++) {
+ char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
+ if (utf8) {
+ mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
+ mrb_utf8_free(utf8);
+ }
+ }
+ mrb_define_global_const(mrb, "ARGV", ARGV);
+
+#ifdef ENABLE_READLINE
+ history_path = get_history_path(mrb);
+ if (history_path == NULL) {
+ fputs("failed to get history path\n", stderr);
+ mrb_close(mrb);
+ return EXIT_FAILURE;
+ }
+
+ MIRB_USING_HISTORY();
+ MIRB_READ_HISTORY(history_path);
+#endif
+
+ print_hint();
+
+ cxt = mrbc_context_new(mrb);
+ cxt->capture_errors = TRUE;
+ cxt->lineno = 1;
+ mrbc_filename(mrb, cxt, "(mirb)");
+ if (args.verbose) cxt->dump_result = TRUE;
+
+ ai = mrb_gc_arena_save(mrb);
+
+ while (TRUE) {
+ char *utf8;
+
+ if (args.rfp) {
+ if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL)
+ goto done;
+ break;
+ }
+
+#ifndef ENABLE_READLINE
+ print_cmdline(code_block_open);
+
+ signal(SIGINT, ctrl_c_handler);
+ char_index = 0;
+ while ((last_char = getchar()) != '\n') {
+ if (last_char == EOF) break;
+ if (char_index >= sizeof(last_code_line)-2) {
+ fputs("input string too long\n", stderr);
+ continue;
+ }
+ last_code_line[char_index++] = last_char;
+ }
+ signal(SIGINT, SIG_DFL);
+ if (input_canceled) {
+ ruby_code[0] = '\0';
+ last_code_line[0] = '\0';
+ code_block_open = FALSE;
+ puts("^C");
+ input_canceled = 0;
+ continue;
+ }
+ if (last_char == EOF) {
+ fputs("\n", stdout);
+ break;
+ }
+
+ last_code_line[char_index++] = '\n';
+ last_code_line[char_index] = '\0';
+#else
+ if (MIRB_SIGSETJMP(ctrl_c_buf) == 0) {
+ ;
+ }
+ else {
+ ruby_code[0] = '\0';
+ last_code_line[0] = '\0';
+ code_block_open = FALSE;
+ puts("^C");
+ }
+ signal(SIGINT, ctrl_c_handler);
+ line = MIRB_READLINE(code_block_open ? "* " : "> ");
+ signal(SIGINT, SIG_DFL);
+
+ if (line == NULL) {
+ printf("\n");
+ break;
+ }
+ if (strlen(line) > sizeof(last_code_line)-2) {
+ fputs("input string too long\n", stderr);
+ continue;
+ }
+ strcpy(last_code_line, line);
+ strcat(last_code_line, "\n");
+ MIRB_ADD_HISTORY(line);
+ free(line);
+#endif
+
+done:
+
+ if (code_block_open) {
+ if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
+ fputs("concatenated input string too long\n", stderr);
+ continue;
+ }
+ strcat(ruby_code, last_code_line);
+ }
+ else {
+ if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) {
+ break;
+ }
+ strcpy(ruby_code, last_code_line);
+ }
+
+ utf8 = mrb_utf8_from_locale(ruby_code, -1);
+ if (!utf8) abort();
+
+ /* parse code */
+ parser = mrb_parser_new(mrb);
+ if (parser == NULL) {
+ fputs("create parser state error\n", stderr);
+ break;
+ }
+ parser->s = utf8;
+ parser->send = utf8 + strlen(utf8);
+ parser->lineno = cxt->lineno;
+ mrb_parser_parse(parser, cxt);
+ code_block_open = is_code_block_open(parser);
+ mrb_utf8_free(utf8);
+
+ if (code_block_open) {
+ /* no evaluation of code */
+ }
+ else {
+ if (0 < parser->nerr) {
+ /* syntax error */
+ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
+ }
+ else {
+ /* generate bytecode */
+ struct RProc *proc = mrb_generate_code(mrb, parser);
+ if (proc == NULL) {
+ fputs("codegen error\n", stderr);
+ mrb_parser_free(parser);
+ break;
+ }
+
+ if (args.verbose) {
+ mrb_codedump_all(mrb, proc);
+ }
+ /* pass a proc for evaluation */
+ /* evaluate the bytecode */
+ result = mrb_vm_run(mrb,
+ proc,
+ mrb_top_self(mrb),
+ stack_keep);
+ stack_keep = proc->body.irep->nlocals;
+ /* did an exception occur? */
+ if (mrb->exc) {
+ p(mrb, mrb_obj_value(mrb->exc), 0);
+ mrb->exc = 0;
+ }
+ else {
+ /* no */
+ if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){
+ result = mrb_any_to_s(mrb, result);
+ }
+ p(mrb, result, 1);
+ }
+ }
+ ruby_code[0] = '\0';
+ last_code_line[0] = '\0';
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ mrb_parser_free(parser);
+ cxt->lineno++;
+ }
+
+#ifdef ENABLE_READLINE
+ MIRB_WRITE_HISTORY(history_path);
+ mrb_free(mrb, history_path);
+#endif
+
+ mrbc_context_free(mrb, cxt);
+ mrb_close(mrb);
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake
new file mode 100644
index 00000000..e710b5a4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake
@@ -0,0 +1,16 @@
+MRuby::Gem::Specification.new 'mruby-bin-mrbc' do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mruby compiler executable'
+
+ spec.add_dependency 'mruby-compiler', :core => 'mruby-compiler'
+
+ exec = exefile("#{build.build_dir}/bin/mrbc")
+ mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten
+
+ file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t|
+ build.linker.run t.name, t.prerequisites
+ end
+
+ build.bins << 'mrbc' unless build.bins.find { |v| v == 'mrbc' }
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
new file mode 100644
index 00000000..580c2e25
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
@@ -0,0 +1,336 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/dump.h>
+#include <mruby/proc.h>
+
+#define RITEBIN_EXT ".mrb"
+#define C_EXT ".c"
+
+struct mrbc_args {
+ int argc;
+ char **argv;
+ int idx;
+ const char *prog;
+ const char *outfile;
+ const char *initname;
+ mrb_bool check_syntax : 1;
+ mrb_bool verbose : 1;
+ unsigned int flags : 4;
+};
+
+static void
+usage(const char *name)
+{
+ static const char *const usage_msg[] = {
+ "switches:",
+ "-c check syntax only",
+ "-o<outfile> place the output into <outfile>",
+ "-v print version number, then turn on verbose mode",
+ "-g produce debugging information",
+ "-B<symbol> binary <symbol> output in C language format",
+ "-e generate little endian iseq data",
+ "-E generate big endian iseq data",
+ "--verbose run at verbose mode",
+ "--version print the version",
+ "--copyright print the copyright",
+ NULL
+ };
+ const char *const *p = usage_msg;
+
+ printf("Usage: %s [switches] programfile\n", name);
+ while (*p)
+ printf(" %s\n", *p++);
+}
+
+static char *
+get_outfilename(mrb_state *mrb, char *infile, const char *ext)
+{
+ size_t infilelen;
+ size_t extlen;
+ char *outfile;
+ char *p;
+
+ infilelen = strlen(infile);
+ extlen = strlen(ext);
+ outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
+ memcpy(outfile, infile, infilelen + 1);
+ if (*ext) {
+ if ((p = strrchr(outfile, '.')) == NULL)
+ p = outfile + infilelen;
+ memcpy(p, ext, extlen + 1);
+ }
+
+ return outfile;
+}
+
+static int
+parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
+{
+ char *outfile = NULL;
+ static const struct mrbc_args args_zero = { 0 };
+ int i;
+
+ *args = args_zero;
+ args->argc = argc;
+ args->argv = argv;
+ args->prog = argv[0];
+
+ for (i=1; i<argc; i++) {
+ if (argv[i][0] == '-') {
+ switch ((argv[i])[1]) {
+ case 'o':
+ if (args->outfile) {
+ fprintf(stderr, "%s: an output file is already specified. (%s)\n",
+ args->prog, outfile);
+ return -1;
+ }
+ if (argv[i][2] == '\0' && argv[i+1]) {
+ i++;
+ args->outfile = get_outfilename(mrb, argv[i], "");
+ }
+ else {
+ args->outfile = get_outfilename(mrb, argv[i] + 2, "");
+ }
+ break;
+ case 'B':
+ if (argv[i][2] == '\0' && argv[i+1]) {
+ i++;
+ args->initname = argv[i];
+ }
+ else {
+ args->initname = argv[i]+2;
+ }
+ if (*args->initname == '\0') {
+ fprintf(stderr, "%s: function name is not specified.\n", args->prog);
+ return -1;
+ }
+ break;
+ case 'c':
+ args->check_syntax = TRUE;
+ break;
+ case 'v':
+ if (!args->verbose) mrb_show_version(mrb);
+ args->verbose = TRUE;
+ break;
+ case 'g':
+ args->flags |= DUMP_DEBUG_INFO;
+ break;
+ case 'E':
+ args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
+ break;
+ case 'e':
+ args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
+ break;
+ case 'h':
+ return -1;
+ case '-':
+ if (argv[i][1] == '\n') {
+ return i;
+ }
+ if (strcmp(argv[i] + 2, "version") == 0) {
+ mrb_show_version(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i] + 2, "verbose") == 0) {
+ args->verbose = TRUE;
+ break;
+ }
+ else if (strcmp(argv[i] + 2, "copyright") == 0) {
+ mrb_show_copyright(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ return -1;
+ default:
+ return i;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
+ fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
+ args->prog, bigendian_p() ? "big" : "little");
+ }
+ return i;
+}
+
+static void
+cleanup(mrb_state *mrb, struct mrbc_args *args)
+{
+ mrb_free(mrb, (void*)args->outfile);
+ mrb_close(mrb);
+}
+
+static int
+partial_hook(struct mrb_parser_state *p)
+{
+ mrbc_context *c = p->cxt;
+ struct mrbc_args *args = (struct mrbc_args *)c->partial_data;
+ const char *fn;
+
+ if (p->f) fclose(p->f);
+ if (args->idx >= args->argc) {
+ p->f = NULL;
+ return -1;
+ }
+ fn = args->argv[args->idx++];
+ p->f = fopen(fn, "r");
+ if (p->f == NULL) {
+ fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
+ return -1;
+ }
+ mrb_parser_set_filename(p, fn);
+ return 0;
+}
+
+static mrb_value
+load_file(mrb_state *mrb, struct mrbc_args *args)
+{
+ mrbc_context *c;
+ mrb_value result;
+ char *input = args->argv[args->idx];
+ FILE *infile;
+ mrb_bool need_close = FALSE;
+
+ c = mrbc_context_new(mrb);
+ if (args->verbose)
+ c->dump_result = TRUE;
+ c->no_exec = TRUE;
+ if (input[0] == '-' && input[1] == '\0') {
+ infile = stdin;
+ }
+ else {
+ need_close = TRUE;
+ if ((infile = fopen(input, "r")) == NULL) {
+ fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
+ return mrb_nil_value();
+ }
+ }
+ mrbc_filename(mrb, c, input);
+ args->idx++;
+ if (args->idx < args->argc) {
+ need_close = FALSE;
+ mrbc_partial_hook(mrb, c, partial_hook, (void*)args);
+ }
+
+ result = mrb_load_file_cxt(mrb, infile, c);
+ if (need_close) fclose(infile);
+ mrbc_context_free(mrb, c);
+ if (mrb_undef_p(result)) {
+ return mrb_nil_value();
+ }
+ return result;
+}
+
+static int
+dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, struct mrbc_args *args)
+{
+ int n = MRB_DUMP_OK;
+ mrb_irep *irep = proc->body.irep;
+
+ if (args->initname) {
+ n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
+ if (n == MRB_DUMP_INVALID_ARGUMENT) {
+ fprintf(stderr, "%s: invalid C language symbol name\n", args->initname);
+ }
+ }
+ else {
+ n = mrb_dump_irep_binary(mrb, irep, args->flags, wfp);
+ }
+ if (n != MRB_DUMP_OK) {
+ fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n);
+ }
+ return n;
+}
+
+int
+main(int argc, char **argv)
+{
+ mrb_state *mrb = mrb_open();
+ int n, result;
+ struct mrbc_args args;
+ FILE *wfp;
+ mrb_value load;
+
+ if (mrb == NULL) {
+ fputs("Invalid mrb_state, exiting mrbc\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ n = parse_args(mrb, argc, argv, &args);
+ if (n < 0) {
+ cleanup(mrb, &args);
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ if (n == argc) {
+ fprintf(stderr, "%s: no program file given\n", args.prog);
+ return EXIT_FAILURE;
+ }
+ if (args.outfile == NULL && !args.check_syntax) {
+ if (n + 1 == argc) {
+ args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT);
+ }
+ else {
+ fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog);
+ return EXIT_FAILURE;
+ }
+ }
+
+ args.idx = n;
+ load = load_file(mrb, &args);
+ if (mrb_nil_p(load)) {
+ cleanup(mrb, &args);
+ return EXIT_FAILURE;
+ }
+ if (args.check_syntax) {
+ printf("%s:%s:Syntax OK\n", args.prog, argv[n]);
+ }
+
+ if (args.check_syntax) {
+ cleanup(mrb, &args);
+ return EXIT_SUCCESS;
+ }
+
+ if (args.outfile) {
+ if (strcmp("-", args.outfile) == 0) {
+ wfp = stdout;
+ }
+ else if ((wfp = fopen(args.outfile, "wb")) == NULL) {
+ fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile);
+ return EXIT_FAILURE;
+ }
+ }
+ else {
+ fprintf(stderr, "Output file is required\n");
+ return EXIT_FAILURE;
+ }
+ result = dump_file(mrb, wfp, args.outfile, mrb_proc_ptr(load), &args);
+ fclose(wfp);
+ cleanup(mrb, &args);
+ if (result != MRB_DUMP_OK) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+void
+mrb_init_mrblib(mrb_state *mrb)
+{
+}
+
+#ifndef DISABLE_GEMS
+void
+mrb_init_mrbgems(mrb_state *mrb)
+{
+}
+
+void
+mrb_final_mrbgems(mrb_state *mrb)
+{
+}
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake
new file mode 100644
index 00000000..66d6ef80
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mrbgem.rake
@@ -0,0 +1,30 @@
+module MRuby
+ class Build
+ def exefile(name)
+ if name.is_a?(Array)
+ name.flatten.map { |n| exefile(n) }
+ elsif name !~ /\./
+ "#{name}#{exts.executable}"
+ else
+ name
+ end
+ end
+ end
+end
+
+MRuby.each_target do
+ next if kind_of? MRuby::CrossBuild
+
+ mruby_config = 'mruby-config' + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
+ mruby_config_path = "#{build_dir}/bin/#{mruby_config}"
+ @bins << mruby_config
+
+ file mruby_config_path => libfile("#{build_dir}/lib/libmruby") do |t|
+ FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name
+ config = Hash[open("#{build_dir}/lib/libmruby.flags.mak").read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}]
+ IO.write(t.name, File.open(t.name) {|f|
+ f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS|MRUBY_LIBMRUBY_PATH)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"}
+ })
+ FileUtils.chmod(0755, t.name)
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config
new file mode 100644
index 00000000..57346c03
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ --cflags) echo MRUBY_CFLAGS;;
+ --ldflags) echo MRUBY_LDFLAGS;;
+ --ldflags-before-libs) echo MRUBY_LDFLAGS_BEFORE_LIBS;;
+ --libs) echo MRUBY_LIBS;;
+ --libmruby-path) echo MRUBY_LIBMRUBY_PATH;;
+ --help) echo "Usage: mruby-config [switches]"
+ echo " switches:"
+ echo " --cflags print flags passed to compiler"
+ echo " --ldflags print flags passed to linker"
+ echo " --ldflags-before-libs print flags passed to linker before linked libraries"
+ echo " --libs print linked libraries"
+ echo " --libmruby-path print libmruby path"
+ exit 0;;
+ esac
+ shift
+done
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat
new file mode 100644
index 00000000..a1f7bfdd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby-config/mruby-config.bat
@@ -0,0 +1,42 @@
+@echo off
+
+:top
+shift
+if "%0" equ "" goto :eof
+if "%0" equ "--cflags" goto cflags
+if "%0" equ "--ldflags" goto ldflags
+if "%0" equ "--ldflags-before-libs" goto ldflagsbeforelibs
+if "%0" equ "--libs" goto libs
+if "%0" equ "--libmruby-path" goto libmrubypath
+if "%0" equ "--help" goto showhelp
+echo Invalid Option
+goto :eof
+
+:cflags
+echo MRUBY_CFLAGS
+goto top
+
+:libs
+echo MRUBY_LIBS
+goto top
+
+:ldflags
+echo MRUBY_LDFLAGS
+goto top
+
+:ldflagsbeforelibs
+echo MRUBY_LDFLAGS_BEFORE_LIBS
+goto top
+
+:libmrubypath
+echo MRUBY_LIBMRUBY_PATH
+goto top
+
+:showhelp
+echo Usage: mruby-config [switches]
+echo switches:
+echo --cflags print flags passed to compiler
+echo --ldflags print flags passed to linker
+echo --ldflags-before-libs print flags passed to linker before linked libraries
+echo --libs print linked libraries
+echo --libmruby-path print libmruby path
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb
new file mode 100644
index 00000000..b6b09018
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb
@@ -0,0 +1,60 @@
+require 'tempfile'
+
+assert('regression for #1564') do
+ o = `#{cmd('mruby')} -e #{shellquote('<<')} 2>&1`
+ assert_include o, "-e:1:2: syntax error"
+ o = `#{cmd('mruby')} -e #{shellquote('<<-')} 2>&1`
+ assert_include o, "-e:1:3: syntax error"
+end
+
+assert('regression for #1572') do
+ script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb')
+ File.write script.path, 'p "ok"'
+ system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}"
+ o = `#{cmd('mruby')} -b #{bin.path}`.strip
+ assert_equal o, '"ok"'
+end
+
+assert '$0 value' do
+ script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb')
+
+ # .rb script
+ script.write "p $0\n"
+ script.flush
+ assert_equal "\"#{script.path}\"", `#{cmd('mruby')} "#{script.path}"`.chomp
+
+ # .mrb file
+ `#{cmd('mrbc')} -o "#{bin.path}" "#{script.path}"`
+ assert_equal "\"#{bin.path}\"", `#{cmd('mruby')} -b "#{bin.path}"`.chomp
+
+ # one liner
+ assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp
+end
+
+assert '__END__', '8.6' do
+ script = Tempfile.new('test.rb')
+
+ script.write <<EOS
+p 'test'
+ __END__ = 'fin'
+p __END__
+__END__
+p 'legend'
+EOS
+ script.flush
+ assert_equal "\"test\"\n\"fin\"\n", `#{cmd('mruby')} #{script.path}`
+end
+
+assert('garbage collecting built-in classes') do
+ script = Tempfile.new('test.rb')
+
+ script.write <<RUBY
+NilClass = nil
+GC.start
+Array.dup
+print nil.class.to_s
+RUBY
+ script.flush
+ assert_equal "NilClass", `#{cmd('mruby')} #{script.path}`
+ assert_equal 0, $?.exitstatus
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake
new file mode 100644
index 00000000..fbec1384
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake
@@ -0,0 +1,12 @@
+MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mruby command'
+ spec.bins = %w(mruby)
+ spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
+ spec.add_dependency('mruby-error', :core => 'mruby-error')
+
+ if build.cxx_exception_enabled?
+ build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
new file mode 100644
index 00000000..61d4cde9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
@@ -0,0 +1,254 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/compile.h>
+#include <mruby/dump.h>
+#include <mruby/variable.h>
+
+#ifdef MRB_DISABLE_STDIO
+static void
+p(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value val = mrb_inspect(mrb, obj);
+
+ fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
+ putc('\n', stdout);
+}
+#else
+#define p(mrb,obj) mrb_p(mrb,obj)
+#endif
+
+struct _args {
+ FILE *rfp;
+ char* cmdline;
+ mrb_bool fname : 1;
+ mrb_bool mrbfile : 1;
+ mrb_bool check_syntax : 1;
+ mrb_bool verbose : 1;
+ int argc;
+ char** argv;
+};
+
+static void
+usage(const char *name)
+{
+ static const char *const usage_msg[] = {
+ "switches:",
+ "-b load and execute RiteBinary (mrb) file",
+ "-c check syntax only",
+ "-e 'command' one line of script",
+ "-v print version number, then run in verbose mode",
+ "--verbose run in verbose mode",
+ "--version print the version",
+ "--copyright print the copyright",
+ NULL
+ };
+ const char *const *p = usage_msg;
+
+ printf("Usage: %s [switches] programfile\n", name);
+ while (*p)
+ printf(" %s\n", *p++);
+}
+
+static int
+parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
+{
+ char **origargv = argv;
+ static const struct _args args_zero = { 0 };
+
+ *args = args_zero;
+
+ for (argc--,argv++; argc > 0; argc--,argv++) {
+ char *item;
+ if (argv[0][0] != '-') break;
+
+ if (strlen(*argv) <= 1) {
+ argc--; argv++;
+ args->rfp = stdin;
+ break;
+ }
+
+ item = argv[0] + 1;
+ switch (*item++) {
+ case 'b':
+ args->mrbfile = TRUE;
+ break;
+ case 'c':
+ args->check_syntax = TRUE;
+ break;
+ case 'e':
+ if (item[0]) {
+ goto append_cmdline;
+ }
+ else if (argc > 1) {
+ argc--; argv++;
+ item = argv[0];
+append_cmdline:
+ if (!args->cmdline) {
+ size_t buflen;
+ char *buf;
+
+ buflen = strlen(item) + 1;
+ buf = (char *)mrb_malloc(mrb, buflen);
+ memcpy(buf, item, buflen);
+ args->cmdline = buf;
+ }
+ else {
+ size_t cmdlinelen;
+ size_t itemlen;
+
+ cmdlinelen = strlen(args->cmdline);
+ itemlen = strlen(item);
+ args->cmdline =
+ (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
+ args->cmdline[cmdlinelen] = '\n';
+ memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
+ }
+ }
+ else {
+ printf("%s: No code specified for -e\n", *origargv);
+ return EXIT_SUCCESS;
+ }
+ break;
+ case 'v':
+ if (!args->verbose) mrb_show_version(mrb);
+ args->verbose = TRUE;
+ break;
+ case '-':
+ if (strcmp((*argv) + 2, "version") == 0) {
+ mrb_show_version(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp((*argv) + 2, "verbose") == 0) {
+ args->verbose = TRUE;
+ break;
+ }
+ else if (strcmp((*argv) + 2, "copyright") == 0) {
+ mrb_show_copyright(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ default:
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (args->rfp == NULL && args->cmdline == NULL) {
+ if (*argv == NULL) args->rfp = stdin;
+ else {
+ args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
+ if (args->rfp == NULL) {
+ printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
+ return EXIT_FAILURE;
+ }
+ args->fname = TRUE;
+ args->cmdline = argv[0];
+ argc--; argv++;
+ }
+ }
+ args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
+ memcpy(args->argv, argv, (argc+1) * sizeof(char*));
+ args->argc = argc;
+
+ return EXIT_SUCCESS;
+}
+
+static void
+cleanup(mrb_state *mrb, struct _args *args)
+{
+ if (args->rfp && args->rfp != stdin)
+ fclose(args->rfp);
+ if (!args->fname)
+ mrb_free(mrb, args->cmdline);
+ mrb_free(mrb, args->argv);
+ mrb_close(mrb);
+}
+
+int
+main(int argc, char **argv)
+{
+ mrb_state *mrb = mrb_open();
+ int n = -1;
+ int i;
+ struct _args args;
+ mrb_value ARGV;
+ mrbc_context *c;
+ mrb_value v;
+ mrb_sym zero_sym;
+
+ if (mrb == NULL) {
+ fputs("Invalid mrb_state, exiting mruby\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ n = parse_args(mrb, argc, argv, &args);
+ if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
+ cleanup(mrb, &args);
+ usage(argv[0]);
+ return n;
+ }
+ else {
+ int ai = mrb_gc_arena_save(mrb);
+ ARGV = mrb_ary_new_capa(mrb, args.argc);
+ for (i = 0; i < args.argc; i++) {
+ char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
+ if (utf8) {
+ mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
+ mrb_utf8_free(utf8);
+ }
+ }
+ mrb_define_global_const(mrb, "ARGV", ARGV);
+
+ c = mrbc_context_new(mrb);
+ if (args.verbose)
+ c->dump_result = TRUE;
+ if (args.check_syntax)
+ c->no_exec = TRUE;
+
+ /* Set $0 */
+ zero_sym = mrb_intern_lit(mrb, "$0");
+ if (args.rfp) {
+ const char *cmdline;
+ cmdline = args.cmdline ? args.cmdline : "-";
+ mrbc_filename(mrb, c, cmdline);
+ mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
+ }
+ else {
+ mrbc_filename(mrb, c, "-e");
+ mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
+ }
+
+ /* Load program */
+ if (args.mrbfile) {
+ v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
+ }
+ else if (args.rfp) {
+ v = mrb_load_file_cxt(mrb, args.rfp, c);
+ }
+ else {
+ char* utf8 = mrb_utf8_from_locale(args.cmdline, -1);
+ if (!utf8) abort();
+ v = mrb_load_string_cxt(mrb, utf8, c);
+ mrb_utf8_free(utf8);
+ }
+
+ mrb_gc_arena_restore(mrb, ai);
+ mrbc_context_free(mrb, c);
+ if (mrb->exc) {
+ if (mrb_undef_p(v)) {
+ mrb_p(mrb, mrb_obj_value(mrb->exc));
+ }
+ else {
+ mrb_print_error(mrb);
+ }
+ n = -1;
+ }
+ else if (args.check_syntax) {
+ printf("Syntax OK\n");
+ }
+ }
+ cleanup(mrb, &args);
+
+ return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb
new file mode 100644
index 00000000..bb664a2b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb
@@ -0,0 +1,73 @@
+require 'tempfile'
+
+assert('no files') do
+ o = `#{cmd('mruby-strip')} 2>&1`
+ assert_equal 1, $?.exitstatus
+ assert_equal "no files to strip", o.split("\n")[0]
+end
+
+assert('file not found') do
+ o = `#{cmd('mruby-strip')} not_found.mrb 2>&1`
+ assert_equal 1, $?.exitstatus
+ assert_equal "can't open file for reading not_found.mrb\n", o
+end
+
+assert('not irep file') do
+ t = Tempfile.new('script.rb')
+ t.write 'p test\n'
+ t.flush
+ o = `#{cmd('mruby-strip')} #{t.path} 2>&1`
+ assert_equal 1, $?.exitstatus
+ assert_equal "can't read irep file #{t.path}\n", o
+end
+
+assert('success') do
+ script_file, compiled1, compiled2 =
+ Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb')
+ script_file.write "p 'test'\n"
+ script_file.flush
+ `#{cmd('mrbc')} -g -o #{compiled1.path} #{script_file.path}`
+ `#{cmd('mrbc')} -g -o #{compiled2.path} #{script_file.path}`
+
+ o = `#{cmd('mruby-strip')} #{compiled1.path}`
+ assert_equal 0, $?.exitstatus
+ assert_equal "", o
+ assert_equal `#{cmd('mruby')} #{script_file.path}`, `#{cmd('mruby')} -b #{compiled1.path}`
+
+ o = `#{cmd('mruby-strip')} #{compiled1.path} #{compiled2.path}`
+ assert_equal 0, $?.exitstatus
+ assert_equal "", o
+end
+
+assert('check debug section') do
+ script_file, with_debug, without_debug =
+ Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb')
+ script_file.write "p 'test'\n"
+ script_file.flush
+ `#{cmd('mrbc')} -o #{without_debug.path} #{script_file.path}`
+ `#{cmd('mrbc')} -g -o #{with_debug.path} #{script_file.path}`
+
+ assert_true with_debug.size >= without_debug.size
+
+ `#{cmd('mruby-strip')} #{with_debug.path}`
+ assert_equal without_debug.size, with_debug.size
+end
+
+assert('check lv section') do
+ script_file, with_lv, without_lv =
+ Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb')
+ script_file.write <<EOS
+a, b = 0, 1
+a += b
+p Kernel.local_variables
+EOS
+ script_file.flush
+ `#{cmd('mrbc')} -o #{with_lv.path} #{script_file.path}`
+ `#{cmd('mrbc')} -o #{without_lv.path} #{script_file.path}`
+
+ `#{cmd('mruby-strip')} -l #{without_lv.path}`
+ assert_true without_lv.size < with_lv.size
+
+ assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
+ assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/mrbgem.rake
new file mode 100644
index 00000000..2abd25ee
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-bin-strip') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'irep dump debug section remover command'
+ spec.bins = %w(mruby-strip)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c
new file mode 100644
index 00000000..deb66d54
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c
@@ -0,0 +1,155 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/dump.h>
+
+struct strip_args {
+ int argc_start;
+ int argc;
+ char **argv;
+ mrb_bool lvar;
+};
+
+
+static void
+irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
+{
+ int i;
+
+ if (irep->lv) {
+ mrb_free(mrb, irep->lv);
+ irep->lv = NULL;
+ }
+
+ for (i = 0; i < irep->rlen; ++i) {
+ irep_remove_lv(mrb, irep->reps[i]);
+ }
+}
+
+static void
+print_usage(const char *f)
+{
+ printf("Usage: %s [switches] irepfiles\n", f);
+ printf("switches:\n");
+ printf(" -l, --lvar remove LVAR section too.\n");
+}
+
+static int
+parse_args(int argc, char **argv, struct strip_args *args)
+{
+ int i;
+
+ args->argc_start = 0;
+ args->argc = argc;
+ args->argv = argv;
+ args->lvar = FALSE;
+
+ for (i = 1; i < argc; ++i) {
+ const size_t len = strlen(argv[i]);
+ if (len >= 2 && argv[i][0] == '-') {
+ switch (argv[i][1]) {
+ case 'l':
+ args->lvar = TRUE;
+ break;
+ case '-':
+ if (strncmp((*argv) + 2, "lvar", len) == 0) {
+ args->lvar = TRUE;
+ break;
+ }
+ default:
+ return -1;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ args->argc_start = i;
+ return i;
+}
+
+static int
+strip(mrb_state *mrb, struct strip_args *args)
+{
+ int i;
+
+ for (i = args->argc_start; i < args->argc; ++i) {
+ char *filename;
+ FILE *rfile;
+ mrb_irep *irep;
+ FILE *wfile;
+ int dump_result;
+
+ filename = args->argv[i];
+ rfile = fopen(filename, "rb");
+ if (rfile == NULL) {
+ fprintf(stderr, "can't open file for reading %s\n", filename);
+ return EXIT_FAILURE;
+ }
+
+ irep = mrb_read_irep_file(mrb, rfile);
+ fclose(rfile);
+ if (irep == NULL) {
+ fprintf(stderr, "can't read irep file %s\n", filename);
+ return EXIT_FAILURE;
+ }
+
+ /* clear lv if --lvar is enabled */
+ if (args->lvar) {
+ irep_remove_lv(mrb, irep);
+ }
+
+ wfile = fopen(filename, "wb");
+ if (wfile == NULL) {
+ fprintf(stderr, "can't open file for writing %s\n", filename);
+ mrb_irep_decref(mrb, irep);
+ return EXIT_FAILURE;
+ }
+
+ /* debug flag must always be false */
+ dump_result = mrb_dump_irep_binary(mrb, irep, FALSE, wfile);
+
+ fclose(wfile);
+ mrb_irep_decref(mrb, irep);
+
+ if (dump_result != MRB_DUMP_OK) {
+ fprintf(stderr, "error occurred during dumping %s\n", filename);
+ return EXIT_FAILURE;
+ }
+ }
+ return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct strip_args args;
+ int args_result;
+ mrb_state *mrb;
+ int ret;
+
+ if (argc <= 1) {
+ printf("no files to strip\n");
+ print_usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ args_result = parse_args(argc, argv, &args);
+ if (args_result < 0) {
+ print_usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ mrb = mrb_open_core(mrb_default_allocf, NULL);
+ if (mrb == NULL) {
+ fputs("Invalid mrb_state, exiting mruby-strip\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ ret = strip(mrb, &args);
+
+ mrb_close(mrb);
+ return ret;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/mrbgem.rake
new file mode 100644
index 00000000..a384b1ee
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-class-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'class/module extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/src/class.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/src/class.c
new file mode 100644
index 00000000..5506c482
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/src/class.c
@@ -0,0 +1,30 @@
+#include "mruby.h"
+#include "mruby/class.h"
+#include "mruby/string.h"
+
+static mrb_value
+mrb_mod_name(mrb_state *mrb, mrb_value self)
+{
+ mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self));
+ return mrb_nil_p(name)? name : mrb_str_dup(mrb, name);
+}
+
+static mrb_value
+mrb_mod_singleton_class_p(mrb_state *mrb, mrb_value self)
+{
+ return mrb_bool_value(mrb_type(self) == MRB_TT_SCLASS);
+}
+
+void
+mrb_mruby_class_ext_gem_init(mrb_state *mrb)
+{
+ struct RClass *mod = mrb->module_class;
+
+ mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE());
+ mrb_define_method(mrb, mod, "singleton_class?", mrb_mod_singleton_class_p, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_class_ext_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/test/module.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/test/module.rb
new file mode 100644
index 00000000..65abde10
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-class-ext/test/module.rb
@@ -0,0 +1,34 @@
+assert 'Module#name' do
+ module Outer
+ class Inner; end
+ const_set :SetInner, Class.new
+ end
+
+ assert_equal 'Outer', Outer.name
+ assert_equal 'Outer::Inner', Outer::Inner.name
+ assert_equal 'Outer::SetInner', Outer::SetInner.name
+
+ outer = Module.new do
+ const_set :SetInner, Class.new
+ end
+ Object.const_set :SetOuter, outer
+
+ assert_equal 'SetOuter', SetOuter.name
+ assert_equal 'SetOuter::SetInner', SetOuter::SetInner.name
+
+ mod = Module.new
+ cls = Class.new
+
+ assert_nil mod.name
+ assert_nil cls.name
+end
+
+assert 'Module#singleton_class?' do
+ mod = Module.new
+ cls = Class.new
+ scl = cls.singleton_class
+
+ assert_false mod.singleton_class?
+ assert_false cls.singleton_class?
+ assert_true scl.singleton_class?
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb
new file mode 100644
index 00000000..f4d9208b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/bintest/mrbc.rb
@@ -0,0 +1,30 @@
+require 'tempfile'
+
+assert('Compiling multiple files without new line in last line. #2361') do
+ a, b, out = Tempfile.new('a.rb'), Tempfile.new('b.rb'), Tempfile.new('out.mrb')
+ a.write('module A; end')
+ a.flush
+ b.write('module B; end')
+ b.flush
+ result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} #{b.path} 2>&1`
+ assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
+ assert_equal 0, $?.exitstatus
+end
+
+assert('parsing function with void argument') do
+ a, out = Tempfile.new('a.rb'), Tempfile.new('out.mrb')
+ a.write('f ()')
+ a.flush
+ result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1`
+ assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp
+ assert_equal 0, $?.exitstatus
+end
+
+assert('embedded document with invalid terminator') do
+ a, out = Tempfile.new('a.rb'), Tempfile.new('out.mrb')
+ a.write("=begin\n=endx\n")
+ a.flush
+ result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} 2>&1`
+ assert_equal "#{a.path}:3:0: embedded document meets end of file", result.chomp
+ assert_equal 1, $?.exitstatus
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/codegen.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/codegen.c
new file mode 100644
index 00000000..8f15a9b1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/codegen.c
@@ -0,0 +1,3026 @@
+/*
+** codegen.c - mruby code generator
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/proc.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include <mruby/debug.h>
+#include "node.h"
+#include <mruby/opcode.h>
+#include <mruby/re.h>
+#include <mruby/throw.h>
+
+#ifndef MRB_CODEGEN_LEVEL_MAX
+#define MRB_CODEGEN_LEVEL_MAX 1024
+#endif
+
+typedef mrb_ast_node node;
+typedef struct mrb_parser_state parser_state;
+
+enum looptype {
+ LOOP_NORMAL,
+ LOOP_BLOCK,
+ LOOP_FOR,
+ LOOP_BEGIN,
+ LOOP_RESCUE,
+};
+
+struct loopinfo {
+ enum looptype type;
+ int pc1, pc2, pc3, acc;
+ int ensure_level;
+ struct loopinfo *prev;
+};
+
+typedef struct scope {
+ mrb_state *mrb;
+ mrb_pool *mpool;
+ struct mrb_jmpbuf jmp;
+
+ struct scope *prev;
+
+ node *lv;
+
+ int sp;
+ int pc;
+ int lastlabel;
+ int ainfo:15;
+ mrb_bool mscope:1;
+
+ struct loopinfo *loop;
+ int ensure_level;
+ char const *filename;
+ uint16_t lineno;
+
+ mrb_code *iseq;
+ uint16_t *lines;
+ int icapa;
+
+ mrb_irep *irep;
+ int pcapa, scapa, rcapa;
+
+ uint16_t nlocals;
+ uint16_t nregs;
+ int ai;
+
+ int debug_start_pos;
+ uint16_t filename_index;
+ parser_state* parser;
+
+ int rlev; /* recursion levels */
+} codegen_scope;
+
+static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
+static void scope_finish(codegen_scope *s);
+static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
+static void loop_break(codegen_scope *s, node *tree);
+static void loop_pop(codegen_scope *s, int val);
+
+static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
+static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
+
+static void codegen(codegen_scope *s, node *tree, int val);
+static void raise_error(codegen_scope *s, const char *msg);
+
+static void
+codegen_error(codegen_scope *s, const char *message)
+{
+ if (!s) return;
+ while (s->prev) {
+ codegen_scope *tmp = s->prev;
+ mrb_free(s->mrb, s->iseq);
+ mrb_pool_close(s->mpool);
+ s = tmp;
+ }
+#ifndef MRB_DISABLE_STDIO
+ if (s->filename && s->lineno) {
+ fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
+ }
+ else {
+ fprintf(stderr, "codegen error: %s\n", message);
+ }
+#endif
+ MRB_THROW(&s->jmp);
+}
+
+static void*
+codegen_palloc(codegen_scope *s, size_t len)
+{
+ void *p = mrb_pool_alloc(s->mpool, len);
+
+ if (!p) codegen_error(s, "pool memory allocation");
+ return p;
+}
+
+static void*
+codegen_malloc(codegen_scope *s, size_t len)
+{
+ void *p = mrb_malloc_simple(s->mrb, len);
+
+ if (!p) codegen_error(s, "mrb_malloc");
+ return p;
+}
+
+static void*
+codegen_realloc(codegen_scope *s, void *p, size_t len)
+{
+ p = mrb_realloc_simple(s->mrb, p, len);
+
+ if (!p && len > 0) codegen_error(s, "mrb_realloc");
+ return p;
+}
+
+static int
+new_label(codegen_scope *s)
+{
+ s->lastlabel = s->pc;
+ return s->pc;
+}
+
+static inline int
+genop(codegen_scope *s, mrb_code i)
+{
+ if (s->pc == s->icapa) {
+ s->icapa *= 2;
+ s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
+ if (s->lines) {
+ s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
+ s->irep->lines = s->lines;
+ }
+ }
+ s->iseq[s->pc] = i;
+ if (s->lines) {
+ s->lines[s->pc] = s->lineno;
+ }
+ return s->pc++;
+}
+
+#define NOVAL 0
+#define VAL 1
+
+static mrb_bool
+no_optimize(codegen_scope *s)
+{
+ if (s && s->parser && s->parser->no_optimize)
+ return TRUE;
+ return FALSE;
+}
+
+static int
+genop_peep(codegen_scope *s, mrb_code i, int val)
+{
+ /* peephole optimization */
+ if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) {
+ mrb_code i0 = s->iseq[s->pc-1];
+ int c1 = GET_OPCODE(i);
+ int c0 = GET_OPCODE(i0);
+
+ switch (c1) {
+ case OP_MOVE:
+ if (GETARG_A(i) == GETARG_B(i)) {
+ /* skip useless OP_MOVE */
+ return 0;
+ }
+ if (val) break;
+ switch (c0) {
+ case OP_MOVE:
+ if (GETARG_A(i) == GETARG_A(i0)) {
+ /* skip overriden OP_MOVE */
+ s->pc--;
+ s->iseq[s->pc] = i;
+ }
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) {
+ /* skip swapping OP_MOVE */
+ return 0;
+ }
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->pc--;
+ return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val);
+ }
+ break;
+ case OP_LOADI:
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
+ return 0;
+ }
+ break;
+ case OP_ARRAY:
+ case OP_HASH:
+ case OP_RANGE:
+ case OP_AREF:
+ case OP_GETUPVAR:
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
+ return 0;
+ }
+ break;
+ case OP_LOADSYM:
+ case OP_GETGLOBAL:
+ case OP_GETIV:
+ case OP_GETCV:
+ case OP_GETCONST:
+ case OP_GETSPECIAL:
+ case OP_LOADL:
+ case OP_STRING:
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
+ return 0;
+ }
+ break;
+ case OP_SCLASS:
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
+ return 0;
+ }
+ break;
+ case OP_LOADNIL:
+ case OP_LOADSELF:
+ case OP_LOADT:
+ case OP_LOADF:
+ case OP_OCLASS:
+ if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case OP_SETIV:
+ case OP_SETCV:
+ case OP_SETCONST:
+ case OP_SETMCNST:
+ case OP_SETGLOBAL:
+ if (val) break;
+ if (c0 == OP_MOVE) {
+ if (GETARG_A(i) == GETARG_A(i0)) {
+ s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
+ return 0;
+ }
+ }
+ break;
+ case OP_SETUPVAR:
+ if (val) break;
+ if (c0 == OP_MOVE) {
+ if (GETARG_A(i) == GETARG_A(i0)) {
+ s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
+ return 0;
+ }
+ }
+ break;
+ case OP_EPOP:
+ if (c0 == OP_EPOP) {
+ s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
+ return 0;
+ }
+ break;
+ case OP_POPERR:
+ if (c0 == OP_POPERR) {
+ s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
+ return 0;
+ }
+ break;
+ case OP_RETURN:
+ switch (c0) {
+ case OP_RETURN:
+ return 0;
+ case OP_MOVE:
+ if (GETARG_A(i0) >= s->nlocals) {
+ s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
+ return 0;
+ }
+ break;
+ case OP_SETIV:
+ case OP_SETCV:
+ case OP_SETCONST:
+ case OP_SETMCNST:
+ case OP_SETUPVAR:
+ case OP_SETGLOBAL:
+ s->pc--;
+ genop_peep(s, i0, NOVAL);
+ i0 = s->iseq[s->pc-1];
+ return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
+#if 0
+ case OP_SEND:
+ if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
+ s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
+ return;
+ }
+ break;
+#endif
+ default:
+ break;
+ }
+ break;
+ case OP_ADD:
+ case OP_SUB:
+ if (c0 == OP_LOADI) {
+ int c = GETARG_sBx(i0);
+
+ if (c1 == OP_SUB) c = -c;
+ if (c > 127 || c < -127) break;
+ if (0 <= c)
+ s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
+ else
+ s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
+ return 0;
+ }
+ case OP_STRCAT:
+ if (c0 == OP_STRING) {
+ mrb_value v = s->irep->pool[GETARG_Bx(i0)];
+
+ if (mrb_string_p(v) && RSTRING_LEN(v) == 0) {
+ s->pc--;
+ return 0;
+ }
+ }
+ if (c0 == OP_LOADNIL) {
+ if (GETARG_B(i) == GETARG_A(i0)) {
+ s->pc--;
+ return 0;
+ }
+ }
+ break;
+ case OP_JMPIF:
+ case OP_JMPNOT:
+ if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
+ s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
+ return s->pc-1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return genop(s, i);
+}
+
+static void
+scope_error(codegen_scope *s)
+{
+ exit(EXIT_FAILURE);
+}
+
+static inline void
+dispatch(codegen_scope *s, int pc)
+{
+ int diff = s->pc - pc;
+ mrb_code i = s->iseq[pc];
+ int c = GET_OPCODE(i);
+
+ s->lastlabel = s->pc;
+ switch (c) {
+ case OP_JMP:
+ case OP_JMPIF:
+ case OP_JMPNOT:
+ case OP_ONERR:
+ break;
+ default:
+#ifndef MRB_DISABLE_STDIO
+ fprintf(stderr, "bug: dispatch on non JMP op\n");
+#endif
+ scope_error(s);
+ break;
+ }
+ if (diff > MAXARG_sBx) {
+ codegen_error(s, "too distant jump address");
+ }
+ s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
+}
+
+static void
+dispatch_linked(codegen_scope *s, int pc)
+{
+ mrb_code i;
+ int pos;
+
+ if (!pc) return;
+ for (;;) {
+ i = s->iseq[pc];
+ pos = GETARG_sBx(i);
+ dispatch(s, pc);
+ if (!pos) break;
+ pc = pos;
+ }
+}
+
+#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
+static void
+push_(codegen_scope *s)
+{
+ if (s->sp > 511) {
+ codegen_error(s, "too complex expression");
+ }
+ s->sp++;
+ nregs_update;
+}
+
+static void
+push_n_(codegen_scope *s, int n)
+{
+ if (s->sp+n > 511) {
+ codegen_error(s, "too complex expression");
+ }
+ s->sp+=n;
+ nregs_update;
+}
+
+#define push() push_(s)
+#define push_n(n) push_n_(s,n)
+#define pop_(s) ((s)->sp--)
+#define pop() pop_(s)
+#define pop_n(n) (s->sp-=(n))
+#define cursp() (s->sp)
+
+static inline int
+new_lit(codegen_scope *s, mrb_value val)
+{
+ int i;
+ mrb_value *pv;
+
+ switch (mrb_type(val)) {
+ case MRB_TT_STRING:
+ for (i=0; i<s->irep->plen; i++) {
+ mrb_int len;
+ pv = &s->irep->pool[i];
+
+ if (mrb_type(*pv) != MRB_TT_STRING) continue;
+ if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
+ if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
+ return i;
+ }
+ break;
+ case MRB_TT_FLOAT:
+ for (i=0; i<s->irep->plen; i++) {
+ pv = &s->irep->pool[i];
+ if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
+ if (mrb_float(*pv) == mrb_float(val)) return i;
+ }
+ break;
+ case MRB_TT_FIXNUM:
+ for (i=0; i<s->irep->plen; i++) {
+ pv = &s->irep->pool[i];
+ if (!mrb_fixnum_p(*pv)) continue;
+ if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
+ }
+ break;
+ default:
+ /* should not happen */
+ return 0;
+ }
+
+ if (s->irep->plen == s->pcapa) {
+ s->pcapa *= 2;
+ s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
+ }
+
+ pv = &s->irep->pool[s->irep->plen];
+ i = s->irep->plen++;
+
+ switch (mrb_type(val)) {
+ case MRB_TT_STRING:
+ *pv = mrb_str_pool(s->mrb, val);
+ break;
+
+ case MRB_TT_FLOAT:
+#ifdef MRB_WORD_BOXING
+ *pv = mrb_float_pool(s->mrb, mrb_float(val));
+ break;
+#endif
+ case MRB_TT_FIXNUM:
+ *pv = val;
+ break;
+
+ default:
+ /* should not happen */
+ break;
+ }
+ return i;
+}
+
+/* method symbols should be fit in 9 bits */
+#define MAXMSYMLEN 512
+/* maximum symbol numbers */
+#define MAXSYMLEN 65536
+
+static int
+new_msym(codegen_scope *s, mrb_sym sym)
+{
+ int i, len;
+
+ mrb_assert(s->irep);
+
+ len = s->irep->slen;
+ if (len > MAXMSYMLEN) len = MAXMSYMLEN;
+ for (i=0; i<len; i++) {
+ if (s->irep->syms[i] == sym) return i;
+ if (s->irep->syms[i] == 0) break;
+ }
+ if (i == MAXMSYMLEN) {
+ codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
+ }
+ s->irep->syms[i] = sym;
+ if (i == s->irep->slen) s->irep->slen++;
+ return i;
+}
+
+static int
+new_sym(codegen_scope *s, mrb_sym sym)
+{
+ int i;
+
+ for (i=0; i<s->irep->slen; i++) {
+ if (s->irep->syms[i] == sym) return i;
+ }
+ if (s->irep->slen == MAXSYMLEN) {
+ codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
+ }
+
+ if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
+ s->scapa = MAXSYMLEN;
+ s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
+ for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
+ static const mrb_sym mrb_sym_zero = { 0 };
+ s->irep->syms[i] = mrb_sym_zero;
+ }
+ s->irep->slen = MAXMSYMLEN;
+ }
+ s->irep->syms[s->irep->slen] = sym;
+ return s->irep->slen++;
+}
+
+static int
+node_len(node *tree)
+{
+ int n = 0;
+
+ while (tree) {
+ n++;
+ tree = tree->cdr;
+ }
+ return n;
+}
+
+#define nsym(x) ((mrb_sym)(intptr_t)(x))
+#define lv_name(lv) nsym((lv)->car)
+static int
+lv_idx(codegen_scope *s, mrb_sym id)
+{
+ node *lv = s->lv;
+ int n = 1;
+
+ while (lv) {
+ if (lv_name(lv) == id) return n;
+ n++;
+ lv = lv->cdr;
+ }
+ return 0;
+}
+
+static void
+for_body(codegen_scope *s, node *tree)
+{
+ codegen_scope *prev = s;
+ int idx;
+ struct loopinfo *lp;
+ node *n2;
+ mrb_code c;
+
+ /* generate receiver */
+ codegen(s, tree->cdr->car, VAL);
+ /* generate loop-block */
+ s = scope_new(s->mrb, s, NULL);
+ if (s == NULL) {
+ raise_error(prev, "unexpected scope");
+ }
+
+ push(); /* push for a block parameter */
+
+ /* generate loop variable */
+ n2 = tree->car;
+ genop(s, MKOP_Ax(OP_ENTER, 0x40000));
+ if (n2->car && !n2->car->cdr && !n2->cdr) {
+ gen_assignment(s, n2->car->car, 1, NOVAL);
+ }
+ else {
+ gen_vmassignment(s, n2, 1, VAL);
+ }
+ /* construct loop */
+ lp = loop_push(s, LOOP_FOR);
+ lp->pc2 = new_label(s);
+
+ /* loop body */
+ codegen(s, tree->cdr->cdr->car, VAL);
+ pop();
+ if (s->pc > 0) {
+ c = s->iseq[s->pc-1];
+ if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ }
+ loop_pop(s, NOVAL);
+ scope_finish(s);
+ s = prev;
+ genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
+ push();pop(); /* space for a block */
+ pop();
+ idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
+ genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
+}
+
+static int
+lambda_body(codegen_scope *s, node *tree, int blk)
+{
+ mrb_code c;
+ codegen_scope *parent = s;
+ s = scope_new(s->mrb, s, tree->car);
+ if (s == NULL) {
+ raise_error(parent, "unexpected scope");
+ }
+
+ s->mscope = !blk;
+
+ if (blk) {
+ struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
+ lp->pc1 = new_label(s);
+ }
+ tree = tree->cdr;
+ if (tree->car) {
+ mrb_aspec a;
+ int ma, oa, ra, pa, ka, kd, ba;
+ int pos, i;
+ node *n, *opt;
+
+ ma = node_len(tree->car->car);
+ n = tree->car->car;
+ while (n) {
+ n = n->cdr;
+ }
+ oa = node_len(tree->car->cdr->car);
+ ra = tree->car->cdr->cdr->car ? 1 : 0;
+ pa = node_len(tree->car->cdr->cdr->cdr->car);
+ ka = kd = 0;
+ ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
+
+ if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
+ codegen_error(s, "too many formal arguments");
+ }
+ a = ((mrb_aspec)(ma & 0x1f) << 18)
+ | ((mrb_aspec)(oa & 0x1f) << 13)
+ | ((ra & 1) << 12)
+ | ((pa & 0x1f) << 7)
+ | ((ka & 0x1f) << 2)
+ | ((kd & 1)<< 1)
+ | (ba & 1);
+ s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
+ | ((ra & 1) << 5)
+ | (pa & 0x1f);
+ genop(s, MKOP_Ax(OP_ENTER, a));
+ pos = new_label(s);
+ for (i=0; i<oa; i++) {
+ new_label(s);
+ genop(s, MKOP_sBx(OP_JMP, 0));
+ }
+ if (oa > 0) {
+ genop(s, MKOP_sBx(OP_JMP, 0));
+ }
+ opt = tree->car->cdr->car;
+ i = 0;
+ while (opt) {
+ int idx;
+
+ dispatch(s, pos+i);
+ codegen(s, opt->car->cdr, VAL);
+ idx = lv_idx(s, nsym(opt->car->car));
+ pop();
+ genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
+ i++;
+ opt = opt->cdr;
+ }
+ if (oa > 0) {
+ dispatch(s, pos+i);
+ }
+ }
+ codegen(s, tree->cdr->car, VAL);
+ pop();
+ if (s->pc > 0) {
+ c = s->iseq[s->pc-1];
+ if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
+ if (s->nregs == 0) {
+ genop(s, MKOP_A(OP_LOADNIL, 0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
+ else {
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ }
+ }
+ }
+ if (blk) {
+ loop_pop(s, NOVAL);
+ }
+ scope_finish(s);
+ return parent->irep->rlen - 1;
+}
+
+static int
+scope_body(codegen_scope *s, node *tree, int val)
+{
+ codegen_scope *scope = scope_new(s->mrb, s, tree->car);
+ if (scope == NULL) {
+ raise_error(s, "unexpected scope");
+ }
+
+ codegen(scope, tree->cdr, VAL);
+ if (!s->iseq) {
+ genop(scope, MKOP_A(OP_STOP, 0));
+ }
+ else if (!val) {
+ genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
+ else {
+ if (scope->nregs == 0) {
+ genop(scope, MKOP_A(OP_LOADNIL, 0));
+ genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
+ else {
+ genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
+ }
+ }
+ scope_finish(scope);
+ if (!s->irep) {
+ /* should not happen */
+ return 0;
+ }
+ return s->irep->rlen - 1;
+}
+
+#define nint(x) ((int)(intptr_t)(x))
+#define nchar(x) ((char)(intptr_t)(x))
+
+static mrb_bool
+nosplat(node *t)
+{
+ while (t) {
+ if (nint(t->car->car) == NODE_SPLAT) return FALSE;
+ t = t->cdr;
+ }
+ return TRUE;
+}
+
+static mrb_sym
+attrsym(codegen_scope *s, mrb_sym a)
+{
+ const char *name;
+ mrb_int len;
+ char *name2;
+
+ name = mrb_sym2name_len(s->mrb, a, &len);
+ name2 = (char *)codegen_palloc(s,
+ (size_t)len
+ + 1 /* '=' */
+ + 1 /* '\0' */
+ );
+ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
+ memcpy(name2, name, (size_t)len);
+ name2[len] = '=';
+ name2[len+1] = '\0';
+
+ return mrb_intern(s->mrb, name2, len+1);
+}
+
+#define CALL_MAXARGS 127
+
+static int
+gen_values(codegen_scope *s, node *t, int val, int extra)
+{
+ int n = 0;
+ int is_splat;
+
+ while (t) {
+ is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
+ if (
+ n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
+ || is_splat) {
+ if (val) {
+ if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
+ codegen(s, t->car->cdr, VAL);
+ pop();
+ }
+ else {
+ pop_n(n);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
+ push();
+ codegen(s, t->car, VAL);
+ pop(); pop();
+ if (is_splat) {
+ genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
+ }
+ else {
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ }
+ }
+ t = t->cdr;
+ while (t) {
+ push();
+ codegen(s, t->car, VAL);
+ pop(); pop();
+ if (nint(t->car->car) == NODE_SPLAT) {
+ genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
+ }
+ else {
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ }
+ t = t->cdr;
+ }
+ }
+ else {
+ while (t) {
+ codegen(s, t->car, NOVAL);
+ t = t->cdr;
+ }
+ }
+ return -1;
+ }
+ /* normal (no splat) mode */
+ codegen(s, t->car, val);
+ n++;
+ t = t->cdr;
+ }
+ return n;
+}
+
+static void
+gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
+{
+ mrb_sym sym = name ? name : nsym(tree->cdr->car);
+ int idx, skip = 0;
+ int n = 0, noop = 0, sendv = 0, blk = 0;
+
+ codegen(s, tree->car, VAL); /* receiver */
+ if (safe) {
+ int recv = cursp()-1;
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
+ push_n(2); pop_n(2); /* space for one arg and a block */
+ pop();
+ idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
+ genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
+ skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
+ }
+ idx = new_msym(s, sym);
+ tree = tree->cdr->cdr->car;
+ if (tree) {
+ n = gen_values(s, tree->car, VAL, sp?1:0);
+ if (n < 0) {
+ n = noop = sendv = 1;
+ push();
+ }
+ }
+ if (sp) {
+ if (sendv) {
+ pop();
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
+ push();
+ }
+ else {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
+ push();
+ n++;
+ }
+ }
+ if (tree && tree->cdr) {
+ noop = 1;
+ codegen(s, tree->cdr, VAL);
+ pop();
+ }
+ else {
+ blk = cursp();
+ }
+ push();pop();
+ pop_n(n+1);
+ {
+ mrb_int symlen;
+ const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
+
+ if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
+ genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
+ }
+ else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
+ genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
+ }
+ else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
+ genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
+ }
+ else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
+ genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
+ }
+ else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
+ genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
+ }
+ else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
+ genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
+ }
+ else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
+ genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
+ }
+ else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
+ genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
+ }
+ else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
+ genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
+ }
+ else {
+ if (sendv) n = CALL_MAXARGS;
+ if (blk > 0) { /* no block */
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
+ }
+ else {
+ genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
+ }
+ }
+ }
+ if (safe) {
+ dispatch(s, skip);
+ }
+ if (val) {
+ push();
+ }
+}
+
+static void
+gen_assignment(codegen_scope *s, node *tree, int sp, int val)
+{
+ int idx;
+ int type = nint(tree->car);
+
+ tree = tree->cdr;
+ switch (type) {
+ case NODE_GVAR:
+ idx = new_sym(s, nsym(tree));
+ genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
+ break;
+ case NODE_LVAR:
+ idx = lv_idx(s, nsym(tree));
+ if (idx > 0) {
+ if (idx != sp) {
+ genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
+ }
+ break;
+ }
+ else { /* upvar */
+ int lv = 0;
+ codegen_scope *up = s->prev;
+
+ while (up) {
+ idx = lv_idx(up, nsym(tree));
+ if (idx > 0) {
+ genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
+ break;
+ }
+ lv++;
+ up = up->prev;
+ }
+ }
+ break;
+ case NODE_IVAR:
+ idx = new_sym(s, nsym(tree));
+ genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
+ break;
+ case NODE_CVAR:
+ idx = new_sym(s, nsym(tree));
+ genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
+ break;
+ case NODE_CONST:
+ idx = new_sym(s, nsym(tree));
+ genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
+ break;
+ case NODE_COLON2:
+ idx = new_sym(s, nsym(tree->cdr));
+ genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
+ push();
+ codegen(s, tree->car, VAL);
+ pop_n(2);
+ genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
+ break;
+
+ case NODE_CALL:
+ case NODE_SCALL:
+ push();
+ gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
+ type == NODE_SCALL);
+ pop();
+ if (val) {
+ genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
+ }
+ break;
+
+ case NODE_MASGN:
+ gen_vmassignment(s, tree->car, sp, val);
+ break;
+
+ /* splat without assignment */
+ case NODE_NIL:
+ break;
+
+ default:
+#ifndef MRB_DISABLE_STDIO
+ fprintf(stderr, "unknown lhs %d\n", type);
+#endif
+ break;
+ }
+ if (val) push();
+}
+
+static void
+gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
+{
+ int n = 0, post = 0;
+ node *t, *p;
+
+ if (tree->car) { /* pre */
+ t = tree->car;
+ n = 0;
+ while (t) {
+ genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
+ gen_assignment(s, t->car, cursp(), NOVAL);
+ n++;
+ t = t->cdr;
+ }
+ }
+ t = tree->cdr;
+ if (t) {
+ if (t->cdr) { /* post count */
+ p = t->cdr->car;
+ while (p) {
+ post++;
+ p = p->cdr;
+ }
+ }
+ if (val) {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
+ }
+ else {
+ pop();
+ }
+ push_n(post);
+ pop_n(post);
+ genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
+ n = 1;
+ if (t->car) { /* rest */
+ gen_assignment(s, t->car, cursp(), NOVAL);
+ }
+ if (t->cdr && t->cdr->car) {
+ t = t->cdr->car;
+ while (t) {
+ gen_assignment(s, t->car, cursp()+n, NOVAL);
+ t = t->cdr;
+ n++;
+ }
+ }
+ if (!val) {
+ push();
+ }
+ }
+}
+
+static void
+gen_send_intern(codegen_scope *s)
+{
+ push();pop(); /* space for a block */
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
+ push();
+}
+static void
+gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
+{
+ if (val) {
+ int i = 0, j = 0;
+
+ while (tree) {
+ switch (nint(tree->car->car)) {
+ case NODE_STR:
+ if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
+ break;
+ /* fall through */
+ case NODE_BEGIN:
+ codegen(s, tree->car, VAL);
+ ++j;
+ break;
+
+ case NODE_LITERAL_DELIM:
+ if (j > 0) {
+ j = 0;
+ ++i;
+ if (sym)
+ gen_send_intern(s);
+ }
+ break;
+ }
+ if (j >= 2) {
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ j = 1;
+ }
+ tree = tree->cdr;
+ }
+ if (j > 0) {
+ ++i;
+ if (sym)
+ gen_send_intern(s);
+ }
+ pop_n(i);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
+ push();
+ }
+ else {
+ while (tree) {
+ switch (nint(tree->car->car)) {
+ case NODE_BEGIN: case NODE_BLOCK:
+ codegen(s, tree->car, NOVAL);
+ }
+ tree = tree->cdr;
+ }
+ }
+}
+
+static void
+raise_error(codegen_scope *s, const char *msg)
+{
+ int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
+
+ genop(s, MKOP_ABx(OP_ERR, 1, idx));
+}
+
+static double
+readint_float(codegen_scope *s, const char *p, int base)
+{
+ const char *e = p + strlen(p);
+ double f = 0;
+ int n;
+
+ if (*p == '+') p++;
+ while (p < e) {
+ char c = *p;
+ c = tolower((unsigned char)c);
+ for (n=0; n<base; n++) {
+ if (mrb_digitmap[n] == c) {
+ f *= base;
+ f += n;
+ break;
+ }
+ }
+ if (n == base) {
+ codegen_error(s, "malformed readint input");
+ }
+ p++;
+ }
+ return f;
+}
+
+static mrb_int
+readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
+{
+ const char *e = p + strlen(p);
+ mrb_int result = 0;
+ int n;
+
+ mrb_assert(base >= 2 && base <= 36);
+ if (*p == '+') p++;
+ while (p < e) {
+ char c = *p;
+ c = tolower((unsigned char)c);
+ for (n=0; n<base; n++) {
+ if (mrb_digitmap[n] == c) {
+ break;
+ }
+ }
+ if (n == base) {
+ codegen_error(s, "malformed readint input");
+ }
+
+ if (neg) {
+ if ((MRB_INT_MIN + n)/base > result) {
+ *overflow = TRUE;
+ return 0;
+ }
+ result *= base;
+ result -= n;
+ }
+ else {
+ if ((MRB_INT_MAX - n)/base < result) {
+ *overflow = TRUE;
+ return 0;
+ }
+ result *= base;
+ result += n;
+ }
+ p++;
+ }
+ *overflow = FALSE;
+ return result;
+}
+
+static void
+gen_retval(codegen_scope *s, node *tree)
+{
+ if (nint(tree->car) == NODE_SPLAT) {
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
+ push();
+ codegen(s, tree, VAL);
+ pop(); pop();
+ genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
+ }
+ else {
+ codegen(s, tree, VAL);
+ pop();
+ }
+}
+
+static void
+codegen(codegen_scope *s, node *tree, int val)
+{
+ int nt;
+ int rlev = s->rlev;
+
+ if (!tree) {
+ if (val) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ }
+ return;
+ }
+
+ s->rlev++;
+ if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
+ codegen_error(s, "too complex expression");
+ }
+ if (s->irep && s->filename_index != tree->filename_index) {
+ s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
+ mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
+ s->debug_start_pos = s->pc;
+ s->filename_index = tree->filename_index;
+ s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
+ }
+
+ nt = nint(tree->car);
+ s->lineno = tree->lineno;
+ tree = tree->cdr;
+ switch (nt) {
+ case NODE_BEGIN:
+ if (val && !tree) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ }
+ while (tree) {
+ codegen(s, tree->car, tree->cdr ? NOVAL : val);
+ tree = tree->cdr;
+ }
+ break;
+
+ case NODE_RESCUE:
+ {
+ int onerr, noexc, exend, pos1, pos2, tmp;
+ struct loopinfo *lp;
+
+ if (tree->car == NULL) goto exit;
+ onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
+ lp = loop_push(s, LOOP_BEGIN);
+ lp->pc1 = onerr;
+ codegen(s, tree->car, VAL);
+ pop();
+ lp->type = LOOP_RESCUE;
+ noexc = genop(s, MKOP_Bx(OP_JMP, 0));
+ dispatch(s, onerr);
+ tree = tree->cdr;
+ exend = 0;
+ pos1 = 0;
+ if (tree->car) {
+ node *n2 = tree->car;
+ int exc = cursp();
+
+ genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
+ push();
+ while (n2) {
+ node *n3 = n2->car;
+ node *n4 = n3->car;
+
+ if (pos1) dispatch(s, pos1);
+ pos2 = 0;
+ do {
+ if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
+ codegen(s, n4->car, VAL);
+ genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
+ push_n(2); pop_n(2); /* space for one arg and a block */
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
+ }
+ else {
+ if (n4) {
+ codegen(s, n4->car, VAL);
+ }
+ else {
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
+ push();
+ }
+ pop();
+ genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
+ }
+ tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ pos2 = tmp;
+ if (n4) {
+ n4 = n4->cdr;
+ }
+ } while (n4);
+ pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch_linked(s, pos2);
+
+ pop();
+ if (n3->cdr->car) {
+ gen_assignment(s, n3->cdr->car, exc, NOVAL);
+ }
+ if (n3->cdr->cdr->car) {
+ codegen(s, n3->cdr->cdr->car, val);
+ if (val) pop();
+ }
+ tmp = genop(s, MKOP_sBx(OP_JMP, exend));
+ exend = tmp;
+ n2 = n2->cdr;
+ push();
+ }
+ if (pos1) {
+ dispatch(s, pos1);
+ genop(s, MKOP_A(OP_RAISE, exc));
+ }
+ }
+ pop();
+ tree = tree->cdr;
+ dispatch(s, noexc);
+ genop(s, MKOP_A(OP_POPERR, 1));
+ if (tree->car) {
+ codegen(s, tree->car, val);
+ }
+ else if (val) {
+ push();
+ }
+ dispatch_linked(s, exend);
+ loop_pop(s, NOVAL);
+ }
+ break;
+
+ case NODE_ENSURE:
+ if (!tree->cdr || !tree->cdr->cdr ||
+ (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
+ tree->cdr->cdr->cdr)) {
+ int idx;
+ int epush = s->pc;
+
+ genop(s, MKOP_Bx(OP_EPUSH, 0));
+ s->ensure_level++;
+ codegen(s, tree->car, val);
+ idx = scope_body(s, tree->cdr, NOVAL);
+ s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
+ s->ensure_level--;
+ genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
+ }
+ else { /* empty ensure ignored */
+ codegen(s, tree->car, val);
+ }
+ break;
+
+ case NODE_LAMBDA:
+ if (val) {
+ int idx = lambda_body(s, tree, 1);
+
+ genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
+ push();
+ }
+ break;
+
+ case NODE_BLOCK:
+ if (val) {
+ int idx = lambda_body(s, tree, 1);
+
+ genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
+ push();
+ }
+ break;
+
+ case NODE_IF:
+ {
+ int pos1, pos2;
+ node *e = tree->cdr->cdr->car;
+
+ if (!tree->car) {
+ codegen(s, e, val);
+ goto exit;
+ }
+ switch (nint(tree->car->car)) {
+ case NODE_TRUE:
+ case NODE_INT:
+ case NODE_STR:
+ codegen(s, tree->cdr->car, val);
+ goto exit;
+ case NODE_FALSE:
+ case NODE_NIL:
+ codegen(s, e, val);
+ goto exit;
+ }
+ codegen(s, tree->car, VAL);
+ pop();
+ pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
+
+ codegen(s, tree->cdr->car, val);
+ if (e) {
+ if (val) pop();
+ pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch(s, pos1);
+ codegen(s, e, val);
+ dispatch(s, pos2);
+ }
+ else {
+ if (val) {
+ pop();
+ pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch(s, pos1);
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ dispatch(s, pos2);
+ push();
+ }
+ else {
+ dispatch(s, pos1);
+ }
+ }
+ }
+ break;
+
+ case NODE_AND:
+ {
+ int pos;
+
+ codegen(s, tree->car, VAL);
+ pop();
+ pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
+ codegen(s, tree->cdr, val);
+ dispatch(s, pos);
+ }
+ break;
+
+ case NODE_OR:
+ {
+ int pos;
+
+ codegen(s, tree->car, VAL);
+ pop();
+ pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
+ codegen(s, tree->cdr, val);
+ dispatch(s, pos);
+ }
+ break;
+
+ case NODE_WHILE:
+ {
+ struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
+
+ lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ lp->pc2 = new_label(s);
+ codegen(s, tree->cdr, NOVAL);
+ dispatch(s, lp->pc1);
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
+
+ loop_pop(s, val);
+ }
+ break;
+
+ case NODE_UNTIL:
+ {
+ struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
+
+ lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ lp->pc2 = new_label(s);
+ codegen(s, tree->cdr, NOVAL);
+ dispatch(s, lp->pc1);
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
+
+ loop_pop(s, val);
+ }
+ break;
+
+ case NODE_FOR:
+ for_body(s, tree);
+ if (val) push();
+ break;
+
+ case NODE_CASE:
+ {
+ int head = 0;
+ int pos1, pos2, pos3, tmp;
+ node *n;
+
+ pos3 = 0;
+ if (tree->car) {
+ head = cursp();
+ codegen(s, tree->car, VAL);
+ }
+ tree = tree->cdr;
+ while (tree) {
+ n = tree->car->car;
+ pos1 = pos2 = 0;
+ while (n) {
+ codegen(s, n->car, VAL);
+ if (head) {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), head));
+ push_n(2); pop_n(2); /* space for one arg and a block */
+ pop();
+ if (nint(n->car->car) == NODE_SPLAT) {
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
+ }
+ else {
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
+ }
+ }
+ else {
+ pop();
+ }
+ tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ pos2 = tmp;
+ n = n->cdr;
+ }
+ if (tree->car->car) {
+ pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch_linked(s, pos2);
+ }
+ codegen(s, tree->car->cdr, val);
+ if (val) pop();
+ tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
+ pos3 = tmp;
+ if (pos1) dispatch(s, pos1);
+ tree = tree->cdr;
+ }
+ if (val) {
+ int pos = cursp();
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ if (pos3) dispatch_linked(s, pos3);
+ if (head) pop();
+ if (cursp() != pos) {
+ genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ }
+ push();
+ }
+ else {
+ if (pos3) {
+ dispatch_linked(s, pos3);
+ }
+ if (head) {
+ pop();
+ }
+ }
+ }
+ break;
+
+ case NODE_SCOPE:
+ scope_body(s, tree, NOVAL);
+ break;
+
+ case NODE_FCALL:
+ case NODE_CALL:
+ gen_call(s, tree, 0, 0, val, 0);
+ break;
+ case NODE_SCALL:
+ gen_call(s, tree, 0, 0, val, 1);
+ break;
+
+ case NODE_DOT2:
+ codegen(s, tree->car, val);
+ codegen(s, tree->cdr, val);
+ if (val) {
+ pop(); pop();
+ genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
+ push();
+ }
+ break;
+
+ case NODE_DOT3:
+ codegen(s, tree->car, val);
+ codegen(s, tree->cdr, val);
+ if (val) {
+ pop(); pop();
+ genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
+ push();
+ }
+ break;
+
+ case NODE_COLON2:
+ {
+ int sym = new_sym(s, nsym(tree->cdr));
+
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ if (val) push();
+ }
+ break;
+
+ case NODE_COLON3:
+ {
+ int sym = new_sym(s, nsym(tree));
+
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ if (val) push();
+ }
+ break;
+
+ case NODE_ARRAY:
+ {
+ int n;
+
+ n = gen_values(s, tree, val, 0);
+ if (n >= 0) {
+ if (val) {
+ pop_n(n);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
+ push();
+ }
+ }
+ else if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_HASH:
+ {
+ int len = 0;
+ mrb_bool update = FALSE;
+
+ while (tree) {
+ codegen(s, tree->car->car, val);
+ codegen(s, tree->car->cdr, val);
+ len++;
+ tree = tree->cdr;
+ if (val && len == 126) {
+ pop_n(len*2);
+ genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
+ if (update) {
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
+ }
+ push();
+ update = TRUE;
+ len = 0;
+ }
+ }
+ if (val) {
+ pop_n(len*2);
+ genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
+ if (update) {
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
+ }
+ push();
+ }
+ }
+ break;
+
+ case NODE_SPLAT:
+ codegen(s, tree, val);
+ break;
+
+ case NODE_ASGN:
+ codegen(s, tree->cdr, VAL);
+ pop();
+ gen_assignment(s, tree->car, cursp(), val);
+ break;
+
+ case NODE_MASGN:
+ {
+ int len = 0, n = 0, post = 0;
+ node *t = tree->cdr, *p;
+ int rhs = cursp();
+
+ if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
+ /* fixed rhs */
+ t = t->cdr;
+ while (t) {
+ codegen(s, t->car, VAL);
+ len++;
+ t = t->cdr;
+ }
+ tree = tree->car;
+ if (tree->car) { /* pre */
+ t = tree->car;
+ n = 0;
+ while (t) {
+ if (n < len) {
+ gen_assignment(s, t->car, rhs+n, NOVAL);
+ n++;
+ }
+ else {
+ genop(s, MKOP_A(OP_LOADNIL, rhs+n));
+ gen_assignment(s, t->car, rhs+n, NOVAL);
+ }
+ t = t->cdr;
+ }
+ }
+ t = tree->cdr;
+ if (t) {
+ if (t->cdr) { /* post count */
+ p = t->cdr->car;
+ while (p) {
+ post++;
+ p = p->cdr;
+ }
+ }
+ if (t->car) { /* rest (len - pre - post) */
+ int rn;
+
+ if (len < post + n) {
+ rn = 0;
+ }
+ else {
+ rn = len - post - n;
+ }
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
+ gen_assignment(s, t->car, cursp(), NOVAL);
+ n += rn;
+ }
+ if (t->cdr && t->cdr->car) {
+ t = t->cdr->car;
+ while (n<len) {
+ gen_assignment(s, t->car, rhs+n, NOVAL);
+ t = t->cdr;
+ n++;
+ }
+ }
+ }
+ pop_n(len);
+ if (val) {
+ genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
+ push();
+ }
+ }
+ else {
+ /* variable rhs */
+ codegen(s, t, VAL);
+ gen_vmassignment(s, tree->car, rhs, val);
+ if (!val) {
+ pop();
+ }
+ }
+ }
+ break;
+
+ case NODE_OP_ASGN:
+ {
+ mrb_sym sym = nsym(tree->cdr->car);
+ mrb_int len;
+ const char *name = mrb_sym2name_len(s->mrb, sym, &len);
+ int idx, callargs = -1, vsp = -1;
+
+ if ((len == 2 && name[0] == '|' && name[1] == '|') &&
+ (nint(tree->car->car) == NODE_CONST ||
+ nint(tree->car->car) == NODE_CVAR)) {
+ int onerr, noexc, exc;
+ struct loopinfo *lp;
+
+ onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
+ lp = loop_push(s, LOOP_BEGIN);
+ lp->pc1 = onerr;
+ exc = cursp();
+ codegen(s, tree->car, VAL);
+ lp->type = LOOP_RESCUE;
+ genop(s, MKOP_A(OP_POPERR, 1));
+ noexc = genop(s, MKOP_Bx(OP_JMP, 0));
+ dispatch(s, onerr);
+ genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
+ genop(s, MKOP_A(OP_LOADF, exc));
+ dispatch(s, noexc);
+ loop_pop(s, NOVAL);
+ }
+ else if (nint(tree->car->car) == NODE_CALL) {
+ node *n = tree->car->cdr;
+ int base, i, nargs = 0;
+ callargs = 0;
+
+ if (val) {
+ vsp = cursp();
+ push();
+ }
+ codegen(s, n->car, VAL); /* receiver */
+ idx = new_msym(s, nsym(n->cdr->car));
+ base = cursp()-1;
+ if (n->cdr->cdr->car) {
+ nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
+ if (nargs >= 0) {
+ callargs = nargs;
+ }
+ else { /* varargs */
+ push();
+ nargs = 1;
+ callargs = CALL_MAXARGS;
+ }
+ }
+ /* copy receiver and arguments */
+ genop(s, MKOP_AB(OP_MOVE, cursp(), base));
+ for (i=0; i<nargs; i++) {
+ genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
+ }
+ push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ push();
+ }
+ else {
+ codegen(s, tree->car, VAL);
+ }
+ if (len == 2 &&
+ ((name[0] == '|' && name[1] == '|') ||
+ (name[0] == '&' && name[1] == '&'))) {
+ int pos;
+
+ pop();
+ if (val) {
+ if (vsp >= 0) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
+ pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
+ }
+ else {
+ pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL);
+ }
+ codegen(s, tree->cdr->cdr->car, VAL);
+ pop();
+ if (val && vsp >= 0) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
+ if (nint(tree->car->car) == NODE_CALL) {
+ if (callargs == CALL_MAXARGS) {
+ pop();
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ }
+ else {
+ pop_n(callargs);
+ callargs++;
+ }
+ pop();
+ idx = new_msym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ }
+ else {
+ gen_assignment(s, tree->car, cursp(), val);
+ }
+ dispatch(s, pos);
+ goto exit;
+ }
+ codegen(s, tree->cdr->cdr->car, VAL);
+ push(); pop();
+ pop(); pop();
+
+ idx = new_msym(s, sym);
+ if (len == 1 && name[0] == '+') {
+ genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
+ }
+ else if (len == 1 && name[0] == '-') {
+ genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
+ }
+ else if (len == 1 && name[0] == '*') {
+ genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
+ }
+ else if (len == 1 && name[0] == '/') {
+ genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
+ }
+ else if (len == 1 && name[0] == '<') {
+ genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
+ }
+ else if (len == 2 && name[0] == '<' && name[1] == '=') {
+ genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
+ }
+ else if (len == 1 && name[0] == '>') {
+ genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
+ }
+ else if (len == 2 && name[0] == '>' && name[1] == '=') {
+ genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
+ }
+ else {
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
+ }
+ if (callargs < 0) {
+ gen_assignment(s, tree->car, cursp(), val);
+ }
+ else {
+ if (val && vsp >= 0) {
+ genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ }
+ if (callargs == CALL_MAXARGS) {
+ pop();
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ }
+ else {
+ pop_n(callargs);
+ callargs++;
+ }
+ pop();
+ idx = new_msym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ }
+ }
+ break;
+
+ case NODE_SUPER:
+ {
+ codegen_scope *s2 = s;
+ int lv = 0;
+ int n = 0, noop = 0, sendv = 0;
+
+ push(); /* room for receiver */
+ while (!s2->mscope) {
+ lv++;
+ s2 = s2->prev;
+ if (!s2) break;
+ }
+ genop(s, MKOP_ABx(OP_ARGARY, cursp(), (lv & 0xf)));
+ push(); push(); /* ARGARY pushes two values */
+ pop(); pop();
+ if (tree) {
+ node *args = tree->car;
+ if (args) {
+ n = gen_values(s, args, VAL, 0);
+ if (n < 0) {
+ n = noop = sendv = 1;
+ push();
+ }
+ }
+ }
+ if (tree && tree->cdr) {
+ codegen(s, tree->cdr, VAL);
+ pop();
+ }
+ else {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push(); pop();
+ }
+ pop_n(n+1);
+ if (sendv) n = CALL_MAXARGS;
+ genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
+ if (val) push();
+ }
+ break;
+
+ case NODE_ZSUPER:
+ {
+ codegen_scope *s2 = s;
+ int lv = 0, ainfo = 0;
+
+ push(); /* room for receiver */
+ while (!s2->mscope) {
+ lv++;
+ s2 = s2->prev;
+ if (!s2) break;
+ }
+ if (s2) ainfo = s2->ainfo;
+ genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
+ push(); push(); pop(); /* ARGARY pushes two values */
+ if (tree && tree->cdr) {
+ codegen(s, tree->cdr, VAL);
+ pop();
+ }
+ pop(); pop();
+ genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
+ if (val) push();
+ }
+ break;
+
+ case NODE_RETURN:
+ if (tree) {
+ gen_retval(s, tree);
+ }
+ else {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ }
+ if (s->loop) {
+ genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
+ }
+ else {
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ }
+ if (val) push();
+ break;
+
+ case NODE_YIELD:
+ {
+ codegen_scope *s2 = s;
+ int lv = 0, ainfo = 0;
+ int n = 0, sendv = 0;
+
+ while (!s2->mscope) {
+ lv++;
+ s2 = s2->prev;
+ if (!s2) break;
+ }
+ if (s2) ainfo = s2->ainfo;
+ push();
+ if (tree) {
+ n = gen_values(s, tree, VAL, 0);
+ if (n < 0) {
+ n = sendv = 1;
+ push();
+ }
+ }
+ push();pop(); /* space for a block */
+ pop_n(n+1);
+ genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
+ if (sendv) n = CALL_MAXARGS;
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
+ if (val) push();
+ }
+ break;
+
+ case NODE_BREAK:
+ loop_break(s, tree);
+ if (val) push();
+ break;
+
+ case NODE_NEXT:
+ if (!s->loop) {
+ raise_error(s, "unexpected next");
+ }
+ else if (s->loop->type == LOOP_NORMAL) {
+ if (s->ensure_level > s->loop->ensure_level) {
+ genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
+ }
+ codegen(s, tree, NOVAL);
+ genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
+ }
+ else {
+ if (tree) {
+ codegen(s, tree, VAL);
+ pop();
+ }
+ else {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ }
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ }
+ if (val) push();
+ break;
+
+ case NODE_REDO:
+ if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
+ raise_error(s, "unexpected redo");
+ }
+ else {
+ if (s->ensure_level > s->loop->ensure_level) {
+ genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
+ }
+ genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
+ }
+ if (val) push();
+ break;
+
+ case NODE_RETRY:
+ {
+ const char *msg = "unexpected retry";
+
+ if (!s->loop) {
+ raise_error(s, msg);
+ }
+ else {
+ struct loopinfo *lp = s->loop;
+ int n = 0;
+
+ while (lp && lp->type != LOOP_RESCUE) {
+ if (lp->type == LOOP_BEGIN) {
+ n++;
+ }
+ lp = lp->prev;
+ }
+ if (!lp) {
+ raise_error(s, msg);
+ }
+ else {
+ if (n > 0) {
+ genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
+ }
+ if (s->ensure_level > lp->ensure_level) {
+ genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
+ }
+ genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
+ }
+ }
+ if (val) push();
+ }
+ break;
+
+ case NODE_LVAR:
+ if (val) {
+ int idx = lv_idx(s, nsym(tree));
+
+ if (idx > 0) {
+ genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
+ }
+ else {
+ int lv = 0;
+ codegen_scope *up = s->prev;
+
+ while (up) {
+ idx = lv_idx(up, nsym(tree));
+ if (idx > 0) {
+ genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
+ break;
+ }
+ lv++;
+ up = up->prev;
+ }
+ }
+ push();
+ }
+ break;
+
+ case NODE_GVAR:
+ if (val) {
+ int sym = new_sym(s, nsym(tree));
+
+ genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
+ push();
+ }
+ break;
+
+ case NODE_IVAR:
+ if (val) {
+ int sym = new_sym(s, nsym(tree));
+
+ genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
+ push();
+ }
+ break;
+
+ case NODE_CVAR:
+ if (val) {
+ int sym = new_sym(s, nsym(tree));
+
+ genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
+ push();
+ }
+ break;
+
+ case NODE_CONST:
+ {
+ int sym = new_sym(s, nsym(tree));
+
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
+ if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_DEFINED:
+ codegen(s, tree, VAL);
+ break;
+
+ case NODE_BACK_REF:
+ if (val) {
+ char buf[3];
+ int sym;
+
+ buf[0] = '$';
+ buf[1] = nchar(tree);
+ buf[2] = 0;
+ sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
+ genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
+ push();
+ }
+ break;
+
+ case NODE_NTH_REF:
+ if (val) {
+ mrb_state *mrb = s->mrb;
+ mrb_value str;
+ int sym;
+
+ str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
+ sym = new_sym(s, mrb_intern_str(mrb, str));
+ genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
+ push();
+ }
+ break;
+
+ case NODE_ARG:
+ /* should not happen */
+ break;
+
+ case NODE_BLOCK_ARG:
+ codegen(s, tree, VAL);
+ break;
+
+ case NODE_INT:
+ if (val) {
+ char *p = (char*)tree->car;
+ int base = nint(tree->cdr->car);
+ mrb_int i;
+ mrb_code co;
+ mrb_bool overflow;
+
+ i = readint_mrb_int(s, p, base, FALSE, &overflow);
+ if (overflow) {
+ double f = readint_float(s, p, base);
+ int off = new_lit(s, mrb_float_value(s->mrb, f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ }
+ else {
+ if (i < MAXARG_sBx && i > -MAXARG_sBx) {
+ co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ }
+ else {
+ int off = new_lit(s, mrb_fixnum_value(i));
+ co = MKOP_ABx(OP_LOADL, cursp(), off);
+ }
+ genop(s, co);
+ }
+ push();
+ }
+ break;
+
+ case NODE_FLOAT:
+ if (val) {
+ char *p = (char*)tree;
+ mrb_float f = mrb_float_read(p, NULL);
+ int off = new_lit(s, mrb_float_value(s->mrb, f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ push();
+ }
+ break;
+
+ case NODE_NEGATE:
+ {
+ nt = nint(tree->car);
+ tree = tree->cdr;
+ switch (nt) {
+ case NODE_FLOAT:
+ if (val) {
+ char *p = (char*)tree;
+ mrb_float f = mrb_float_read(p, NULL);
+ int off = new_lit(s, mrb_float_value(s->mrb, -f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ push();
+ }
+ break;
+
+ case NODE_INT:
+ if (val) {
+ char *p = (char*)tree->car;
+ int base = nint(tree->cdr->car);
+ mrb_int i;
+ mrb_code co;
+ mrb_bool overflow;
+
+ i = readint_mrb_int(s, p, base, TRUE, &overflow);
+ if (overflow) {
+ double f = readint_float(s, p, base);
+ int off = new_lit(s, mrb_float_value(s->mrb, -f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ }
+ else {
+ if (i < MAXARG_sBx && i > -MAXARG_sBx) {
+ co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ }
+ else {
+ int off = new_lit(s, mrb_fixnum_value(i));
+ co = MKOP_ABx(OP_LOADL, cursp(), off);
+ }
+ genop(s, co);
+ }
+ push();
+ }
+ break;
+
+ default:
+ if (val) {
+ int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
+
+ genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
+ push();
+ codegen(s, tree, VAL);
+ pop(); pop();
+ genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
+ }
+ else {
+ codegen(s, tree, NOVAL);
+ }
+ break;
+ }
+ }
+ break;
+
+ case NODE_STR:
+ if (val) {
+ char *p = (char*)tree->car;
+ size_t len = (intptr_t)tree->cdr;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int off = new_lit(s, mrb_str_new(s->mrb, p, len));
+
+ mrb_gc_arena_restore(s->mrb, ai);
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ push();
+ }
+ break;
+
+ case NODE_HEREDOC:
+ tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
+ /* fall through */
+ case NODE_DSTR:
+ if (val) {
+ node *n = tree;
+
+ if (!n) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ break;
+ }
+ codegen(s, n->car, VAL);
+ n = n->cdr;
+ while (n) {
+ codegen(s, n->car, VAL);
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ n = n->cdr;
+ }
+ }
+ else {
+ node *n = tree;
+
+ while (n) {
+ if (nint(n->car->car) != NODE_STR) {
+ codegen(s, n->car, NOVAL);
+ }
+ n = n->cdr;
+ }
+ }
+ break;
+
+ case NODE_WORDS:
+ gen_literal_array(s, tree, FALSE, val);
+ break;
+
+ case NODE_SYMBOLS:
+ gen_literal_array(s, tree, TRUE, val);
+ break;
+
+ case NODE_DXSTR:
+ {
+ node *n;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
+
+ genop(s, MKOP_A(OP_LOADSELF, cursp()));
+ push();
+ codegen(s, tree->car, VAL);
+ n = tree->cdr;
+ while (n) {
+ if (nint(n->car->car) == NODE_XSTR) {
+ n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
+ mrb_assert(!n->cdr); /* must be the end */
+ }
+ codegen(s, n->car, VAL);
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ n = n->cdr;
+ }
+ push(); /* for block */
+ pop_n(3);
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ if (val) push();
+ mrb_gc_arena_restore(s->mrb, ai);
+ }
+ break;
+
+ case NODE_XSTR:
+ {
+ char *p = (char*)tree->car;
+ size_t len = (intptr_t)tree->cdr;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int off = new_lit(s, mrb_str_new(s->mrb, p, len));
+ int sym;
+
+ genop(s, MKOP_A(OP_LOADSELF, cursp()));
+ push();
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ push(); push();
+ pop_n(3);
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ if (val) push();
+ mrb_gc_arena_restore(s->mrb, ai);
+ }
+ break;
+
+ case NODE_REGX:
+ if (val) {
+ char *p1 = (char*)tree->car;
+ char *p2 = (char*)tree->cdr->car;
+ char *p3 = (char*)tree->cdr->cdr;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
+ int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
+ int argc = 1;
+
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ push();
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ push();
+ if (p2 || p3) {
+ if (p2) { /* opt */
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ }
+ else {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ }
+ push();
+ argc++;
+ if (p3) { /* enc */
+ off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ push();
+ argc++;
+ }
+ }
+ push(); /* space for a block */
+ pop_n(argc+2);
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
+ mrb_gc_arena_restore(s->mrb, ai);
+ push();
+ }
+ break;
+
+ case NODE_DREGX:
+ if (val) {
+ node *n = tree->car;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
+ int argc = 1;
+ int off;
+ char *p;
+
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ push();
+ codegen(s, n->car, VAL);
+ n = n->cdr;
+ while (n) {
+ codegen(s, n->car, VAL);
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ n = n->cdr;
+ }
+ n = tree->cdr->cdr;
+ if (n->car) { /* tail */
+ p = (char*)n->car;
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
+ codegen(s, tree->car, VAL);
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ }
+ if (n->cdr->car) { /* opt */
+ char *p2 = (char*)n->cdr->car;
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ push();
+ argc++;
+ }
+ if (n->cdr->cdr) { /* enc */
+ char *p2 = (char*)n->cdr->cdr;
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
+ genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ push();
+ argc++;
+ }
+ push(); /* space for a block */
+ pop_n(argc+2);
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
+ mrb_gc_arena_restore(s->mrb, ai);
+ push();
+ }
+ else {
+ node *n = tree->car;
+
+ while (n) {
+ if (nint(n->car->car) != NODE_STR) {
+ codegen(s, n->car, NOVAL);
+ }
+ n = n->cdr;
+ }
+ }
+ break;
+
+ case NODE_SYM:
+ if (val) {
+ int sym = new_sym(s, nsym(tree));
+
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
+ push();
+ }
+ break;
+
+ case NODE_DSYM:
+ codegen(s, tree, val);
+ if (val) {
+ gen_send_intern(s);
+ }
+ break;
+
+ case NODE_SELF:
+ if (val) {
+ genop(s, MKOP_A(OP_LOADSELF, cursp()));
+ push();
+ }
+ break;
+
+ case NODE_NIL:
+ if (val) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ }
+ break;
+
+ case NODE_TRUE:
+ if (val) {
+ genop(s, MKOP_A(OP_LOADT, cursp()));
+ push();
+ }
+ break;
+
+ case NODE_FALSE:
+ if (val) {
+ genop(s, MKOP_A(OP_LOADF, cursp()));
+ push();
+ }
+ break;
+
+ case NODE_ALIAS:
+ {
+ int a = new_msym(s, nsym(tree->car));
+ int b = new_msym(s, nsym(tree->cdr));
+ int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
+
+ genop(s, MKOP_A(OP_TCLASS, cursp()));
+ push();
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
+ push();
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
+ push();
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push(); /* space for a block */
+ pop_n(4);
+ genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
+ if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_UNDEF:
+ {
+ int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
+ int num = 0;
+ node *t = tree;
+
+ genop(s, MKOP_A(OP_TCLASS, cursp()));
+ push();
+ while (t) {
+ int symbol;
+ if (num >= CALL_MAXARGS - 1) {
+ pop_n(num);
+ genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
+ while (t) {
+ symbol = new_msym(s, nsym(t->car));
+ push();
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
+ pop();
+ genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ t = t->cdr;
+ }
+ num = CALL_MAXARGS;
+ break;
+ }
+ symbol = new_msym(s, nsym(t->car));
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
+ push();
+ t = t->cdr;
+ num++;
+ }
+ push();pop(); /* space for a block */
+ pop();
+ if (num < CALL_MAXARGS) {
+ pop_n(num);
+ }
+ genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
+ if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_CLASS:
+ {
+ int idx;
+
+ if (tree->car->car == (node*)0) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ }
+ else if (tree->car->car == (node*)1) {
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ push();
+ }
+ else {
+ codegen(s, tree->car->car, VAL);
+ }
+ if (tree->cdr->car) {
+ codegen(s, tree->cdr->car, VAL);
+ }
+ else {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ }
+ pop(); pop();
+ idx = new_msym(s, nsym(tree->car->cdr));
+ genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
+ idx = scope_body(s, tree->cdr->cdr->car, val);
+ genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
+ if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_MODULE:
+ {
+ int idx;
+
+ if (tree->car->car == (node*)0) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push();
+ }
+ else if (tree->car->car == (node*)1) {
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ push();
+ }
+ else {
+ codegen(s, tree->car->car, VAL);
+ }
+ pop();
+ idx = new_msym(s, nsym(tree->car->cdr));
+ genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
+ idx = scope_body(s, tree->cdr->car, val);
+ genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
+ if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_SCLASS:
+ {
+ int idx;
+
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
+ idx = scope_body(s, tree->cdr->car, val);
+ genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
+ if (val) {
+ push();
+ }
+ }
+ break;
+
+ case NODE_DEF:
+ {
+ int sym = new_msym(s, nsym(tree->car));
+ int idx = lambda_body(s, tree->cdr, 0);
+
+ genop(s, MKOP_A(OP_TCLASS, cursp()));
+ push();
+ genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
+ push(); pop();
+ pop();
+ genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
+ if (val) {
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
+ push();
+ }
+ }
+ break;
+
+ case NODE_SDEF:
+ {
+ node *recv = tree->car;
+ int sym = new_msym(s, nsym(tree->cdr->car));
+ int idx = lambda_body(s, tree->cdr->cdr, 0);
+
+ codegen(s, recv, VAL);
+ pop();
+ genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
+ push();
+ genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
+ pop();
+ genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
+ if (val) {
+ genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
+ push();
+ }
+ }
+ break;
+
+ case NODE_POSTEXE:
+ codegen(s, tree, NOVAL);
+ break;
+
+ default:
+ break;
+ }
+ exit:
+ s->rlev = rlev;
+}
+
+static void
+scope_add_irep(codegen_scope *s, mrb_irep *irep)
+{
+ if (s->irep == NULL) {
+ s->irep = irep;
+ return;
+ }
+ if (s->irep->rlen == s->rcapa) {
+ s->rcapa *= 2;
+ s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
+ }
+ s->irep->reps[s->irep->rlen] = irep;
+ s->irep->rlen++;
+}
+
+static codegen_scope*
+scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
+{
+ static const codegen_scope codegen_scope_zero = { 0 };
+ mrb_pool *pool = mrb_pool_open(mrb);
+ codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
+
+ if (!p) return NULL;
+ *p = codegen_scope_zero;
+ p->mrb = mrb;
+ p->mpool = pool;
+ if (!prev) return p;
+ p->prev = prev;
+ p->ainfo = -1;
+ p->mscope = 0;
+
+ p->irep = mrb_add_irep(mrb);
+ scope_add_irep(prev, p->irep);
+
+ p->rcapa = 8;
+ p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
+
+ p->icapa = 1024;
+ p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
+ p->irep->iseq = NULL;
+
+ p->pcapa = 32;
+ p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
+ p->irep->plen = 0;
+
+ p->scapa = MAXMSYMLEN;
+ p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
+ p->irep->slen = 0;
+
+ p->lv = lv;
+ p->sp += node_len(lv)+1; /* add self */
+ p->nlocals = p->sp;
+ if (lv) {
+ node *n = lv;
+ size_t i = 0;
+
+ p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
+ for (i=0, n=lv; n; i++,n=n->cdr) {
+ p->irep->lv[i].name = lv_name(n);
+ if (lv_name(n)) {
+ p->irep->lv[i].r = lv_idx(p, lv_name(n));
+ }
+ else {
+ p->irep->lv[i].r = 0;
+ }
+ }
+ mrb_assert(i + 1 == p->nlocals);
+ }
+ p->ai = mrb_gc_arena_save(mrb);
+
+ p->filename = prev->filename;
+ if (p->filename) {
+ p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
+ }
+ p->lineno = prev->lineno;
+
+ /* debug setting */
+ p->debug_start_pos = 0;
+ if (p->filename) {
+ mrb_debug_info_alloc(mrb, p->irep);
+ p->irep->filename = p->filename;
+ p->irep->lines = p->lines;
+ }
+ else {
+ p->irep->debug_info = NULL;
+ }
+ p->parser = prev->parser;
+ p->filename_index = prev->filename_index;
+
+ p->rlev = prev->rlev+1;
+
+ return p;
+}
+
+static void
+scope_finish(codegen_scope *s)
+{
+ mrb_state *mrb = s->mrb;
+ mrb_irep *irep = s->irep;
+ size_t fname_len;
+ char *fname;
+
+ irep->flags = 0;
+ if (s->iseq) {
+ irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
+ irep->ilen = s->pc;
+ if (s->lines) {
+ irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
+ }
+ else {
+ irep->lines = 0;
+ }
+ }
+ irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
+ irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
+ irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
+ if (s->filename) {
+ irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
+ mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc);
+
+ fname_len = strlen(s->filename);
+ fname = (char*)codegen_malloc(s, fname_len + 1);
+ memcpy(fname, s->filename, fname_len);
+ fname[fname_len] = '\0';
+ irep->filename = fname;
+ irep->own_filename = TRUE;
+ }
+
+ irep->nlocals = s->nlocals;
+ irep->nregs = s->nregs;
+
+ mrb_gc_arena_restore(mrb, s->ai);
+ mrb_pool_close(s->mpool);
+}
+
+static struct loopinfo*
+loop_push(codegen_scope *s, enum looptype t)
+{
+ struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
+
+ p->type = t;
+ p->pc1 = p->pc2 = p->pc3 = 0;
+ p->prev = s->loop;
+ p->ensure_level = s->ensure_level;
+ p->acc = cursp();
+ s->loop = p;
+
+ return p;
+}
+
+static void
+loop_break(codegen_scope *s, node *tree)
+{
+ if (!s->loop) {
+ codegen(s, tree, NOVAL);
+ raise_error(s, "unexpected break");
+ }
+ else {
+ struct loopinfo *loop;
+ int n = 0;
+
+ if (tree) {
+ gen_retval(s, tree);
+ }
+
+ loop = s->loop;
+ while (loop) {
+ if (loop->type == LOOP_BEGIN) {
+ n++;
+ loop = loop->prev;
+ }
+ else if (loop->type == LOOP_RESCUE) {
+ loop = loop->prev;
+ }
+ else{
+ break;
+ }
+ }
+ if (!loop) {
+ raise_error(s, "unexpected break");
+ return;
+ }
+ if (n > 0) {
+ genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
+ }
+
+ if (loop->type == LOOP_NORMAL) {
+ int tmp;
+
+ if (s->ensure_level > s->loop->ensure_level) {
+ genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
+ }
+ if (tree) {
+ genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
+ }
+ tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
+ loop->pc3 = tmp;
+ }
+ else {
+ if (!tree) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ }
+ genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
+ }
+ }
+}
+
+static void
+loop_pop(codegen_scope *s, int val)
+{
+ if (val) {
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ }
+ dispatch_linked(s, s->loop->pc3);
+ s->loop = s->loop->prev;
+ if (val) push();
+}
+
+MRB_API struct RProc*
+mrb_generate_code(mrb_state *mrb, parser_state *p)
+{
+ codegen_scope *scope = scope_new(mrb, 0, 0);
+ struct RProc *proc;
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+
+ if (!scope) {
+ return NULL;
+ }
+ scope->mrb = mrb;
+ scope->parser = p;
+ scope->filename = p->filename;
+ scope->filename_index = p->current_filename_index;
+
+ MRB_TRY(&scope->jmp) {
+ mrb->jmp = &scope->jmp;
+ /* prepare irep */
+ codegen(scope, p->tree, NOVAL);
+ proc = mrb_proc_new(mrb, scope->irep);
+ mrb_irep_decref(mrb, scope->irep);
+ mrb_pool_close(scope->mpool);
+ proc->c = NULL;
+ mrb->jmp = prev_jmp;
+ return proc;
+ }
+ MRB_CATCH(&scope->jmp) {
+ mrb_irep_decref(mrb, scope->irep);
+ mrb_pool_close(scope->mpool);
+ mrb->jmp = prev_jmp;
+ return NULL;
+ }
+ MRB_END_EXC(&scope->jmp);
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/keywords b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/keywords
new file mode 100644
index 00000000..9cb86608
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/keywords
@@ -0,0 +1,50 @@
+%{
+struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
+const struct kwtable *mrb_reserved_word(const char *, unsigned int);
+static const struct kwtable *reserved_word(const char *, unsigned int);
+#define mrb_reserved_word(str, len) reserved_word(str, len)
+%}
+
+struct kwtable;
+%%
+__ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END
+__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END
+__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END
+BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END
+END, {keyword_END, keyword_END}, EXPR_END
+alias, {keyword_alias, keyword_alias}, EXPR_FNAME
+and, {keyword_and, keyword_and}, EXPR_VALUE
+begin, {keyword_begin, keyword_begin}, EXPR_BEG
+break, {keyword_break, keyword_break}, EXPR_MID
+case, {keyword_case, keyword_case}, EXPR_VALUE
+class, {keyword_class, keyword_class}, EXPR_CLASS
+def, {keyword_def, keyword_def}, EXPR_FNAME
+do, {keyword_do, keyword_do}, EXPR_BEG
+else, {keyword_else, keyword_else}, EXPR_BEG
+elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE
+end, {keyword_end, keyword_end}, EXPR_END
+ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG
+false, {keyword_false, keyword_false}, EXPR_END
+for, {keyword_for, keyword_for}, EXPR_VALUE
+if, {keyword_if, modifier_if}, EXPR_VALUE
+in, {keyword_in, keyword_in}, EXPR_VALUE
+module, {keyword_module, keyword_module}, EXPR_VALUE
+next, {keyword_next, keyword_next}, EXPR_MID
+nil, {keyword_nil, keyword_nil}, EXPR_END
+not, {keyword_not, keyword_not}, EXPR_ARG
+or, {keyword_or, keyword_or}, EXPR_VALUE
+redo, {keyword_redo, keyword_redo}, EXPR_END
+rescue, {keyword_rescue, modifier_rescue}, EXPR_MID
+retry, {keyword_retry, keyword_retry}, EXPR_END
+return, {keyword_return, keyword_return}, EXPR_MID
+self, {keyword_self, keyword_self}, EXPR_END
+super, {keyword_super, keyword_super}, EXPR_ARG
+then, {keyword_then, keyword_then}, EXPR_BEG
+true, {keyword_true, keyword_true}, EXPR_END
+undef, {keyword_undef, keyword_undef}, EXPR_FNAME
+unless, {keyword_unless, modifier_unless}, EXPR_VALUE
+until, {keyword_until, modifier_until}, EXPR_VALUE
+when, {keyword_when, keyword_when}, EXPR_VALUE
+while, {keyword_while, modifier_while}, EXPR_VALUE
+yield, {keyword_yield, keyword_yield}, EXPR_ARG
+%%
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/lex.def b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/lex.def
new file mode 100644
index 00000000..58e30296
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/lex.def
@@ -0,0 +1,212 @@
+/* ANSI-C code produced by gperf version 3.0.4 */
+/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' /home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#line 1 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+
+struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
+const struct kwtable *mrb_reserved_word(const char *, unsigned int);
+static const struct kwtable *reserved_word(const char *, unsigned int);
+#define mrb_reserved_word(str, len) reserved_word(str, len)
+#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+struct kwtable;
+
+#define TOTAL_KEYWORDS 40
+#define MIN_WORD_LENGTH 2
+#define MAX_WORD_LENGTH 12
+#define MIN_HASH_VALUE 8
+#define MAX_HASH_VALUE 50
+/* maximum key range = 43, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+hash (register const char *str, register unsigned int len)
+{
+ static const unsigned char asso_values[] =
+ {
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 14, 51, 16, 8,
+ 11, 13, 51, 51, 51, 51, 10, 51, 13, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 11, 51, 13, 1, 26,
+ 4, 1, 8, 28, 51, 23, 51, 1, 1, 27,
+ 5, 19, 21, 51, 8, 3, 3, 11, 51, 21,
+ 24, 16, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51
+ };
+ register int hval = len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ case 1:
+ hval += asso_values[(unsigned char)str[0]];
+ break;
+ }
+ return hval + asso_values[(unsigned char)str[len - 1]];
+}
+
+#ifdef __GNUC__
+__inline
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct kwtable *
+mrb_reserved_word (register const char *str, register unsigned int len)
+{
+ static const struct kwtable wordlist[] =
+ {
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"break", {keyword_break, keyword_break}, EXPR_MID},
+#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"else", {keyword_else, keyword_else}, EXPR_BEG},
+#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"nil", {keyword_nil, keyword_nil}, EXPR_END},
+#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
+#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"end", {keyword_end, keyword_end}, EXPR_END},
+#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"then", {keyword_then, keyword_then}, EXPR_BEG},
+#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"not", {keyword_not, keyword_not}, EXPR_ARG},
+#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"false", {keyword_false, keyword_false}, EXPR_END},
+#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"self", {keyword_self, keyword_self}, EXPR_END},
+#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
+#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
+#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"true", {keyword_true, keyword_true}, EXPR_END},
+#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"until", {keyword_until, modifier_until}, EXPR_VALUE},
+#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
+#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"return", {keyword_return, keyword_return}, EXPR_MID},
+#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"def", {keyword_def, keyword_def}, EXPR_FNAME},
+#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"and", {keyword_and, keyword_and}, EXPR_VALUE},
+#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"do", {keyword_do, keyword_do}, EXPR_BEG},
+#line 49 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
+#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"for", {keyword_for, keyword_for}, EXPR_VALUE},
+#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
+#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"or", {keyword_or, keyword_or}, EXPR_VALUE},
+#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"in", {keyword_in, keyword_in}, EXPR_VALUE},
+#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"when", {keyword_when, keyword_when}, EXPR_VALUE},
+#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"retry", {keyword_retry, keyword_retry}, EXPR_END},
+#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"if", {keyword_if, modifier_if}, EXPR_VALUE},
+#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"case", {keyword_case, keyword_case}, EXPR_VALUE},
+#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"redo", {keyword_redo, keyword_redo}, EXPR_END},
+#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"next", {keyword_next, keyword_next}, EXPR_MID},
+#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"super", {keyword_super, keyword_super}, EXPR_ARG},
+#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"module", {keyword_module, keyword_module}, EXPR_VALUE},
+#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
+#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
+#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
+#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
+#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"END", {keyword_END, keyword_END}, EXPR_END},
+#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
+#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
+ {""},
+#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"class", {keyword_class, keyword_class}, EXPR_CLASS},
+ {""}, {""},
+#line 48 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+ {"while", {keyword_while, modifier_while}, EXPR_VALUE}
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register int key = hash (str, len);
+
+ if (key <= MAX_HASH_VALUE && key >= 0)
+ {
+ register const char *s = wordlist[key].name;
+
+ if (*str == *s && !strcmp (str + 1, s + 1))
+ return &wordlist[key];
+ }
+ }
+ return 0;
+}
+#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/node.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/node.h
new file mode 100644
index 00000000..9636dd75
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/node.h
@@ -0,0 +1,118 @@
+/*
+** node.h - nodes of abstract syntax tree
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_COMPILER_NODE_H
+#define MRUBY_COMPILER_NODE_H
+
+enum node_type {
+ NODE_METHOD,
+ NODE_FBODY,
+ NODE_CFUNC,
+ NODE_SCOPE,
+ NODE_BLOCK,
+ NODE_IF,
+ NODE_CASE,
+ NODE_WHEN,
+ NODE_OPT_N,
+ NODE_WHILE,
+ NODE_UNTIL,
+ NODE_ITER,
+ NODE_FOR,
+ NODE_BREAK,
+ NODE_NEXT,
+ NODE_REDO,
+ NODE_RETRY,
+ NODE_BEGIN,
+ NODE_RESCUE,
+ NODE_ENSURE,
+ NODE_AND,
+ NODE_OR,
+ NODE_NOT,
+ NODE_MASGN,
+ NODE_ASGN,
+ NODE_CDECL,
+ NODE_CVASGN,
+ NODE_CVDECL,
+ NODE_OP_ASGN,
+ NODE_CALL,
+ NODE_SCALL,
+ NODE_FCALL,
+ NODE_VCALL,
+ NODE_SUPER,
+ NODE_ZSUPER,
+ NODE_ARRAY,
+ NODE_ZARRAY,
+ NODE_HASH,
+ NODE_RETURN,
+ NODE_YIELD,
+ NODE_LVAR,
+ NODE_DVAR,
+ NODE_GVAR,
+ NODE_IVAR,
+ NODE_CONST,
+ NODE_CVAR,
+ NODE_NTH_REF,
+ NODE_BACK_REF,
+ NODE_MATCH,
+ NODE_MATCH2,
+ NODE_MATCH3,
+ NODE_INT,
+ NODE_FLOAT,
+ NODE_NEGATE,
+ NODE_LAMBDA,
+ NODE_SYM,
+ NODE_STR,
+ NODE_DSTR,
+ NODE_XSTR,
+ NODE_DXSTR,
+ NODE_REGX,
+ NODE_DREGX,
+ NODE_DREGX_ONCE,
+ NODE_LIST,
+ NODE_ARG,
+ NODE_ARGSCAT,
+ NODE_ARGSPUSH,
+ NODE_SPLAT,
+ NODE_TO_ARY,
+ NODE_SVALUE,
+ NODE_BLOCK_ARG,
+ NODE_DEF,
+ NODE_SDEF,
+ NODE_ALIAS,
+ NODE_UNDEF,
+ NODE_CLASS,
+ NODE_MODULE,
+ NODE_SCLASS,
+ NODE_COLON2,
+ NODE_COLON3,
+ NODE_CREF,
+ NODE_DOT2,
+ NODE_DOT3,
+ NODE_FLIP2,
+ NODE_FLIP3,
+ NODE_ATTRSET,
+ NODE_SELF,
+ NODE_NIL,
+ NODE_TRUE,
+ NODE_FALSE,
+ NODE_DEFINED,
+ NODE_NEWLINE,
+ NODE_POSTEXE,
+ NODE_ALLOCA,
+ NODE_DMETHOD,
+ NODE_BMETHOD,
+ NODE_MEMO,
+ NODE_IFUNC,
+ NODE_DSYM,
+ NODE_ATTRASGN,
+ NODE_HEREDOC,
+ NODE_LITERAL_DELIM,
+ NODE_WORDS,
+ NODE_SYMBOLS,
+ NODE_LAST
+};
+
+#endif /* MRUBY_COMPILER_NODE_H */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/parse.y b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/parse.y
new file mode 100644
index 00000000..0e425b18
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/core/parse.y
@@ -0,0 +1,6652 @@
+/*
+** parse.y - mruby parser
+**
+** See Copyright Notice in mruby.h
+*/
+
+%{
+#undef PARSER_DEBUG
+#ifdef PARSER_DEBUG
+# define YYDEBUG 1
+#endif
+#define YYERROR_VERBOSE 1
+/*
+ * Force yacc to use our memory management. This is a little evil because
+ * the macros assume that "parser_state *p" is in scope
+ */
+#define YYMALLOC(n) mrb_malloc(p->mrb, (n))
+#define YYFREE(o) mrb_free(p->mrb, (o))
+#define YYSTACK_USE_ALLOCA 0
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/compile.h>
+#include <mruby/proc.h>
+#include <mruby/error.h>
+#include <mruby/throw.h>
+#include "node.h"
+
+#define YYLEX_PARAM p
+
+typedef mrb_ast_node node;
+typedef struct mrb_parser_state parser_state;
+typedef struct mrb_parser_heredoc_info parser_heredoc_info;
+
+static int yyparse(parser_state *p);
+static int yylex(void *lval, parser_state *p);
+static void yyerror(parser_state *p, const char *s);
+static void yywarn(parser_state *p, const char *s);
+static void yywarning(parser_state *p, const char *s);
+static void backref_error(parser_state *p, node *n);
+static void void_expr_error(parser_state *p, node *n);
+static void tokadd(parser_state *p, int32_t c);
+
+#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
+
+typedef unsigned int stack_type;
+
+#define BITSTACK_PUSH(stack, n) ((stack) = ((stack)<<1)|((n)&1))
+#define BITSTACK_POP(stack) ((stack) = (stack) >> 1)
+#define BITSTACK_LEXPOP(stack) ((stack) = ((stack) >> 1) | ((stack) & 1))
+#define BITSTACK_SET_P(stack) ((stack)&1)
+
+#define COND_PUSH(n) BITSTACK_PUSH(p->cond_stack, (n))
+#define COND_POP() BITSTACK_POP(p->cond_stack)
+#define COND_LEXPOP() BITSTACK_LEXPOP(p->cond_stack)
+#define COND_P() BITSTACK_SET_P(p->cond_stack)
+
+#define CMDARG_PUSH(n) BITSTACK_PUSH(p->cmdarg_stack, (n))
+#define CMDARG_POP() BITSTACK_POP(p->cmdarg_stack)
+#define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack)
+#define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack)
+
+#define SET_LINENO(c,n) ((c)->lineno = (n))
+#define NODE_LINENO(c,n) do {\
+ if (n) {\
+ (c)->filename_index = (n)->filename_index;\
+ (c)->lineno = (n)->lineno;\
+ }\
+} while (0)
+
+#define sym(x) ((mrb_sym)(intptr_t)(x))
+#define nsym(x) ((node*)(intptr_t)(x))
+#define nint(x) ((node*)(intptr_t)(x))
+#define intn(x) ((int)(intptr_t)(x))
+
+static inline mrb_sym
+intern_cstr_gen(parser_state *p, const char *s)
+{
+ return mrb_intern_cstr(p->mrb, s);
+}
+#define intern_cstr(s) intern_cstr_gen(p,(s))
+
+static inline mrb_sym
+intern_gen(parser_state *p, const char *s, size_t len)
+{
+ return mrb_intern(p->mrb, s, len);
+}
+#define intern(s,len) intern_gen(p,(s),(len))
+
+static inline mrb_sym
+intern_gen_c(parser_state *p, const char c)
+{
+ return mrb_intern(p->mrb, &c, 1);
+}
+#define intern_c(c) intern_gen_c(p,(c))
+
+static void
+cons_free_gen(parser_state *p, node *cons)
+{
+ cons->cdr = p->cells;
+ p->cells = cons;
+}
+#define cons_free(c) cons_free_gen(p, (c))
+
+static void*
+parser_palloc(parser_state *p, size_t size)
+{
+ void *m = mrb_pool_alloc(p->pool, size);
+
+ if (!m) {
+ MRB_THROW(p->jmp);
+ }
+ return m;
+}
+
+static node*
+cons_gen(parser_state *p, node *car, node *cdr)
+{
+ node *c;
+
+ if (p->cells) {
+ c = p->cells;
+ p->cells = p->cells->cdr;
+ }
+ else {
+ c = (node *)parser_palloc(p, sizeof(mrb_ast_node));
+ }
+
+ c->car = car;
+ c->cdr = cdr;
+ c->lineno = p->lineno;
+ c->filename_index = p->current_filename_index;
+ return c;
+}
+#define cons(a,b) cons_gen(p,(a),(b))
+
+static node*
+list1_gen(parser_state *p, node *a)
+{
+ return cons(a, 0);
+}
+#define list1(a) list1_gen(p, (a))
+
+static node*
+list2_gen(parser_state *p, node *a, node *b)
+{
+ return cons(a, cons(b,0));
+}
+#define list2(a,b) list2_gen(p, (a),(b))
+
+static node*
+list3_gen(parser_state *p, node *a, node *b, node *c)
+{
+ return cons(a, cons(b, cons(c,0)));
+}
+#define list3(a,b,c) list3_gen(p, (a),(b),(c))
+
+static node*
+list4_gen(parser_state *p, node *a, node *b, node *c, node *d)
+{
+ return cons(a, cons(b, cons(c, cons(d, 0))));
+}
+#define list4(a,b,c,d) list4_gen(p, (a),(b),(c),(d))
+
+static node*
+list5_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e)
+{
+ return cons(a, cons(b, cons(c, cons(d, cons(e, 0)))));
+}
+#define list5(a,b,c,d,e) list5_gen(p, (a),(b),(c),(d),(e))
+
+static node*
+list6_gen(parser_state *p, node *a, node *b, node *c, node *d, node *e, node *f)
+{
+ return cons(a, cons(b, cons(c, cons(d, cons(e, cons(f, 0))))));
+}
+#define list6(a,b,c,d,e,f) list6_gen(p, (a),(b),(c),(d),(e),(f))
+
+static node*
+append_gen(parser_state *p, node *a, node *b)
+{
+ node *c = a;
+
+ if (!a) return b;
+ while (c->cdr) {
+ c = c->cdr;
+ }
+ if (b) {
+ c->cdr = b;
+ }
+ return a;
+}
+#define append(a,b) append_gen(p,(a),(b))
+#define push(a,b) append_gen(p,(a),list1(b))
+
+static char*
+parser_strndup(parser_state *p, const char *s, size_t len)
+{
+ char *b = (char *)parser_palloc(p, len+1);
+
+ memcpy(b, s, len);
+ b[len] = '\0';
+ return b;
+}
+#undef strndup
+#define strndup(s,len) parser_strndup(p, s, len)
+
+static char*
+parser_strdup(parser_state *p, const char *s)
+{
+ return parser_strndup(p, s, strlen(s));
+}
+#undef strdup
+#define strdup(s) parser_strdup(p, s)
+
+/* xxx ----------------------------- */
+
+static node*
+local_switch(parser_state *p)
+{
+ node *prev = p->locals;
+
+ p->locals = cons(0, 0);
+ return prev;
+}
+
+static void
+local_resume(parser_state *p, node *prev)
+{
+ p->locals = prev;
+}
+
+static void
+local_nest(parser_state *p)
+{
+ p->locals = cons(0, p->locals);
+}
+
+static void
+local_unnest(parser_state *p)
+{
+ if (p->locals) {
+ p->locals = p->locals->cdr;
+ }
+}
+
+static mrb_bool
+local_var_p(parser_state *p, mrb_sym sym)
+{
+ node *l = p->locals;
+
+ while (l) {
+ node *n = l->car;
+ while (n) {
+ if (sym(n->car) == sym) return TRUE;
+ n = n->cdr;
+ }
+ l = l->cdr;
+ }
+ return FALSE;
+}
+
+static void
+local_add_f(parser_state *p, mrb_sym sym)
+{
+ if (p->locals) {
+ p->locals->car = push(p->locals->car, nsym(sym));
+ }
+}
+
+static void
+local_add(parser_state *p, mrb_sym sym)
+{
+ if (!local_var_p(p, sym)) {
+ local_add_f(p, sym);
+ }
+}
+
+static node*
+locals_node(parser_state *p)
+{
+ return p->locals ? p->locals->car : NULL;
+}
+
+/* (:scope (vars..) (prog...)) */
+static node*
+new_scope(parser_state *p, node *body)
+{
+ return cons((node*)NODE_SCOPE, cons(locals_node(p), body));
+}
+
+/* (:begin prog...) */
+static node*
+new_begin(parser_state *p, node *body)
+{
+ if (body) {
+ return list2((node*)NODE_BEGIN, body);
+ }
+ return cons((node*)NODE_BEGIN, 0);
+}
+
+#define newline_node(n) (n)
+
+/* (:rescue body rescue else) */
+static node*
+new_rescue(parser_state *p, node *body, node *resq, node *els)
+{
+ return list4((node*)NODE_RESCUE, body, resq, els);
+}
+
+static node*
+new_mod_rescue(parser_state *p, node *body, node *resq)
+{
+ return new_rescue(p, body, list1(list3(0, 0, resq)), 0);
+}
+
+/* (:ensure body ensure) */
+static node*
+new_ensure(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_ENSURE, cons(a, cons(0, b)));
+}
+
+/* (:nil) */
+static node*
+new_nil(parser_state *p)
+{
+ return list1((node*)NODE_NIL);
+}
+
+/* (:true) */
+static node*
+new_true(parser_state *p)
+{
+ return list1((node*)NODE_TRUE);
+}
+
+/* (:false) */
+static node*
+new_false(parser_state *p)
+{
+ return list1((node*)NODE_FALSE);
+}
+
+/* (:alias new old) */
+static node*
+new_alias(parser_state *p, mrb_sym a, mrb_sym b)
+{
+ return cons((node*)NODE_ALIAS, cons(nsym(a), nsym(b)));
+}
+
+/* (:if cond then else) */
+static node*
+new_if(parser_state *p, node *a, node *b, node *c)
+{
+ void_expr_error(p, a);
+ return list4((node*)NODE_IF, a, b, c);
+}
+
+/* (:unless cond then else) */
+static node*
+new_unless(parser_state *p, node *a, node *b, node *c)
+{
+ void_expr_error(p, a);
+ return list4((node*)NODE_IF, a, c, b);
+}
+
+/* (:while cond body) */
+static node*
+new_while(parser_state *p, node *a, node *b)
+{
+ void_expr_error(p, a);
+ return cons((node*)NODE_WHILE, cons(a, b));
+}
+
+/* (:until cond body) */
+static node*
+new_until(parser_state *p, node *a, node *b)
+{
+ void_expr_error(p, a);
+ return cons((node*)NODE_UNTIL, cons(a, b));
+}
+
+/* (:for var obj body) */
+static node*
+new_for(parser_state *p, node *v, node *o, node *b)
+{
+ void_expr_error(p, o);
+ return list4((node*)NODE_FOR, v, o, b);
+}
+
+/* (:case a ((when ...) body) ((when...) body)) */
+static node*
+new_case(parser_state *p, node *a, node *b)
+{
+ node *n = list2((node*)NODE_CASE, a);
+ node *n2 = n;
+
+ void_expr_error(p, a);
+ while (n2->cdr) {
+ n2 = n2->cdr;
+ }
+ n2->cdr = b;
+ return n;
+}
+
+/* (:postexe a) */
+static node*
+new_postexe(parser_state *p, node *a)
+{
+ return cons((node*)NODE_POSTEXE, a);
+}
+
+/* (:self) */
+static node*
+new_self(parser_state *p)
+{
+ return list1((node*)NODE_SELF);
+}
+
+/* (:call a b c) */
+static node*
+new_call(parser_state *p, node *a, mrb_sym b, node *c, int pass)
+{
+ node *n = list4(nint(pass?NODE_CALL:NODE_SCALL), a, nsym(b), c);
+ void_expr_error(p, a);
+ NODE_LINENO(n, a);
+ return n;
+}
+
+/* (:fcall self mid args) */
+static node*
+new_fcall(parser_state *p, mrb_sym b, node *c)
+{
+ node *n = new_self(p);
+ NODE_LINENO(n, c);
+ n = list4((node*)NODE_FCALL, n, nsym(b), c);
+ NODE_LINENO(n, c);
+ return n;
+}
+
+/* (:super . c) */
+static node*
+new_super(parser_state *p, node *c)
+{
+ return cons((node*)NODE_SUPER, c);
+}
+
+/* (:zsuper) */
+static node*
+new_zsuper(parser_state *p)
+{
+ return list1((node*)NODE_ZSUPER);
+}
+
+/* (:yield . c) */
+static node*
+new_yield(parser_state *p, node *c)
+{
+ if (c) {
+ if (c->cdr) {
+ yyerror(p, "both block arg and actual block given");
+ }
+ return cons((node*)NODE_YIELD, c->car);
+ }
+ return cons((node*)NODE_YIELD, 0);
+}
+
+/* (:return . c) */
+static node*
+new_return(parser_state *p, node *c)
+{
+ return cons((node*)NODE_RETURN, c);
+}
+
+/* (:break . c) */
+static node*
+new_break(parser_state *p, node *c)
+{
+ return cons((node*)NODE_BREAK, c);
+}
+
+/* (:next . c) */
+static node*
+new_next(parser_state *p, node *c)
+{
+ return cons((node*)NODE_NEXT, c);
+}
+
+/* (:redo) */
+static node*
+new_redo(parser_state *p)
+{
+ return list1((node*)NODE_REDO);
+}
+
+/* (:retry) */
+static node*
+new_retry(parser_state *p)
+{
+ return list1((node*)NODE_RETRY);
+}
+
+/* (:dot2 a b) */
+static node*
+new_dot2(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_DOT2, cons(a, b));
+}
+
+/* (:dot3 a b) */
+static node*
+new_dot3(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_DOT3, cons(a, b));
+}
+
+/* (:colon2 b c) */
+static node*
+new_colon2(parser_state *p, node *b, mrb_sym c)
+{
+ void_expr_error(p, b);
+ return cons((node*)NODE_COLON2, cons(b, nsym(c)));
+}
+
+/* (:colon3 . c) */
+static node*
+new_colon3(parser_state *p, mrb_sym c)
+{
+ return cons((node*)NODE_COLON3, nsym(c));
+}
+
+/* (:and a b) */
+static node*
+new_and(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_AND, cons(a, b));
+}
+
+/* (:or a b) */
+static node*
+new_or(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_OR, cons(a, b));
+}
+
+/* (:array a...) */
+static node*
+new_array(parser_state *p, node *a)
+{
+ return cons((node*)NODE_ARRAY, a);
+}
+
+/* (:splat . a) */
+static node*
+new_splat(parser_state *p, node *a)
+{
+ return cons((node*)NODE_SPLAT, a);
+}
+
+/* (:hash (k . v) (k . v)...) */
+static node*
+new_hash(parser_state *p, node *a)
+{
+ return cons((node*)NODE_HASH, a);
+}
+
+/* (:sym . a) */
+static node*
+new_sym(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_SYM, nsym(sym));
+}
+
+static mrb_sym
+new_strsym(parser_state *p, node* str)
+{
+ const char *s = (const char*)str->cdr->car;
+ size_t len = (size_t)str->cdr->cdr;
+
+ return mrb_intern(p->mrb, s, len);
+}
+
+/* (:lvar . a) */
+static node*
+new_lvar(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_LVAR, nsym(sym));
+}
+
+/* (:gvar . a) */
+static node*
+new_gvar(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_GVAR, nsym(sym));
+}
+
+/* (:ivar . a) */
+static node*
+new_ivar(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_IVAR, nsym(sym));
+}
+
+/* (:cvar . a) */
+static node*
+new_cvar(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_CVAR, nsym(sym));
+}
+
+/* (:const . a) */
+static node*
+new_const(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_CONST, nsym(sym));
+}
+
+/* (:undef a...) */
+static node*
+new_undef(parser_state *p, mrb_sym sym)
+{
+ return list2((node*)NODE_UNDEF, nsym(sym));
+}
+
+/* (:class class super body) */
+static node*
+new_class(parser_state *p, node *c, node *s, node *b)
+{
+ void_expr_error(p, s);
+ return list4((node*)NODE_CLASS, c, s, cons(locals_node(p), b));
+}
+
+/* (:sclass obj body) */
+static node*
+new_sclass(parser_state *p, node *o, node *b)
+{
+ void_expr_error(p, o);
+ return list3((node*)NODE_SCLASS, o, cons(locals_node(p), b));
+}
+
+/* (:module module body) */
+static node*
+new_module(parser_state *p, node *m, node *b)
+{
+ return list3((node*)NODE_MODULE, m, cons(locals_node(p), b));
+}
+
+/* (:def m lv (arg . body)) */
+static node*
+new_def(parser_state *p, mrb_sym m, node *a, node *b)
+{
+ return list5((node*)NODE_DEF, nsym(m), locals_node(p), a, b);
+}
+
+/* (:sdef obj m lv (arg . body)) */
+static node*
+new_sdef(parser_state *p, node *o, mrb_sym m, node *a, node *b)
+{
+ void_expr_error(p, o);
+ return list6((node*)NODE_SDEF, o, nsym(m), locals_node(p), a, b);
+}
+
+/* (:arg . sym) */
+static node*
+new_arg(parser_state *p, mrb_sym sym)
+{
+ return cons((node*)NODE_ARG, nsym(sym));
+}
+
+/* (m o r m2 b) */
+/* m: (a b c) */
+/* o: ((a . e1) (b . e2)) */
+/* r: a */
+/* m2: (a b c) */
+/* b: a */
+static node*
+new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk)
+{
+ node *n;
+
+ n = cons(m2, nsym(blk));
+ n = cons(nsym(rest), n);
+ n = cons(opt, n);
+ return cons(m, n);
+}
+
+/* (:block_arg . a) */
+static node*
+new_block_arg(parser_state *p, node *a)
+{
+ return cons((node*)NODE_BLOCK_ARG, a);
+}
+
+/* (:block arg body) */
+static node*
+new_block(parser_state *p, node *a, node *b)
+{
+ return list4((node*)NODE_BLOCK, locals_node(p), a, b);
+}
+
+/* (:lambda arg body) */
+static node*
+new_lambda(parser_state *p, node *a, node *b)
+{
+ return list4((node*)NODE_LAMBDA, locals_node(p), a, b);
+}
+
+/* (:asgn lhs rhs) */
+static node*
+new_asgn(parser_state *p, node *a, node *b)
+{
+ void_expr_error(p, b);
+ return cons((node*)NODE_ASGN, cons(a, b));
+}
+
+/* (:masgn mlhs=(pre rest post) mrhs) */
+static node*
+new_masgn(parser_state *p, node *a, node *b)
+{
+ void_expr_error(p, b);
+ return cons((node*)NODE_MASGN, cons(a, b));
+}
+
+/* (:asgn lhs rhs) */
+static node*
+new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
+{
+ void_expr_error(p, b);
+ return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
+}
+
+/* (:int . i) */
+static node*
+new_int(parser_state *p, const char *s, int base)
+{
+ return list3((node*)NODE_INT, (node*)strdup(s), nint(base));
+}
+
+/* (:float . i) */
+static node*
+new_float(parser_state *p, const char *s)
+{
+ return cons((node*)NODE_FLOAT, (node*)strdup(s));
+}
+
+/* (:str . (s . len)) */
+static node*
+new_str(parser_state *p, const char *s, size_t len)
+{
+ return cons((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
+}
+
+/* (:dstr . a) */
+static node*
+new_dstr(parser_state *p, node *a)
+{
+ return cons((node*)NODE_DSTR, a);
+}
+
+/* (:str . (s . len)) */
+static node*
+new_xstr(parser_state *p, const char *s, int len)
+{
+ return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), nint(len)));
+}
+
+/* (:xstr . a) */
+static node*
+new_dxstr(parser_state *p, node *a)
+{
+ return cons((node*)NODE_DXSTR, a);
+}
+
+/* (:dsym . a) */
+static node*
+new_dsym(parser_state *p, node *a)
+{
+ return cons((node*)NODE_DSYM, new_dstr(p, a));
+}
+
+/* (:regx . (s . (opt . enc))) */
+static node*
+new_regx(parser_state *p, const char *p1, const char* p2, const char* p3)
+{
+ return cons((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3)));
+}
+
+/* (:dregx . (a . b)) */
+static node*
+new_dregx(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_DREGX, cons(a, b));
+}
+
+/* (:backref . n) */
+static node*
+new_back_ref(parser_state *p, int n)
+{
+ return cons((node*)NODE_BACK_REF, nint(n));
+}
+
+/* (:nthref . n) */
+static node*
+new_nth_ref(parser_state *p, int n)
+{
+ return cons((node*)NODE_NTH_REF, nint(n));
+}
+
+/* (:heredoc . a) */
+static node*
+new_heredoc(parser_state *p)
+{
+ parser_heredoc_info *inf = (parser_heredoc_info *)parser_palloc(p, sizeof(parser_heredoc_info));
+ return cons((node*)NODE_HEREDOC, (node*)inf);
+}
+
+static void
+new_bv(parser_state *p, mrb_sym id)
+{
+}
+
+static node*
+new_literal_delim(parser_state *p)
+{
+ return cons((node*)NODE_LITERAL_DELIM, 0);
+}
+
+/* (:words . a) */
+static node*
+new_words(parser_state *p, node *a)
+{
+ return cons((node*)NODE_WORDS, a);
+}
+
+/* (:symbols . a) */
+static node*
+new_symbols(parser_state *p, node *a)
+{
+ return cons((node*)NODE_SYMBOLS, a);
+}
+
+/* xxx ----------------------------- */
+
+/* (:call a op) */
+static node*
+call_uni_op(parser_state *p, node *recv, const char *m)
+{
+ void_expr_error(p, recv);
+ return new_call(p, recv, intern_cstr(m), 0, 1);
+}
+
+/* (:call a op b) */
+static node*
+call_bin_op(parser_state *p, node *recv, const char *m, node *arg1)
+{
+ return new_call(p, recv, intern_cstr(m), list1(list1(arg1)), 1);
+}
+
+static void
+args_with_block(parser_state *p, node *a, node *b)
+{
+ if (b) {
+ if (a->cdr) {
+ yyerror(p, "both block arg and actual block given");
+ }
+ a->cdr = b;
+ }
+}
+
+static void
+call_with_block(parser_state *p, node *a, node *b)
+{
+ node *n;
+
+ switch ((enum node_type)intn(a->car)) {
+ case NODE_SUPER:
+ case NODE_ZSUPER:
+ if (!a->cdr) a->cdr = cons(0, b);
+ else {
+ args_with_block(p, a->cdr, b);
+ }
+ break;
+ case NODE_CALL:
+ case NODE_FCALL:
+ case NODE_SCALL:
+ n = a->cdr->cdr->cdr;
+ if (!n->car) n->car = cons(0, b);
+ else {
+ args_with_block(p, n->car, b);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static node*
+negate_lit(parser_state *p, node *n)
+{
+ return cons((node*)NODE_NEGATE, n);
+}
+
+static node*
+cond(node *n)
+{
+ return n;
+}
+
+static node*
+ret_args(parser_state *p, node *n)
+{
+ if (n->cdr) {
+ yyerror(p, "block argument should not be given");
+ return NULL;
+ }
+ if (!n->car->cdr) return n->car->car;
+ return new_array(p, n->car);
+}
+
+static void
+assignable(parser_state *p, node *lhs)
+{
+ if (intn(lhs->car) == NODE_LVAR) {
+ local_add(p, sym(lhs->cdr));
+ }
+}
+
+static node*
+var_reference(parser_state *p, node *lhs)
+{
+ node *n;
+
+ if (intn(lhs->car) == NODE_LVAR) {
+ if (!local_var_p(p, sym(lhs->cdr))) {
+ n = new_fcall(p, sym(lhs->cdr), 0);
+ cons_free(lhs);
+ return n;
+ }
+ }
+
+ return lhs;
+}
+
+typedef enum mrb_string_type string_type;
+
+static node*
+new_strterm(parser_state *p, string_type type, int term, int paren)
+{
+ return cons(nint(type), cons((node*)0, cons(nint(paren), nint(term))));
+}
+
+static void
+end_strterm(parser_state *p)
+{
+ cons_free(p->lex_strterm->cdr->cdr);
+ cons_free(p->lex_strterm->cdr);
+ cons_free(p->lex_strterm);
+ p->lex_strterm = NULL;
+}
+
+static parser_heredoc_info *
+parsing_heredoc_inf(parser_state *p)
+{
+ node *nd = p->parsing_heredoc;
+ if (nd == NULL)
+ return NULL;
+ /* mrb_assert(nd->car->car == NODE_HEREDOC); */
+ return (parser_heredoc_info*)nd->car->cdr;
+}
+
+static void
+heredoc_treat_nextline(parser_state *p)
+{
+ if (p->heredocs_from_nextline == NULL)
+ return;
+ if (p->parsing_heredoc == NULL) {
+ node *n;
+ p->parsing_heredoc = p->heredocs_from_nextline;
+ p->lex_strterm_before_heredoc = p->lex_strterm;
+ p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0);
+ n = p->all_heredocs;
+ if (n) {
+ while (n->cdr)
+ n = n->cdr;
+ n->cdr = p->parsing_heredoc;
+ }
+ else {
+ p->all_heredocs = p->parsing_heredoc;
+ }
+ }
+ else {
+ node *n, *m;
+ m = p->heredocs_from_nextline;
+ while (m->cdr)
+ m = m->cdr;
+ n = p->all_heredocs;
+ mrb_assert(n != NULL);
+ if (n == p->parsing_heredoc) {
+ m->cdr = n;
+ p->all_heredocs = p->heredocs_from_nextline;
+ p->parsing_heredoc = p->heredocs_from_nextline;
+ }
+ else {
+ while (n->cdr != p->parsing_heredoc) {
+ n = n->cdr;
+ mrb_assert(n != NULL);
+ }
+ m->cdr = n->cdr;
+ n->cdr = p->heredocs_from_nextline;
+ p->parsing_heredoc = p->heredocs_from_nextline;
+ }
+ }
+ p->heredocs_from_nextline = NULL;
+}
+
+static void
+heredoc_end(parser_state *p)
+{
+ p->parsing_heredoc = p->parsing_heredoc->cdr;
+ if (p->parsing_heredoc == NULL) {
+ p->lstate = EXPR_BEG;
+ p->cmd_start = TRUE;
+ end_strterm(p);
+ p->lex_strterm = p->lex_strterm_before_heredoc;
+ p->lex_strterm_before_heredoc = NULL;
+ p->heredoc_end_now = TRUE;
+ }
+ else {
+ /* next heredoc */
+ p->lex_strterm->car = nint(parsing_heredoc_inf(p)->type);
+ }
+}
+#define is_strterm_type(p,str_func) (intn((p)->lex_strterm->car) & (str_func))
+
+/* xxx ----------------------------- */
+
+%}
+
+%pure-parser
+%parse-param {parser_state *p}
+%lex-param {parser_state *p}
+
+%union {
+ node *nd;
+ mrb_sym id;
+ int num;
+ stack_type stack;
+ const struct vtable *vars;
+}
+
+%token <num>
+ keyword_class
+ keyword_module
+ keyword_def
+ keyword_begin
+ keyword_if
+ keyword_unless
+ keyword_while
+ keyword_until
+ keyword_for
+
+%token
+ keyword_undef
+ keyword_rescue
+ keyword_ensure
+ keyword_end
+ keyword_then
+ keyword_elsif
+ keyword_else
+ keyword_case
+ keyword_when
+ keyword_break
+ keyword_next
+ keyword_redo
+ keyword_retry
+ keyword_in
+ keyword_do
+ keyword_do_cond
+ keyword_do_block
+ keyword_do_LAMBDA
+ keyword_return
+ keyword_yield
+ keyword_super
+ keyword_self
+ keyword_nil
+ keyword_true
+ keyword_false
+ keyword_and
+ keyword_or
+ keyword_not
+ modifier_if
+ modifier_unless
+ modifier_while
+ modifier_until
+ modifier_rescue
+ keyword_alias
+ keyword_BEGIN
+ keyword_END
+ keyword__LINE__
+ keyword__FILE__
+ keyword__ENCODING__
+
+%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
+%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
+%token <nd> tSTRING tSTRING_PART tSTRING_MID tLABEL_END
+%token <nd> tNTH_REF tBACK_REF
+%token <num> tREGEXP_END
+
+%type <nd> singleton string string_rep string_interp xstring regexp
+%type <nd> literal numeric cpath symbol
+%type <nd> top_compstmt top_stmts top_stmt
+%type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
+%type <nd> expr_value arg_rhs primary_value
+%type <nd> if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure
+%type <nd> args call_args opt_call_args
+%type <nd> paren_args opt_paren_args variable
+%type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs
+%type <nd> command_asgn command_rhs mrhs superclass block_call block_command
+%type <nd> f_block_optarg f_block_opt
+%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
+%type <nd> assoc_list assocs assoc undef_list backref for_var
+%type <nd> block_param opt_block_param block_param_def f_opt
+%type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body
+%type <nd> brace_block cmd_brace_block do_block lhs none f_bad_arg
+%type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner
+%type <id> fsym sym basic_symbol operation operation2 operation3
+%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_opt_asgn
+%type <nd> heredoc words symbols
+%type <num> call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */
+
+%token tUPLUS /* unary+ */
+%token tUMINUS /* unary- */
+%token tPOW /* ** */
+%token tCMP /* <=> */
+%token tEQ /* == */
+%token tEQQ /* === */
+%token tNEQ /* != */
+%token tGEQ /* >= */
+%token tLEQ /* <= */
+%token tANDOP tOROP /* && and || */
+%token tMATCH tNMATCH /* =~ and !~ */
+%token tDOT2 tDOT3 /* .. and ... */
+%token tAREF tASET /* [] and []= */
+%token tLSHFT tRSHFT /* << and >> */
+%token tCOLON2 /* :: */
+%token tCOLON3 /* :: at EXPR_BEG */
+%token <id> tOP_ASGN /* +=, -= etc. */
+%token tASSOC /* => */
+%token tLPAREN /* ( */
+%token tLPAREN_ARG /* ( */
+%token tRPAREN /* ) */
+%token tLBRACK /* [ */
+%token tLBRACE /* { */
+%token tLBRACE_ARG /* { */
+%token tSTAR /* * */
+%token tAMPER /* & */
+%token tLAMBDA /* -> */
+%token tANDDOT /* &. */
+%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG
+%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG
+%token <nd> tHEREDOC_BEG /* <<, <<- */
+%token tHEREDOC_END tLITERAL_DELIM tHD_LITERAL_DELIM
+%token <nd> tHD_STRING_PART tHD_STRING_MID
+
+/*
+ * precedence table
+ */
+
+%nonassoc tLOWEST
+%nonassoc tLBRACE_ARG
+
+%nonassoc modifier_if modifier_unless modifier_while modifier_until
+%left keyword_or keyword_and
+%right keyword_not
+%right '=' tOP_ASGN
+%left modifier_rescue
+%right '?' ':'
+%nonassoc tDOT2 tDOT3
+%left tOROP
+%left tANDOP
+%nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
+%left '>' tGEQ '<' tLEQ
+%left '|' '^'
+%left '&'
+%left tLSHFT tRSHFT
+%left '+' '-'
+%left '*' '/' '%'
+%right tUMINUS_NUM tUMINUS
+%right tPOW
+%right '!' '~' tUPLUS
+
+%token tLAST_TOKEN
+
+%%
+program : {
+ p->lstate = EXPR_BEG;
+ if (!p->locals) p->locals = cons(0,0);
+ }
+ top_compstmt
+ {
+ p->tree = new_scope(p, $2);
+ NODE_LINENO(p->tree, $2);
+ }
+ ;
+
+top_compstmt : top_stmts opt_terms
+ {
+ $$ = $1;
+ }
+ ;
+
+top_stmts : none
+ {
+ $$ = new_begin(p, 0);
+ }
+ | top_stmt
+ {
+ $$ = new_begin(p, $1);
+ NODE_LINENO($$, $1);
+ }
+ | top_stmts terms top_stmt
+ {
+ $$ = push($1, newline_node($3));
+ }
+ | error top_stmt
+ {
+ $$ = new_begin(p, 0);
+ }
+ ;
+
+top_stmt : stmt
+ | keyword_BEGIN
+ {
+ $<nd>$ = local_switch(p);
+ }
+ '{' top_compstmt '}'
+ {
+ yyerror(p, "BEGIN not supported");
+ local_resume(p, $<nd>2);
+ $$ = 0;
+ }
+ ;
+
+bodystmt : compstmt
+ opt_rescue
+ opt_else
+ opt_ensure
+ {
+ if ($2) {
+ $$ = new_rescue(p, $1, $2, $3);
+ NODE_LINENO($$, $1);
+ }
+ else if ($3) {
+ yywarn(p, "else without rescue is useless");
+ $$ = push($1, $3);
+ }
+ else {
+ $$ = $1;
+ }
+ if ($4) {
+ if ($$) {
+ $$ = new_ensure(p, $$, $4);
+ }
+ else {
+ $$ = push($4, new_nil(p));
+ }
+ }
+ }
+ ;
+
+compstmt : stmts opt_terms
+ {
+ $$ = $1;
+ }
+ ;
+
+stmts : none
+ {
+ $$ = new_begin(p, 0);
+ }
+ | stmt
+ {
+ $$ = new_begin(p, $1);
+ NODE_LINENO($$, $1);
+ }
+ | stmts terms stmt
+ {
+ $$ = push($1, newline_node($3));
+ }
+ | error stmt
+ {
+ $$ = new_begin(p, $2);
+ }
+ ;
+
+stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym
+ {
+ $$ = new_alias(p, $2, $4);
+ }
+ | keyword_undef undef_list
+ {
+ $$ = $2;
+ }
+ | stmt modifier_if expr_value
+ {
+ $$ = new_if(p, cond($3), $1, 0);
+ }
+ | stmt modifier_unless expr_value
+ {
+ $$ = new_unless(p, cond($3), $1, 0);
+ }
+ | stmt modifier_while expr_value
+ {
+ $$ = new_while(p, cond($3), $1);
+ }
+ | stmt modifier_until expr_value
+ {
+ $$ = new_until(p, cond($3), $1);
+ }
+ | stmt modifier_rescue stmt
+ {
+ $$ = new_mod_rescue(p, $1, $3);
+ }
+ | keyword_END '{' compstmt '}'
+ {
+ yyerror(p, "END not supported");
+ $$ = new_postexe(p, $3);
+ }
+ | command_asgn
+ | mlhs '=' command_call
+ {
+ $$ = new_masgn(p, $1, $3);
+ }
+ | lhs '=' mrhs
+ {
+ $$ = new_asgn(p, $1, new_array(p, $3));
+ }
+ | mlhs '=' arg
+ {
+ $$ = new_masgn(p, $1, $3);
+ }
+ | mlhs '=' mrhs
+ {
+ $$ = new_masgn(p, $1, new_array(p, $3));
+ }
+ | expr
+ ;
+
+command_asgn : lhs '=' command_rhs
+ {
+ $$ = new_asgn(p, $1, $3);
+ }
+ | var_lhs tOP_ASGN command_rhs
+ {
+ $$ = new_op_asgn(p, $1, $2, $3);
+ }
+ | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
+ }
+ | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+ }
+ | primary_value call_op tCONSTANT tOP_ASGN command_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+ }
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
+ {
+ yyerror(p, "constant re-assignment");
+ $$ = 0;
+ }
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5);
+ }
+ | backref tOP_ASGN command_rhs
+ {
+ backref_error(p, $1);
+ $$ = new_begin(p, 0);
+ }
+ ;
+
+command_rhs : command_call %prec tOP_ASGN
+ | command_call modifier_rescue stmt
+ {
+ $$ = new_mod_rescue(p, $1, $3);
+ }
+ | command_asgn
+ ;
+
+
+expr : command_call
+ | expr keyword_and expr
+ {
+ $$ = new_and(p, $1, $3);
+ }
+ | expr keyword_or expr
+ {
+ $$ = new_or(p, $1, $3);
+ }
+ | keyword_not opt_nl expr
+ {
+ $$ = call_uni_op(p, cond($3), "!");
+ }
+ | '!' command_call
+ {
+ $$ = call_uni_op(p, cond($2), "!");
+ }
+ | arg
+ ;
+
+expr_value : expr
+ {
+ if (!$1) $$ = new_nil(p);
+ else {
+ $$ = $1;
+ }
+ }
+ ;
+
+command_call : command
+ | block_command
+ ;
+
+block_command : block_call
+ | block_call call_op2 operation2 command_args
+ {
+ $$ = new_call(p, $1, $3, $4, $2);
+ }
+ ;
+
+cmd_brace_block : tLBRACE_ARG
+ {
+ local_nest(p);
+ }
+ opt_block_param
+ compstmt
+ '}'
+ {
+ $$ = new_block(p, $3, $4);
+ local_unnest(p);
+ }
+ ;
+
+command : operation command_args %prec tLOWEST
+ {
+ $$ = new_fcall(p, $1, $2);
+ }
+ | operation command_args cmd_brace_block
+ {
+ args_with_block(p, $2, $3);
+ $$ = new_fcall(p, $1, $2);
+ }
+ | primary_value call_op operation2 command_args %prec tLOWEST
+ {
+ $$ = new_call(p, $1, $3, $4, $2);
+ }
+ | primary_value call_op operation2 command_args cmd_brace_block
+ {
+ args_with_block(p, $4, $5);
+ $$ = new_call(p, $1, $3, $4, $2);
+ }
+ | primary_value tCOLON2 operation2 command_args %prec tLOWEST
+ {
+ $$ = new_call(p, $1, $3, $4, tCOLON2);
+ }
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
+ {
+ args_with_block(p, $4, $5);
+ $$ = new_call(p, $1, $3, $4, tCOLON2);
+ }
+ | keyword_super command_args
+ {
+ $$ = new_super(p, $2);
+ }
+ | keyword_yield command_args
+ {
+ $$ = new_yield(p, $2);
+ }
+ | keyword_return call_args
+ {
+ $$ = new_return(p, ret_args(p, $2));
+ }
+ | keyword_break call_args
+ {
+ $$ = new_break(p, ret_args(p, $2));
+ }
+ | keyword_next call_args
+ {
+ $$ = new_next(p, ret_args(p, $2));
+ }
+ ;
+
+mlhs : mlhs_basic
+ {
+ $$ = $1;
+ }
+ | tLPAREN mlhs_inner rparen
+ {
+ $$ = $2;
+ }
+ ;
+
+mlhs_inner : mlhs_basic
+ | tLPAREN mlhs_inner rparen
+ {
+ $$ = $2;
+ }
+ ;
+
+mlhs_basic : mlhs_list
+ {
+ $$ = list1($1);
+ }
+ | mlhs_list mlhs_item
+ {
+ $$ = list1(push($1,$2));
+ }
+ | mlhs_list tSTAR mlhs_node
+ {
+ $$ = list2($1, $3);
+ }
+ | mlhs_list tSTAR mlhs_node ',' mlhs_post
+ {
+ $$ = list3($1, $3, $5);
+ }
+ | mlhs_list tSTAR
+ {
+ $$ = list2($1, new_nil(p));
+ }
+ | mlhs_list tSTAR ',' mlhs_post
+ {
+ $$ = list3($1, new_nil(p), $4);
+ }
+ | tSTAR mlhs_node
+ {
+ $$ = list2(0, $2);
+ }
+ | tSTAR mlhs_node ',' mlhs_post
+ {
+ $$ = list3(0, $2, $4);
+ }
+ | tSTAR
+ {
+ $$ = list2(0, new_nil(p));
+ }
+ | tSTAR ',' mlhs_post
+ {
+ $$ = list3(0, new_nil(p), $3);
+ }
+ ;
+
+mlhs_item : mlhs_node
+ | tLPAREN mlhs_inner rparen
+ {
+ $$ = new_masgn(p, $2, NULL);
+ }
+ ;
+
+mlhs_list : mlhs_item ','
+ {
+ $$ = list1($1);
+ }
+ | mlhs_list mlhs_item ','
+ {
+ $$ = push($1, $2);
+ }
+ ;
+
+mlhs_post : mlhs_item
+ {
+ $$ = list1($1);
+ }
+ | mlhs_list mlhs_item
+ {
+ $$ = push($1, $2);
+ }
+ ;
+
+mlhs_node : variable
+ {
+ assignable(p, $1);
+ }
+ | primary_value '[' opt_call_args rbracket
+ {
+ $$ = new_call(p, $1, intern("[]",2), $3, '.');
+ }
+ | primary_value call_op tIDENTIFIER
+ {
+ $$ = new_call(p, $1, $3, 0, $2);
+ }
+ | primary_value tCOLON2 tIDENTIFIER
+ {
+ $$ = new_call(p, $1, $3, 0, tCOLON2);
+ }
+ | primary_value call_op tCONSTANT
+ {
+ $$ = new_call(p, $1, $3, 0, $2);
+ }
+ | primary_value tCOLON2 tCONSTANT
+ {
+ if (p->in_def || p->in_single)
+ yyerror(p, "dynamic constant assignment");
+ $$ = new_colon2(p, $1, $3);
+ }
+ | tCOLON3 tCONSTANT
+ {
+ if (p->in_def || p->in_single)
+ yyerror(p, "dynamic constant assignment");
+ $$ = new_colon3(p, $2);
+ }
+ | backref
+ {
+ backref_error(p, $1);
+ $$ = 0;
+ }
+ ;
+
+lhs : variable
+ {
+ assignable(p, $1);
+ }
+ | primary_value '[' opt_call_args rbracket
+ {
+ $$ = new_call(p, $1, intern("[]",2), $3, '.');
+ }
+ | primary_value call_op tIDENTIFIER
+ {
+ $$ = new_call(p, $1, $3, 0, $2);
+ }
+ | primary_value tCOLON2 tIDENTIFIER
+ {
+ $$ = new_call(p, $1, $3, 0, tCOLON2);
+ }
+ | primary_value call_op tCONSTANT
+ {
+ $$ = new_call(p, $1, $3, 0, $2);
+ }
+ | primary_value tCOLON2 tCONSTANT
+ {
+ if (p->in_def || p->in_single)
+ yyerror(p, "dynamic constant assignment");
+ $$ = new_colon2(p, $1, $3);
+ }
+ | tCOLON3 tCONSTANT
+ {
+ if (p->in_def || p->in_single)
+ yyerror(p, "dynamic constant assignment");
+ $$ = new_colon3(p, $2);
+ }
+ | backref
+ {
+ backref_error(p, $1);
+ $$ = 0;
+ }
+ ;
+
+cname : tIDENTIFIER
+ {
+ yyerror(p, "class/module name must be CONSTANT");
+ }
+ | tCONSTANT
+ ;
+
+cpath : tCOLON3 cname
+ {
+ $$ = cons((node*)1, nsym($2));
+ }
+ | cname
+ {
+ $$ = cons((node*)0, nsym($1));
+ }
+ | primary_value tCOLON2 cname
+ {
+ void_expr_error(p, $1);
+ $$ = cons($1, nsym($3));
+ }
+ ;
+
+fname : tIDENTIFIER
+ | tCONSTANT
+ | tFID
+ | op
+ {
+ p->lstate = EXPR_ENDFN;
+ $$ = $1;
+ }
+ | reswords
+ {
+ p->lstate = EXPR_ENDFN;
+ $$ = $<id>1;
+ }
+ ;
+
+fsym : fname
+ | basic_symbol
+ ;
+
+undef_list : fsym
+ {
+ $$ = new_undef(p, $1);
+ }
+ | undef_list ',' {p->lstate = EXPR_FNAME;} fsym
+ {
+ $$ = push($1, nsym($4));
+ }
+ ;
+
+op : '|' { $$ = intern_c('|'); }
+ | '^' { $$ = intern_c('^'); }
+ | '&' { $$ = intern_c('&'); }
+ | tCMP { $$ = intern("<=>",3); }
+ | tEQ { $$ = intern("==",2); }
+ | tEQQ { $$ = intern("===",3); }
+ | tMATCH { $$ = intern("=~",2); }
+ | tNMATCH { $$ = intern("!~",2); }
+ | '>' { $$ = intern_c('>'); }
+ | tGEQ { $$ = intern(">=",2); }
+ | '<' { $$ = intern_c('<'); }
+ | tLEQ { $$ = intern("<=",2); }
+ | tNEQ { $$ = intern("!=",2); }
+ | tLSHFT { $$ = intern("<<",2); }
+ | tRSHFT { $$ = intern(">>",2); }
+ | '+' { $$ = intern_c('+'); }
+ | '-' { $$ = intern_c('-'); }
+ | '*' { $$ = intern_c('*'); }
+ | tSTAR { $$ = intern_c('*'); }
+ | '/' { $$ = intern_c('/'); }
+ | '%' { $$ = intern_c('%'); }
+ | tPOW { $$ = intern("**",2); }
+ | '!' { $$ = intern_c('!'); }
+ | '~' { $$ = intern_c('~'); }
+ | tUPLUS { $$ = intern("+@",2); }
+ | tUMINUS { $$ = intern("-@",2); }
+ | tAREF { $$ = intern("[]",2); }
+ | tASET { $$ = intern("[]=",3); }
+ | '`' { $$ = intern_c('`'); }
+ ;
+
+reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
+ | keyword_BEGIN | keyword_END
+ | keyword_alias | keyword_and | keyword_begin
+ | keyword_break | keyword_case | keyword_class | keyword_def
+ | keyword_do | keyword_else | keyword_elsif
+ | keyword_end | keyword_ensure | keyword_false
+ | keyword_for | keyword_in | keyword_module | keyword_next
+ | keyword_nil | keyword_not | keyword_or | keyword_redo
+ | keyword_rescue | keyword_retry | keyword_return | keyword_self
+ | keyword_super | keyword_then | keyword_true | keyword_undef
+ | keyword_when | keyword_yield | keyword_if | keyword_unless
+ | keyword_while | keyword_until
+ ;
+
+arg : lhs '=' arg_rhs
+ {
+ $$ = new_asgn(p, $1, $3);
+ }
+ | var_lhs tOP_ASGN arg_rhs
+ {
+ $$ = new_op_asgn(p, $1, $2, $3);
+ }
+ | primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
+ }
+ | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+ }
+ | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, $3, 0, $2), $4, $5);
+ }
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
+ {
+ $$ = new_op_asgn(p, new_call(p, $1, $3, 0, tCOLON2), $4, $5);
+ }
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
+ {
+ yyerror(p, "constant re-assignment");
+ $$ = new_begin(p, 0);
+ }
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
+ {
+ yyerror(p, "constant re-assignment");
+ $$ = new_begin(p, 0);
+ }
+ | backref tOP_ASGN arg_rhs
+ {
+ backref_error(p, $1);
+ $$ = new_begin(p, 0);
+ }
+ | arg tDOT2 arg
+ {
+ $$ = new_dot2(p, $1, $3);
+ }
+ | arg tDOT3 arg
+ {
+ $$ = new_dot3(p, $1, $3);
+ }
+ | arg '+' arg
+ {
+ $$ = call_bin_op(p, $1, "+", $3);
+ }
+ | arg '-' arg
+ {
+ $$ = call_bin_op(p, $1, "-", $3);
+ }
+ | arg '*' arg
+ {
+ $$ = call_bin_op(p, $1, "*", $3);
+ }
+ | arg '/' arg
+ {
+ $$ = call_bin_op(p, $1, "/", $3);
+ }
+ | arg '%' arg
+ {
+ $$ = call_bin_op(p, $1, "%", $3);
+ }
+ | arg tPOW arg
+ {
+ $$ = call_bin_op(p, $1, "**", $3);
+ }
+ | tUMINUS_NUM tINTEGER tPOW arg
+ {
+ $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
+ }
+ | tUMINUS_NUM tFLOAT tPOW arg
+ {
+ $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@");
+ }
+ | tUPLUS arg
+ {
+ $$ = call_uni_op(p, $2, "+@");
+ }
+ | tUMINUS arg
+ {
+ $$ = call_uni_op(p, $2, "-@");
+ }
+ | arg '|' arg
+ {
+ $$ = call_bin_op(p, $1, "|", $3);
+ }
+ | arg '^' arg
+ {
+ $$ = call_bin_op(p, $1, "^", $3);
+ }
+ | arg '&' arg
+ {
+ $$ = call_bin_op(p, $1, "&", $3);
+ }
+ | arg tCMP arg
+ {
+ $$ = call_bin_op(p, $1, "<=>", $3);
+ }
+ | arg '>' arg
+ {
+ $$ = call_bin_op(p, $1, ">", $3);
+ }
+ | arg tGEQ arg
+ {
+ $$ = call_bin_op(p, $1, ">=", $3);
+ }
+ | arg '<' arg
+ {
+ $$ = call_bin_op(p, $1, "<", $3);
+ }
+ | arg tLEQ arg
+ {
+ $$ = call_bin_op(p, $1, "<=", $3);
+ }
+ | arg tEQ arg
+ {
+ $$ = call_bin_op(p, $1, "==", $3);
+ }
+ | arg tEQQ arg
+ {
+ $$ = call_bin_op(p, $1, "===", $3);
+ }
+ | arg tNEQ arg
+ {
+ $$ = call_bin_op(p, $1, "!=", $3);
+ }
+ | arg tMATCH arg
+ {
+ $$ = call_bin_op(p, $1, "=~", $3);
+ }
+ | arg tNMATCH arg
+ {
+ $$ = call_bin_op(p, $1, "!~", $3);
+ }
+ | '!' arg
+ {
+ $$ = call_uni_op(p, cond($2), "!");
+ }
+ | '~' arg
+ {
+ $$ = call_uni_op(p, cond($2), "~");
+ }
+ | arg tLSHFT arg
+ {
+ $$ = call_bin_op(p, $1, "<<", $3);
+ }
+ | arg tRSHFT arg
+ {
+ $$ = call_bin_op(p, $1, ">>", $3);
+ }
+ | arg tANDOP arg
+ {
+ $$ = new_and(p, $1, $3);
+ }
+ | arg tOROP arg
+ {
+ $$ = new_or(p, $1, $3);
+ }
+ | arg '?' arg opt_nl ':' arg
+ {
+ $$ = new_if(p, cond($1), $3, $6);
+ }
+ | primary
+ {
+ $$ = $1;
+ }
+ ;
+
+aref_args : none
+ | args trailer
+ {
+ $$ = $1;
+ NODE_LINENO($$, $1);
+ }
+ | args comma assocs trailer
+ {
+ $$ = push($1, new_hash(p, $3));
+ }
+ | assocs trailer
+ {
+ $$ = cons(new_hash(p, $1), 0);
+ NODE_LINENO($$, $1);
+ }
+ ;
+
+arg_rhs : arg %prec tOP_ASGN
+ {
+ $$ = $1;
+ }
+ | arg modifier_rescue arg
+ {
+ void_expr_error(p, $1);
+ void_expr_error(p, $3);
+ $$ = new_mod_rescue(p, $1, $3);
+ }
+ ;
+
+paren_args : '(' opt_call_args rparen
+ {
+ $$ = $2;
+ }
+ ;
+
+opt_paren_args : none
+ | paren_args
+ ;
+
+opt_call_args : none
+ | call_args
+ | args ','
+ {
+ $$ = cons($1,0);
+ NODE_LINENO($$, $1);
+ }
+ | args comma assocs ','
+ {
+ $$ = cons(push($1, new_hash(p, $3)), 0);
+ NODE_LINENO($$, $1);
+ }
+ | assocs ','
+ {
+ $$ = cons(list1(new_hash(p, $1)), 0);
+ NODE_LINENO($$, $1);
+ }
+ ;
+
+call_args : command
+ {
+ void_expr_error(p, $1);
+ $$ = cons(list1($1), 0);
+ NODE_LINENO($$, $1);
+ }
+ | args opt_block_arg
+ {
+ $$ = cons($1, $2);
+ NODE_LINENO($$, $1);
+ }
+ | assocs opt_block_arg
+ {
+ $$ = cons(list1(new_hash(p, $1)), $2);
+ NODE_LINENO($$, $1);
+ }
+ | args comma assocs opt_block_arg
+ {
+ $$ = cons(push($1, new_hash(p, $3)), $4);
+ NODE_LINENO($$, $1);
+ }
+ | block_arg
+ {
+ $$ = cons(0, $1);
+ NODE_LINENO($$, $1);
+ }
+ ;
+
+command_args : {
+ $<stack>$ = p->cmdarg_stack;
+ CMDARG_PUSH(1);
+ }
+ call_args
+ {
+ p->cmdarg_stack = $<stack>1;
+ $$ = $2;
+ }
+ ;
+
+block_arg : tAMPER arg
+ {
+ $$ = new_block_arg(p, $2);
+ }
+ ;
+
+opt_block_arg : comma block_arg
+ {
+ $$ = $2;
+ }
+ | none
+ {
+ $$ = 0;
+ }
+ ;
+
+comma : ','
+ | ',' heredoc_bodies
+ ;
+
+args : arg
+ {
+ void_expr_error(p, $1);
+ $$ = cons($1, 0);
+ NODE_LINENO($$, $1);
+ }
+ | tSTAR arg
+ {
+ void_expr_error(p, $2);
+ $$ = cons(new_splat(p, $2), 0);
+ NODE_LINENO($$, $2);
+ }
+ | args comma arg
+ {
+ void_expr_error(p, $3);
+ $$ = push($1, $3);
+ }
+ | args comma tSTAR arg
+ {
+ void_expr_error(p, $4);
+ $$ = push($1, new_splat(p, $4));
+ }
+ ;
+
+mrhs : args comma arg
+ {
+ void_expr_error(p, $3);
+ $$ = push($1, $3);
+ }
+ | args comma tSTAR arg
+ {
+ void_expr_error(p, $4);
+ $$ = push($1, new_splat(p, $4));
+ }
+ | tSTAR arg
+ {
+ void_expr_error(p, $2);
+ $$ = list1(new_splat(p, $2));
+ }
+ ;
+
+primary : literal
+ | string
+ | xstring
+ | regexp
+ | heredoc
+ | var_ref
+ | backref
+ | tFID
+ {
+ $$ = new_fcall(p, $1, 0);
+ }
+ | keyword_begin
+ {
+ $<stack>$ = p->cmdarg_stack;
+ p->cmdarg_stack = 0;
+ }
+ bodystmt
+ keyword_end
+ {
+ p->cmdarg_stack = $<stack>2;
+ $$ = $3;
+ }
+ | tLPAREN_ARG
+ {
+ $<stack>$ = p->cmdarg_stack;
+ p->cmdarg_stack = 0;
+ }
+ stmt {p->lstate = EXPR_ENDARG;} rparen
+ {
+ p->cmdarg_stack = $<stack>2;
+ $$ = $3;
+ }
+ | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen
+ {
+ $$ = new_nil(p);
+ }
+ | tLPAREN compstmt ')'
+ {
+ $$ = $2;
+ }
+ | primary_value tCOLON2 tCONSTANT
+ {
+ $$ = new_colon2(p, $1, $3);
+ }
+ | tCOLON3 tCONSTANT
+ {
+ $$ = new_colon3(p, $2);
+ }
+ | tLBRACK aref_args ']'
+ {
+ $$ = new_array(p, $2);
+ NODE_LINENO($$, $2);
+ }
+ | tLBRACE assoc_list '}'
+ {
+ $$ = new_hash(p, $2);
+ NODE_LINENO($$, $2);
+ }
+ | keyword_return
+ {
+ $$ = new_return(p, 0);
+ }
+ | keyword_yield opt_paren_args
+ {
+ $$ = new_yield(p, $2);
+ }
+ | keyword_not '(' expr rparen
+ {
+ $$ = call_uni_op(p, cond($3), "!");
+ }
+ | keyword_not '(' rparen
+ {
+ $$ = call_uni_op(p, new_nil(p), "!");
+ }
+ | operation brace_block
+ {
+ $$ = new_fcall(p, $1, cons(0, $2));
+ }
+ | method_call
+ | method_call brace_block
+ {
+ call_with_block(p, $1, $2);
+ $$ = $1;
+ }
+ | tLAMBDA
+ {
+ local_nest(p);
+ $<num>$ = p->lpar_beg;
+ p->lpar_beg = ++p->paren_nest;
+ }
+ f_larglist
+ {
+ $<stack>$ = p->cmdarg_stack;
+ p->cmdarg_stack = 0;
+ }
+ lambda_body
+ {
+ p->lpar_beg = $<num>2;
+ $$ = new_lambda(p, $3, $5);
+ local_unnest(p);
+ p->cmdarg_stack = $<stack>4;
+ CMDARG_LEXPOP();
+ }
+ | keyword_if expr_value then
+ compstmt
+ if_tail
+ keyword_end
+ {
+ $$ = new_if(p, cond($2), $4, $5);
+ SET_LINENO($$, $1);
+ }
+ | keyword_unless expr_value then
+ compstmt
+ opt_else
+ keyword_end
+ {
+ $$ = new_unless(p, cond($2), $4, $5);
+ SET_LINENO($$, $1);
+ }
+ | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();}
+ compstmt
+ keyword_end
+ {
+ $$ = new_while(p, cond($3), $6);
+ SET_LINENO($$, $1);
+ }
+ | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();}
+ compstmt
+ keyword_end
+ {
+ $$ = new_until(p, cond($3), $6);
+ SET_LINENO($$, $1);
+ }
+ | keyword_case expr_value opt_terms
+ case_body
+ keyword_end
+ {
+ $$ = new_case(p, $2, $4);
+ }
+ | keyword_case opt_terms case_body keyword_end
+ {
+ $$ = new_case(p, 0, $3);
+ }
+ | keyword_for for_var keyword_in
+ {COND_PUSH(1);}
+ expr_value do
+ {COND_POP();}
+ compstmt
+ keyword_end
+ {
+ $$ = new_for(p, $2, $5, $8);
+ SET_LINENO($$, $1);
+ }
+ | keyword_class
+ cpath superclass
+ {
+ if (p->in_def || p->in_single)
+ yyerror(p, "class definition in method body");
+ $<nd>$ = local_switch(p);
+ }
+ bodystmt
+ keyword_end
+ {
+ $$ = new_class(p, $2, $3, $5);
+ SET_LINENO($$, $1);
+ local_resume(p, $<nd>4);
+ }
+ | keyword_class
+ tLSHFT expr
+ {
+ $<num>$ = p->in_def;
+ p->in_def = 0;
+ }
+ term
+ {
+ $<nd>$ = cons(local_switch(p), nint(p->in_single));
+ p->in_single = 0;
+ }
+ bodystmt
+ keyword_end
+ {
+ $$ = new_sclass(p, $3, $7);
+ SET_LINENO($$, $1);
+ local_resume(p, $<nd>6->car);
+ p->in_def = $<num>4;
+ p->in_single = intn($<nd>6->cdr);
+ }
+ | keyword_module
+ cpath
+ {
+ if (p->in_def || p->in_single)
+ yyerror(p, "module definition in method body");
+ $<nd>$ = local_switch(p);
+ }
+ bodystmt
+ keyword_end
+ {
+ $$ = new_module(p, $2, $4);
+ SET_LINENO($$, $1);
+ local_resume(p, $<nd>3);
+ }
+ | keyword_def fname
+ {
+ $<stack>$ = p->cmdarg_stack;
+ p->cmdarg_stack = 0;
+ }
+ {
+ p->in_def++;
+ $<nd>$ = local_switch(p);
+ }
+ f_arglist
+ bodystmt
+ keyword_end
+ {
+ $$ = new_def(p, $2, $5, $6);
+ SET_LINENO($$, $1);
+ local_resume(p, $<nd>4);
+ p->in_def--;
+ p->cmdarg_stack = $<stack>3;
+ }
+ | keyword_def singleton dot_or_colon
+ {
+ p->lstate = EXPR_FNAME;
+ $<stack>$ = p->cmdarg_stack;
+ p->cmdarg_stack = 0;
+ }
+ fname
+ {
+ p->in_single++;
+ p->lstate = EXPR_ENDFN; /* force for args */
+ $<nd>$ = local_switch(p);
+ }
+ f_arglist
+ bodystmt
+ keyword_end
+ {
+ $$ = new_sdef(p, $2, $5, $7, $8);
+ SET_LINENO($$, $1);
+ local_resume(p, $<nd>6);
+ p->in_single--;
+ p->cmdarg_stack = $<stack>4;
+ }
+ | keyword_break
+ {
+ $$ = new_break(p, 0);
+ }
+ | keyword_next
+ {
+ $$ = new_next(p, 0);
+ }
+ | keyword_redo
+ {
+ $$ = new_redo(p);
+ }
+ | keyword_retry
+ {
+ $$ = new_retry(p);
+ }
+ ;
+
+primary_value : primary
+ {
+ $$ = $1;
+ if (!$$) $$ = new_nil(p);
+ }
+ ;
+
+then : term
+ | keyword_then
+ | term keyword_then
+ ;
+
+do : term
+ | keyword_do_cond
+ ;
+
+if_tail : opt_else
+ | keyword_elsif expr_value then
+ compstmt
+ if_tail
+ {
+ $$ = new_if(p, cond($2), $4, $5);
+ }
+ ;
+
+opt_else : none
+ | keyword_else compstmt
+ {
+ $$ = $2;
+ }
+ ;
+
+for_var : lhs
+ {
+ $$ = list1(list1($1));
+ }
+ | mlhs
+ ;
+
+f_marg : f_norm_arg
+ {
+ $$ = new_arg(p, $1);
+ }
+ | tLPAREN f_margs rparen
+ {
+ $$ = new_masgn(p, $2, 0);
+ }
+ ;
+
+f_marg_list : f_marg
+ {
+ $$ = list1($1);
+ }
+ | f_marg_list ',' f_marg
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+f_margs : f_marg_list
+ {
+ $$ = list3($1,0,0);
+ }
+ | f_marg_list ',' tSTAR f_norm_arg
+ {
+ $$ = list3($1, new_arg(p, $4), 0);
+ }
+ | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
+ {
+ $$ = list3($1, new_arg(p, $4), $6);
+ }
+ | f_marg_list ',' tSTAR
+ {
+ $$ = list3($1, (node*)-1, 0);
+ }
+ | f_marg_list ',' tSTAR ',' f_marg_list
+ {
+ $$ = list3($1, (node*)-1, $5);
+ }
+ | tSTAR f_norm_arg
+ {
+ $$ = list3(0, new_arg(p, $2), 0);
+ }
+ | tSTAR f_norm_arg ',' f_marg_list
+ {
+ $$ = list3(0, new_arg(p, $2), $4);
+ }
+ | tSTAR
+ {
+ $$ = list3(0, (node*)-1, 0);
+ }
+ | tSTAR ',' f_marg_list
+ {
+ $$ = list3(0, (node*)-1, $3);
+ }
+ ;
+
+block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, $5, 0, $6);
+ }
+ | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, $5, $7, $8);
+ }
+ | f_arg ',' f_block_optarg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, 0, 0, $4);
+ }
+ | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, 0, $5, $6);
+ }
+ | f_arg ',' f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, 0, $3, 0, $4);
+ }
+ | f_arg ','
+ {
+ $$ = new_args(p, $1, 0, 0, 0, 0);
+ }
+ | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, 0, $3, $5, $6);
+ }
+ | f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, 0, 0, 0, $2);
+ }
+ | f_block_optarg ',' f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, $3, 0, $4);
+ }
+ | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, $3, $5, $6);
+ }
+ | f_block_optarg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, 0, 0, $2);
+ }
+ | f_block_optarg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, 0, $3, $4);
+ }
+ | f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, 0, $1, 0, $2);
+ }
+ | f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, 0, $1, $3, $4);
+ }
+ | f_block_arg
+ {
+ $$ = new_args(p, 0, 0, 0, 0, $1);
+ }
+ ;
+
+opt_block_param : none
+ | block_param_def
+ {
+ p->cmd_start = TRUE;
+ $$ = $1;
+ }
+ ;
+
+block_param_def : '|' opt_bv_decl '|'
+ {
+ $$ = 0;
+ }
+ | tOROP
+ {
+ $$ = 0;
+ }
+ | '|' block_param opt_bv_decl '|'
+ {
+ $$ = $2;
+ }
+ ;
+
+
+opt_bv_decl : opt_nl
+ {
+ $$ = 0;
+ }
+ | opt_nl ';' bv_decls opt_nl
+ {
+ $$ = 0;
+ }
+ ;
+
+bv_decls : bvar
+ | bv_decls ',' bvar
+ ;
+
+bvar : tIDENTIFIER
+ {
+ local_add_f(p, $1);
+ new_bv(p, $1);
+ }
+ | f_bad_arg
+ ;
+
+f_larglist : '(' f_args opt_bv_decl ')'
+ {
+ $$ = $2;
+ }
+ | f_args
+ {
+ $$ = $1;
+ }
+ ;
+
+lambda_body : tLAMBEG compstmt '}'
+ {
+ $$ = $2;
+ }
+ | keyword_do_LAMBDA compstmt keyword_end
+ {
+ $$ = $2;
+ }
+ ;
+
+do_block : keyword_do_block
+ {
+ local_nest(p);
+ }
+ opt_block_param
+ compstmt
+ keyword_end
+ {
+ $$ = new_block(p,$3,$4);
+ local_unnest(p);
+ }
+ ;
+
+block_call : command do_block
+ {
+ if ($1->car == (node*)NODE_YIELD) {
+ yyerror(p, "block given to yield");
+ }
+ else {
+ call_with_block(p, $1, $2);
+ }
+ $$ = $1;
+ }
+ | block_call call_op2 operation2 opt_paren_args
+ {
+ $$ = new_call(p, $1, $3, $4, $2);
+ }
+ | block_call call_op2 operation2 opt_paren_args brace_block
+ {
+ $$ = new_call(p, $1, $3, $4, $2);
+ call_with_block(p, $$, $5);
+ }
+ | block_call call_op2 operation2 command_args do_block
+ {
+ $$ = new_call(p, $1, $3, $4, $2);
+ call_with_block(p, $$, $5);
+ }
+ ;
+
+method_call : operation paren_args
+ {
+ $$ = new_fcall(p, $1, $2);
+ }
+ | primary_value call_op operation2 opt_paren_args
+ {
+ $$ = new_call(p, $1, $3, $4, $2);
+ }
+ | primary_value tCOLON2 operation2 paren_args
+ {
+ $$ = new_call(p, $1, $3, $4, tCOLON2);
+ }
+ | primary_value tCOLON2 operation3
+ {
+ $$ = new_call(p, $1, $3, 0, tCOLON2);
+ }
+ | primary_value call_op paren_args
+ {
+ $$ = new_call(p, $1, intern("call",4), $3, $2);
+ }
+ | primary_value tCOLON2 paren_args
+ {
+ $$ = new_call(p, $1, intern("call",4), $3, tCOLON2);
+ }
+ | keyword_super paren_args
+ {
+ $$ = new_super(p, $2);
+ }
+ | keyword_super
+ {
+ $$ = new_zsuper(p);
+ }
+ | primary_value '[' opt_call_args rbracket
+ {
+ $$ = new_call(p, $1, intern("[]",2), $3, '.');
+ }
+ ;
+
+brace_block : '{'
+ {
+ local_nest(p);
+ $<num>$ = p->lineno;
+ }
+ opt_block_param
+ compstmt '}'
+ {
+ $$ = new_block(p,$3,$4);
+ SET_LINENO($$, $<num>2);
+ local_unnest(p);
+ }
+ | keyword_do
+ {
+ local_nest(p);
+ $<num>$ = p->lineno;
+ }
+ opt_block_param
+ compstmt keyword_end
+ {
+ $$ = new_block(p,$3,$4);
+ SET_LINENO($$, $<num>2);
+ local_unnest(p);
+ }
+ ;
+
+case_body : keyword_when args then
+ compstmt
+ cases
+ {
+ $$ = cons(cons($2, $4), $5);
+ }
+ ;
+
+cases : opt_else
+ {
+ if ($1) {
+ $$ = cons(cons(0, $1), 0);
+ }
+ else {
+ $$ = 0;
+ }
+ }
+ | case_body
+ ;
+
+opt_rescue : keyword_rescue exc_list exc_var then
+ compstmt
+ opt_rescue
+ {
+ $$ = list1(list3($2, $3, $5));
+ if ($6) $$ = append($$, $6);
+ }
+ | none
+ ;
+
+exc_list : arg
+ {
+ $$ = list1($1);
+ }
+ | mrhs
+ | none
+ ;
+
+exc_var : tASSOC lhs
+ {
+ $$ = $2;
+ }
+ | none
+ ;
+
+opt_ensure : keyword_ensure compstmt
+ {
+ $$ = $2;
+ }
+ | none
+ ;
+
+literal : numeric
+ | symbol
+ | words
+ | symbols
+ ;
+
+string : tCHAR
+ | tSTRING
+ | tSTRING_BEG tSTRING
+ {
+ $$ = $2;
+ }
+ | tSTRING_BEG string_rep tSTRING
+ {
+ $$ = new_dstr(p, push($2, $3));
+ }
+ ;
+
+string_rep : string_interp
+ | string_rep string_interp
+ {
+ $$ = append($1, $2);
+ }
+ ;
+
+string_interp : tSTRING_MID
+ {
+ $$ = list1($1);
+ }
+ | tSTRING_PART
+ {
+ $<nd>$ = p->lex_strterm;
+ p->lex_strterm = NULL;
+ }
+ compstmt
+ '}'
+ {
+ p->lex_strterm = $<nd>2;
+ $$ = list2($1, $3);
+ }
+ | tLITERAL_DELIM
+ {
+ $$ = list1(new_literal_delim(p));
+ }
+ | tHD_LITERAL_DELIM heredoc_bodies
+ {
+ $$ = list1(new_literal_delim(p));
+ }
+ ;
+
+xstring : tXSTRING_BEG tXSTRING
+ {
+ $$ = $2;
+ }
+ | tXSTRING_BEG string_rep tXSTRING
+ {
+ $$ = new_dxstr(p, push($2, $3));
+ }
+ ;
+
+regexp : tREGEXP_BEG tREGEXP
+ {
+ $$ = $2;
+ }
+ | tREGEXP_BEG string_rep tREGEXP
+ {
+ $$ = new_dregx(p, $2, $3);
+ }
+ ;
+
+heredoc : tHEREDOC_BEG
+ ;
+
+heredoc_bodies : heredoc_body
+ | heredoc_bodies heredoc_body
+ ;
+
+heredoc_body : tHEREDOC_END
+ {
+ parser_heredoc_info * inf = parsing_heredoc_inf(p);
+ inf->doc = push(inf->doc, new_str(p, "", 0));
+ heredoc_end(p);
+ }
+ | heredoc_string_rep tHEREDOC_END
+ {
+ heredoc_end(p);
+ }
+ ;
+
+heredoc_string_rep : heredoc_string_interp
+ | heredoc_string_rep heredoc_string_interp
+ ;
+
+heredoc_string_interp : tHD_STRING_MID
+ {
+ parser_heredoc_info * inf = parsing_heredoc_inf(p);
+ inf->doc = push(inf->doc, $1);
+ heredoc_treat_nextline(p);
+ }
+ | tHD_STRING_PART
+ {
+ $<nd>$ = p->lex_strterm;
+ p->lex_strterm = NULL;
+ }
+ compstmt
+ '}'
+ {
+ parser_heredoc_info * inf = parsing_heredoc_inf(p);
+ p->lex_strterm = $<nd>2;
+ inf->doc = push(push(inf->doc, $1), $3);
+ }
+ ;
+
+words : tWORDS_BEG tSTRING
+ {
+ $$ = new_words(p, list1($2));
+ }
+ | tWORDS_BEG string_rep tSTRING
+ {
+ $$ = new_words(p, push($2, $3));
+ }
+ ;
+
+
+symbol : basic_symbol
+ {
+ $$ = new_sym(p, $1);
+ }
+ | tSYMBEG tSTRING_BEG string_rep tSTRING
+ {
+ p->lstate = EXPR_END;
+ $$ = new_dsym(p, push($3, $4));
+ }
+ ;
+
+basic_symbol : tSYMBEG sym
+ {
+ p->lstate = EXPR_END;
+ $$ = $2;
+ }
+ ;
+
+sym : fname
+ | tIVAR
+ | tGVAR
+ | tCVAR
+ | tSTRING
+ {
+ $$ = new_strsym(p, $1);
+ }
+ | tSTRING_BEG tSTRING
+ {
+ $$ = new_strsym(p, $2);
+ }
+ ;
+
+symbols : tSYMBOLS_BEG tSTRING
+ {
+ $$ = new_symbols(p, list1($2));
+ }
+ | tSYMBOLS_BEG string_rep tSTRING
+ {
+ $$ = new_symbols(p, push($2, $3));
+ }
+ ;
+
+numeric : tINTEGER
+ | tFLOAT
+ | tUMINUS_NUM tINTEGER %prec tLOWEST
+ {
+ $$ = negate_lit(p, $2);
+ }
+ | tUMINUS_NUM tFLOAT %prec tLOWEST
+ {
+ $$ = negate_lit(p, $2);
+ }
+ ;
+
+variable : tIDENTIFIER
+ {
+ $$ = new_lvar(p, $1);
+ }
+ | tIVAR
+ {
+ $$ = new_ivar(p, $1);
+ }
+ | tGVAR
+ {
+ $$ = new_gvar(p, $1);
+ }
+ | tCVAR
+ {
+ $$ = new_cvar(p, $1);
+ }
+ | tCONSTANT
+ {
+ $$ = new_const(p, $1);
+ }
+ ;
+
+var_lhs : variable
+ {
+ assignable(p, $1);
+ }
+ ;
+
+var_ref : variable
+ {
+ $$ = var_reference(p, $1);
+ }
+ | keyword_nil
+ {
+ $$ = new_nil(p);
+ }
+ | keyword_self
+ {
+ $$ = new_self(p);
+ }
+ | keyword_true
+ {
+ $$ = new_true(p);
+ }
+ | keyword_false
+ {
+ $$ = new_false(p);
+ }
+ | keyword__FILE__
+ {
+ const char *fn = p->filename;
+ if (!fn) {
+ fn = "(null)";
+ }
+ $$ = new_str(p, fn, strlen(fn));
+ }
+ | keyword__LINE__
+ {
+ char buf[16];
+
+ snprintf(buf, sizeof(buf), "%d", p->lineno);
+ $$ = new_int(p, buf, 10);
+ }
+ | keyword__ENCODING__
+ {
+#ifdef MRB_UTF8_STRING
+ const char *enc = "UTF-8";
+#else
+ const char *enc = "ASCII-8BIT";
+#endif
+ $$ = new_str(p, enc, strlen(enc));
+ }
+ ;
+
+backref : tNTH_REF
+ | tBACK_REF
+ ;
+
+superclass : /* term */
+ {
+ $$ = 0;
+ }
+ | '<'
+ {
+ p->lstate = EXPR_BEG;
+ p->cmd_start = TRUE;
+ }
+ expr_value term
+ {
+ $$ = $3;
+ } /*
+ | error term
+ {
+ yyerrok;
+ $$ = 0;
+ } */
+ ;
+
+f_arglist : '(' f_args rparen
+ {
+ $$ = $2;
+ p->lstate = EXPR_BEG;
+ p->cmd_start = TRUE;
+ }
+ | f_args term
+ {
+ $$ = $1;
+ }
+ ;
+
+f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, $5, 0, $6);
+ }
+ | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, $5, $7, $8);
+ }
+ | f_arg ',' f_optarg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, 0, 0, $4);
+ }
+ | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, $3, 0, $5, $6);
+ }
+ | f_arg ',' f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, 0, $3, 0, $4);
+ }
+ | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, 0, $3, $5, $6);
+ }
+ | f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, $1, 0, 0, 0, $2);
+ }
+ | f_optarg ',' f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, $3, 0, $4);
+ }
+ | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, $3, $5, $6);
+ }
+ | f_optarg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, 0, 0, $2);
+ }
+ | f_optarg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, $1, 0, $3, $4);
+ }
+ | f_rest_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, 0, $1, 0, $2);
+ }
+ | f_rest_arg ',' f_arg opt_f_block_arg
+ {
+ $$ = new_args(p, 0, 0, $1, $3, $4);
+ }
+ | f_block_arg
+ {
+ $$ = new_args(p, 0, 0, 0, 0, $1);
+ }
+ | /* none */
+ {
+ local_add_f(p, 0);
+ $$ = new_args(p, 0, 0, 0, 0, 0);
+ }
+ ;
+
+f_bad_arg : tCONSTANT
+ {
+ yyerror(p, "formal argument cannot be a constant");
+ $$ = 0;
+ }
+ | tIVAR
+ {
+ yyerror(p, "formal argument cannot be an instance variable");
+ $$ = 0;
+ }
+ | tGVAR
+ {
+ yyerror(p, "formal argument cannot be a global variable");
+ $$ = 0;
+ }
+ | tCVAR
+ {
+ yyerror(p, "formal argument cannot be a class variable");
+ $$ = 0;
+ }
+ ;
+
+f_norm_arg : f_bad_arg
+ {
+ $$ = 0;
+ }
+ | tIDENTIFIER
+ {
+ local_add_f(p, $1);
+ $$ = $1;
+ }
+ ;
+
+f_arg_item : f_norm_arg
+ {
+ $$ = new_arg(p, $1);
+ }
+ | tLPAREN f_margs rparen
+ {
+ $$ = new_masgn(p, $2, 0);
+ }
+ ;
+
+f_arg : f_arg_item
+ {
+ $$ = list1($1);
+ }
+ | f_arg ',' f_arg_item
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+f_opt_asgn : tIDENTIFIER '='
+ {
+ local_add_f(p, $1);
+ $$ = $1;
+ }
+ ;
+
+f_opt : f_opt_asgn arg
+ {
+ void_expr_error(p, $2);
+ $$ = cons(nsym($1), $2);
+ }
+ ;
+
+f_block_opt : f_opt_asgn primary_value
+ {
+ void_expr_error(p, $2);
+ $$ = cons(nsym($1), $2);
+ }
+ ;
+
+f_block_optarg : f_block_opt
+ {
+ $$ = list1($1);
+ }
+ | f_block_optarg ',' f_block_opt
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+f_optarg : f_opt
+ {
+ $$ = list1($1);
+ }
+ | f_optarg ',' f_opt
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+restarg_mark : '*'
+ | tSTAR
+ ;
+
+f_rest_arg : restarg_mark tIDENTIFIER
+ {
+ local_add_f(p, $2);
+ $$ = $2;
+ }
+ | restarg_mark
+ {
+ local_add_f(p, 0);
+ $$ = -1;
+ }
+ ;
+
+blkarg_mark : '&'
+ | tAMPER
+ ;
+
+f_block_arg : blkarg_mark tIDENTIFIER
+ {
+ local_add_f(p, $2);
+ $$ = $2;
+ }
+ ;
+
+opt_f_block_arg : ',' f_block_arg
+ {
+ $$ = $2;
+ }
+ | none
+ {
+ local_add_f(p, 0);
+ $$ = 0;
+ }
+ ;
+
+singleton : var_ref
+ {
+ $$ = $1;
+ if (!$$) $$ = new_nil(p);
+ }
+ | '(' {p->lstate = EXPR_BEG;} expr rparen
+ {
+ if ($3 == 0) {
+ yyerror(p, "can't define singleton method for ().");
+ }
+ else {
+ switch ((enum node_type)intn($3->car)) {
+ case NODE_STR:
+ case NODE_DSTR:
+ case NODE_XSTR:
+ case NODE_DXSTR:
+ case NODE_DREGX:
+ case NODE_MATCH:
+ case NODE_FLOAT:
+ case NODE_ARRAY:
+ case NODE_HEREDOC:
+ yyerror(p, "can't define singleton method for literals");
+ default:
+ break;
+ }
+ }
+ $$ = $3;
+ }
+ ;
+
+assoc_list : none
+ | assocs trailer
+ {
+ $$ = $1;
+ }
+ ;
+
+assocs : assoc
+ {
+ $$ = list1($1);
+ NODE_LINENO($$, $1);
+ }
+ | assocs ',' assoc
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+assoc : arg tASSOC arg
+ {
+ void_expr_error(p, $1);
+ void_expr_error(p, $3);
+ $$ = cons($1, $3);
+ }
+ | tLABEL arg
+ {
+ void_expr_error(p, $2);
+ $$ = cons(new_sym(p, $1), $2);
+ }
+ | tLABEL_END arg
+ {
+ void_expr_error(p, $2);
+ $$ = cons(new_sym(p, new_strsym(p, $1)), $2);
+ }
+ | tSTRING_BEG tLABEL_END arg
+ {
+ void_expr_error(p, $3);
+ $$ = cons(new_sym(p, new_strsym(p, $2)), $3);
+ }
+ | tSTRING_BEG string_rep tLABEL_END arg
+ {
+ void_expr_error(p, $4);
+ $$ = cons(new_dsym(p, push($2, $3)), $4);
+ }
+ ;
+
+operation : tIDENTIFIER
+ | tCONSTANT
+ | tFID
+ ;
+
+operation2 : tIDENTIFIER
+ | tCONSTANT
+ | tFID
+ | op
+ ;
+
+operation3 : tIDENTIFIER
+ | tFID
+ | op
+ ;
+
+dot_or_colon : '.'
+ | tCOLON2
+ ;
+
+call_op : '.'
+ {
+ $$ = '.';
+ }
+ | tANDDOT
+ {
+ $$ = 0;
+ }
+ ;
+
+call_op2 : call_op
+ | tCOLON2
+ {
+ $$ = tCOLON2;
+ }
+ ;
+
+opt_terms : /* none */
+ | terms
+ ;
+
+opt_nl : /* none */
+ | nl
+ ;
+
+rparen : opt_nl ')'
+ ;
+
+rbracket : opt_nl ']'
+ ;
+
+trailer : /* none */
+ | nl
+ | comma
+ ;
+
+term : ';' {yyerrok;}
+ | nl
+ | heredoc_body
+ ;
+
+nl : '\n'
+ {
+ p->lineno++;
+ p->column = 0;
+ }
+ ;
+
+terms : term
+ | terms term
+ ;
+
+none : /* none */
+ {
+ $$ = 0;
+ }
+ ;
+%%
+#define pylval (*((YYSTYPE*)(p->ylval)))
+
+static void
+yyerror(parser_state *p, const char *s)
+{
+ char* c;
+ size_t n;
+
+ if (! p->capture_errors) {
+#ifndef MRB_DISABLE_STDIO
+ if (p->filename) {
+ fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
+ }
+ else {
+ fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
+ }
+#endif
+ }
+ else if (p->nerr < sizeof(p->error_buffer) / sizeof(p->error_buffer[0])) {
+ n = strlen(s);
+ c = (char *)parser_palloc(p, n + 1);
+ memcpy(c, s, n + 1);
+ p->error_buffer[p->nerr].message = c;
+ p->error_buffer[p->nerr].lineno = p->lineno;
+ p->error_buffer[p->nerr].column = p->column;
+ }
+ p->nerr++;
+}
+
+static void
+yyerror_i(parser_state *p, const char *fmt, int i)
+{
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), fmt, i);
+ yyerror(p, buf);
+}
+
+static void
+yywarn(parser_state *p, const char *s)
+{
+ char* c;
+ size_t n;
+
+ if (! p->capture_errors) {
+#ifndef MRB_DISABLE_STDIO
+ if (p->filename) {
+ fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
+ }
+ else {
+ fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
+ }
+#endif
+ }
+ else if (p->nwarn < sizeof(p->warn_buffer) / sizeof(p->warn_buffer[0])) {
+ n = strlen(s);
+ c = (char *)parser_palloc(p, n + 1);
+ memcpy(c, s, n + 1);
+ p->warn_buffer[p->nwarn].message = c;
+ p->warn_buffer[p->nwarn].lineno = p->lineno;
+ p->warn_buffer[p->nwarn].column = p->column;
+ }
+ p->nwarn++;
+}
+
+static void
+yywarning(parser_state *p, const char *s)
+{
+ yywarn(p, s);
+}
+
+static void
+yywarning_s(parser_state *p, const char *fmt, const char *s)
+{
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), fmt, s);
+ yywarning(p, buf);
+}
+
+static void
+backref_error(parser_state *p, node *n)
+{
+ int c;
+
+ c = (int)(intptr_t)n->car;
+
+ if (c == NODE_NTH_REF) {
+ yyerror_i(p, "can't set variable $%" MRB_PRId, (mrb_int)(intptr_t)n->cdr);
+ }
+ else if (c == NODE_BACK_REF) {
+ yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
+ }
+ else {
+ mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
+ }
+}
+
+static void
+void_expr_error(parser_state *p, node *n)
+{
+ int c;
+
+ if (n == NULL) return;
+ c = (int)(intptr_t)n->car;
+ switch (c) {
+ case NODE_BREAK:
+ case NODE_RETURN:
+ case NODE_NEXT:
+ case NODE_REDO:
+ case NODE_RETRY:
+ yyerror(p, "void value expression");
+ break;
+ case NODE_AND:
+ case NODE_OR:
+ void_expr_error(p, n->cdr->car);
+ void_expr_error(p, n->cdr->cdr);
+ break;
+ case NODE_BEGIN:
+ if (n->cdr) {
+ while (n->cdr) {
+ n = n->cdr;
+ }
+ void_expr_error(p, n->car);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void pushback(parser_state *p, int c);
+static mrb_bool peeks(parser_state *p, const char *s);
+static mrb_bool skips(parser_state *p, const char *s);
+
+static inline int
+nextc(parser_state *p)
+{
+ int c;
+
+ if (p->pb) {
+ node *tmp;
+
+ c = (int)(intptr_t)p->pb->car;
+ tmp = p->pb;
+ p->pb = p->pb->cdr;
+ cons_free(tmp);
+ }
+ else {
+#ifndef MRB_DISABLE_STDIO
+ if (p->f) {
+ if (feof(p->f)) goto eof;
+ c = fgetc(p->f);
+ if (c == EOF) goto eof;
+ }
+ else
+#endif
+ if (!p->s || p->s >= p->send) {
+ goto eof;
+ }
+ else {
+ c = (unsigned char)*p->s++;
+ }
+ }
+ if (c >= 0) {
+ p->column++;
+ }
+ if (c == '\r') {
+ c = nextc(p);
+ if (c != '\n') {
+ pushback(p, c);
+ return '\r';
+ }
+ return c;
+ }
+ return c;
+
+ eof:
+ if (!p->cxt) return -1;
+ else {
+ if (p->cxt->partial_hook(p) < 0)
+ return -1; /* end of program(s) */
+ return -2; /* end of a file in the program files */
+ }
+}
+
+static void
+pushback(parser_state *p, int c)
+{
+ if (c >= 0) {
+ p->column--;
+ }
+ p->pb = cons((node*)(intptr_t)c, p->pb);
+}
+
+static void
+skip(parser_state *p, char term)
+{
+ int c;
+
+ for (;;) {
+ c = nextc(p);
+ if (c < 0) break;
+ if (c == term) break;
+ }
+}
+
+static int
+peekc_n(parser_state *p, int n)
+{
+ node *list = 0;
+ int c0;
+
+ do {
+ c0 = nextc(p);
+ if (c0 == -1) return c0; /* do not skip partial EOF */
+ if (c0 >= 0) --p->column;
+ list = push(list, (node*)(intptr_t)c0);
+ } while(n--);
+ if (p->pb) {
+ p->pb = append((node*)list, p->pb);
+ }
+ else {
+ p->pb = list;
+ }
+ return c0;
+}
+
+static mrb_bool
+peek_n(parser_state *p, int c, int n)
+{
+ return peekc_n(p, n) == c && c >= 0;
+}
+#define peek(p,c) peek_n((p), (c), 0)
+
+static mrb_bool
+peeks(parser_state *p, const char *s)
+{
+ size_t len = strlen(s);
+
+#ifndef MRB_DISABLE_STDIO
+ if (p->f) {
+ int n = 0;
+ while (*s) {
+ if (!peek_n(p, *s++, n++)) return FALSE;
+ }
+ return TRUE;
+ }
+ else
+#endif
+ if (p->s && p->s + len <= p->send) {
+ if (memcmp(p->s, s, len) == 0) return TRUE;
+ }
+ return FALSE;
+}
+
+static mrb_bool
+skips(parser_state *p, const char *s)
+{
+ int c;
+
+ for (;;) {
+ /* skip until first char */
+ for (;;) {
+ c = nextc(p);
+ if (c < 0) return FALSE;
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ }
+ if (c == *s) break;
+ }
+ s++;
+ if (peeks(p, s)) {
+ size_t len = strlen(s);
+
+ while (len--) {
+ if (nextc(p) == '\n') {
+ p->lineno++;
+ p->column = 0;
+ }
+ }
+ return TRUE;
+ }
+ else{
+ s--;
+ }
+ }
+ return FALSE;
+}
+
+
+static int
+newtok(parser_state *p)
+{
+ if (p->tokbuf != p->buf) {
+ mrb_free(p->mrb, p->tokbuf);
+ p->tokbuf = p->buf;
+ p->tsiz = MRB_PARSER_TOKBUF_SIZE;
+ }
+ p->tidx = 0;
+ return p->column - 1;
+}
+
+static void
+tokadd(parser_state *p, int32_t c)
+{
+ char utf8[4];
+ int i, len;
+
+ /* mrb_assert(-0x10FFFF <= c && c <= 0xFF); */
+ if (c >= 0) {
+ /* Single byte from source or non-Unicode escape */
+ utf8[0] = (char)c;
+ len = 1;
+ }
+ else {
+ /* Unicode character */
+ c = -c;
+ if (c < 0x80) {
+ utf8[0] = (char)c;
+ len = 1;
+ }
+ else if (c < 0x800) {
+ utf8[0] = (char)(0xC0 | (c >> 6));
+ utf8[1] = (char)(0x80 | (c & 0x3F));
+ len = 2;
+ }
+ else if (c < 0x10000) {
+ utf8[0] = (char)(0xE0 | (c >> 12) );
+ utf8[1] = (char)(0x80 | ((c >> 6) & 0x3F));
+ utf8[2] = (char)(0x80 | ( c & 0x3F));
+ len = 3;
+ }
+ else {
+ utf8[0] = (char)(0xF0 | (c >> 18) );
+ utf8[1] = (char)(0x80 | ((c >> 12) & 0x3F));
+ utf8[2] = (char)(0x80 | ((c >> 6) & 0x3F));
+ utf8[3] = (char)(0x80 | ( c & 0x3F));
+ len = 4;
+ }
+ }
+ if (p->tidx+len >= p->tsiz) {
+ if (p->tsiz >= MRB_PARSER_TOKBUF_MAX) {
+ p->tidx += len;
+ return;
+ }
+ p->tsiz *= 2;
+ if (p->tokbuf == p->buf) {
+ p->tokbuf = (char*)mrb_malloc(p->mrb, p->tsiz);
+ memcpy(p->tokbuf, p->buf, MRB_PARSER_TOKBUF_SIZE);
+ }
+ else {
+ p->tokbuf = (char*)mrb_realloc(p->mrb, p->tokbuf, p->tsiz);
+ }
+ }
+ for (i = 0; i < len; i++) {
+ p->tokbuf[p->tidx++] = utf8[i];
+ }
+}
+
+static int
+toklast(parser_state *p)
+{
+ return p->tokbuf[p->tidx-1];
+}
+
+static void
+tokfix(parser_state *p)
+{
+ if (p->tidx >= MRB_PARSER_TOKBUF_MAX) {
+ p->tidx = MRB_PARSER_TOKBUF_MAX-1;
+ yyerror(p, "string too long (truncated)");
+ }
+ p->tokbuf[p->tidx] = '\0';
+}
+
+static const char*
+tok(parser_state *p)
+{
+ return p->tokbuf;
+}
+
+static int
+toklen(parser_state *p)
+{
+ return p->tidx;
+}
+
+#define IS_ARG() (p->lstate == EXPR_ARG || p->lstate == EXPR_CMDARG)
+#define IS_END() (p->lstate == EXPR_END || p->lstate == EXPR_ENDARG || p->lstate == EXPR_ENDFN)
+#define IS_BEG() (p->lstate == EXPR_BEG || p->lstate == EXPR_MID || p->lstate == EXPR_VALUE || p->lstate == EXPR_CLASS)
+#define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
+#define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
+#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
+
+static int32_t
+scan_oct(const int *start, int len, int *retlen)
+{
+ const int *s = start;
+ int32_t retval = 0;
+
+ /* mrb_assert(len <= 3) */
+ while (len-- && *s >= '0' && *s <= '7') {
+ retval <<= 3;
+ retval |= *s++ - '0';
+ }
+ *retlen = (int)(s - start);
+
+ return retval;
+}
+
+static int32_t
+scan_hex(parser_state *p, const int *start, int len, int *retlen)
+{
+ static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
+ const int *s = start;
+ uint32_t retval = 0;
+ char *tmp;
+
+ /* mrb_assert(len <= 8) */
+ while (len-- && *s && (tmp = (char*)strchr(hexdigit, *s))) {
+ retval <<= 4;
+ retval |= (tmp - hexdigit) & 15;
+ s++;
+ }
+ *retlen = (int)(s - start);
+
+ return (int32_t)retval;
+}
+
+static int32_t
+read_escape_unicode(parser_state *p, int limit)
+{
+ int buf[9];
+ int i;
+ int32_t hex;
+
+ /* Look for opening brace */
+ i = 0;
+ buf[0] = nextc(p);
+ if (buf[0] < 0) {
+ eof:
+ yyerror(p, "invalid escape character syntax");
+ return -1;
+ }
+ if (ISXDIGIT(buf[0])) {
+ /* \uxxxx form */
+ for (i=1; i<limit; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] < 0) goto eof;
+ if (!ISXDIGIT(buf[i])) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ }
+ else {
+ pushback(p, buf[0]);
+ }
+ hex = scan_hex(p, buf, i, &i);
+ if (i == 0 || hex > 0x10FFFF || (hex & 0xFFFFF800) == 0xD800) {
+ yyerror(p, "invalid Unicode code point");
+ return -1;
+ }
+ return hex;
+}
+
+/* Return negative to indicate Unicode code point */
+static int32_t
+read_escape(parser_state *p)
+{
+ int32_t c;
+
+ switch (c = nextc(p)) {
+ case '\\':/* Backslash */
+ return c;
+
+ case 'n':/* newline */
+ return '\n';
+
+ case 't':/* horizontal tab */
+ return '\t';
+
+ case 'r':/* carriage-return */
+ return '\r';
+
+ case 'f':/* form-feed */
+ return '\f';
+
+ case 'v':/* vertical tab */
+ return '\13';
+
+ case 'a':/* alarm(bell) */
+ return '\007';
+
+ case 'e':/* escape */
+ return 033;
+
+ case '0': case '1': case '2': case '3': /* octal constant */
+ case '4': case '5': case '6': case '7':
+ {
+ int buf[3];
+ int i;
+
+ buf[0] = c;
+ for (i=1; i<3; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] < 0) goto eof;
+ if (buf[i] < '0' || '7' < buf[i]) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ c = scan_oct(buf, i, &i);
+ }
+ return c;
+
+ case 'x': /* hex constant */
+ {
+ int buf[2];
+ int i;
+
+ for (i=0; i<2; i++) {
+ buf[i] = nextc(p);
+ if (buf[i] < 0) goto eof;
+ if (!ISXDIGIT(buf[i])) {
+ pushback(p, buf[i]);
+ break;
+ }
+ }
+ if (i == 0) {
+ yyerror(p, "invalid hex escape");
+ return -1;
+ }
+ return scan_hex(p, buf, i, &i);
+ }
+
+ case 'u': /* Unicode */
+ if (peek(p, '{')) {
+ /* \u{xxxxxxxx} form */
+ nextc(p);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) return 0;
+ if (nextc(p) != '}') goto eof;
+ }
+ else {
+ c = read_escape_unicode(p, 4);
+ if (c < 0) return 0;
+ }
+ return -c;
+
+ case 'b':/* backspace */
+ return '\010';
+
+ case 's':/* space */
+ return ' ';
+
+ case 'M':
+ if ((c = nextc(p)) != '-') {
+ yyerror(p, "Invalid escape character syntax");
+ pushback(p, c);
+ return '\0';
+ }
+ if ((c = nextc(p)) == '\\') {
+ return read_escape(p) | 0x80;
+ }
+ else if (c < 0) goto eof;
+ else {
+ return ((c & 0xff) | 0x80);
+ }
+
+ case 'C':
+ if ((c = nextc(p)) != '-') {
+ yyerror(p, "Invalid escape character syntax");
+ pushback(p, c);
+ return '\0';
+ }
+ case 'c':
+ if ((c = nextc(p))== '\\') {
+ c = read_escape(p);
+ }
+ else if (c == '?')
+ return 0177;
+ else if (c < 0) goto eof;
+ return c & 0x9f;
+
+ eof:
+ case -1:
+ case -2: /* end of a file */
+ yyerror(p, "Invalid escape character syntax");
+ return '\0';
+
+ default:
+ return c;
+ }
+}
+
+static int
+parse_string(parser_state *p)
+{
+ int c;
+ string_type type = (string_type)(intptr_t)p->lex_strterm->car;
+ int nest_level = intn(p->lex_strterm->cdr->car);
+ int beg = intn(p->lex_strterm->cdr->cdr->car);
+ int end = intn(p->lex_strterm->cdr->cdr->cdr);
+ parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
+ int cmd_state = p->cmd_start;
+
+ if (beg == 0) beg = -3; /* should never happen */
+ if (end == 0) end = -3;
+ newtok(p);
+ while ((c = nextc(p)) != end || nest_level != 0) {
+ if (hinf && (c == '\n' || c < 0)) {
+ mrb_bool line_head;
+ tokadd(p, '\n');
+ tokfix(p);
+ p->lineno++;
+ p->column = 0;
+ line_head = hinf->line_head;
+ hinf->line_head = TRUE;
+ if (line_head) {
+ /* check whether end of heredoc */
+ const char *s = tok(p);
+ int len = toklen(p);
+ if (hinf->allow_indent) {
+ while (ISSPACE(*s) && len > 0) {
+ ++s;
+ --len;
+ }
+ }
+ if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
+ if (c < 0) {
+ p->parsing_heredoc = NULL;
+ }
+ else {
+ return tHEREDOC_END;
+ }
+ }
+ }
+ if (c < 0) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term);
+ yyerror(p, buf);
+ return 0;
+ }
+ pylval.nd = new_str(p, tok(p), toklen(p));
+ return tHD_STRING_MID;
+ }
+ if (c < 0) {
+ yyerror(p, "unterminated string meets end of file");
+ return 0;
+ }
+ else if (c == beg) {
+ nest_level++;
+ p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ }
+ else if (c == end) {
+ nest_level--;
+ p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ }
+ else if (c == '\\') {
+ c = nextc(p);
+ if (type & STR_FUNC_EXPAND) {
+ if (c == end || c == beg) {
+ tokadd(p, c);
+ }
+ else if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ if (type & STR_FUNC_ARRAY) {
+ tokadd(p, '\n');
+ }
+ }
+ else if (type & STR_FUNC_REGEXP) {
+ tokadd(p, '\\');
+ tokadd(p, c);
+ }
+ else if (c == 'u' && peek(p, '{')) {
+ /* \u{xxxx xxxx xxxx} form */
+ nextc(p);
+ while (1) {
+ do c = nextc(p); while (ISSPACE(c));
+ if (c == '}') break;
+ pushback(p, c);
+ c = read_escape_unicode(p, 8);
+ if (c < 0) break;
+ tokadd(p, -c);
+ }
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
+ else {
+ pushback(p, c);
+ tokadd(p, read_escape(p));
+ if (hinf)
+ hinf->line_head = FALSE;
+ }
+ }
+ else {
+ if (c != beg && c != end) {
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ }
+ if (!(c == '\\' || ((type & STR_FUNC_ARRAY) && ISSPACE(c)))) {
+ tokadd(p, '\\');
+ }
+ }
+ tokadd(p, c);
+ }
+ continue;
+ }
+ else if ((c == '#') && (type & STR_FUNC_EXPAND)) {
+ c = nextc(p);
+ if (c == '{') {
+ tokfix(p);
+ p->lstate = EXPR_BEG;
+ p->cmd_start = TRUE;
+ pylval.nd = new_str(p, tok(p), toklen(p));
+ if (hinf) {
+ hinf->line_head = FALSE;
+ return tHD_STRING_PART;
+ }
+ return tSTRING_PART;
+ }
+ tokadd(p, '#');
+ pushback(p, c);
+ continue;
+ }
+ if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) {
+ if (toklen(p) == 0) {
+ do {
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ heredoc_treat_nextline(p);
+ if (p->parsing_heredoc != NULL) {
+ return tHD_LITERAL_DELIM;
+ }
+ }
+ c = nextc(p);
+ } while (ISSPACE(c));
+ pushback(p, c);
+ return tLITERAL_DELIM;
+ }
+ else {
+ pushback(p, c);
+ tokfix(p);
+ pylval.nd = new_str(p, tok(p), toklen(p));
+ return tSTRING_MID;
+ }
+ }
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ }
+ tokadd(p, c);
+ }
+
+ tokfix(p);
+ p->lstate = EXPR_END;
+ end_strterm(p);
+
+ if (type & STR_FUNC_XQUOTE) {
+ pylval.nd = new_xstr(p, tok(p), toklen(p));
+ return tXSTRING;
+ }
+
+ if (type & STR_FUNC_REGEXP) {
+ int f = 0;
+ int re_opt;
+ char *s = strndup(tok(p), toklen(p));
+ char flags[3];
+ char *flag = flags;
+ char enc = '\0';
+ char *encp;
+ char *dup;
+
+ newtok(p);
+ while (re_opt = nextc(p), re_opt >= 0 && ISALPHA(re_opt)) {
+ switch (re_opt) {
+ case 'i': f |= 1; break;
+ case 'x': f |= 2; break;
+ case 'm': f |= 4; break;
+ case 'u': f |= 16; break;
+ case 'n': f |= 32; break;
+ default: tokadd(p, re_opt); break;
+ }
+ }
+ pushback(p, re_opt);
+ if (toklen(p)) {
+ char msg[128];
+ tokfix(p);
+ snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
+ toklen(p) > 1 ? "s" : "", tok(p));
+ yyerror(p, msg);
+ }
+ if (f != 0) {
+ if (f & 1) *flag++ = 'i';
+ if (f & 2) *flag++ = 'x';
+ if (f & 4) *flag++ = 'm';
+ if (f & 16) enc = 'u';
+ if (f & 32) enc = 'n';
+ }
+ if (flag > flags) {
+ dup = strndup(flags, (size_t)(flag - flags));
+ }
+ else {
+ dup = NULL;
+ }
+ if (enc) {
+ encp = strndup(&enc, 1);
+ }
+ else {
+ encp = NULL;
+ }
+ pylval.nd = new_regx(p, s, dup, encp);
+
+ return tREGEXP;
+ }
+ pylval.nd = new_str(p, tok(p), toklen(p));
+ if (IS_LABEL_POSSIBLE()) {
+ if (IS_LABEL_SUFFIX(0)) {
+ p->lstate = EXPR_BEG;
+ nextc(p);
+ return tLABEL_END;
+ }
+ }
+
+ return tSTRING;
+}
+
+
+static int
+heredoc_identifier(parser_state *p)
+{
+ int c;
+ int type = str_heredoc;
+ mrb_bool indent = FALSE;
+ mrb_bool quote = FALSE;
+ node *newnode;
+ parser_heredoc_info *info;
+
+ c = nextc(p);
+ if (ISSPACE(c) || c == '=') {
+ pushback(p, c);
+ return 0;
+ }
+ if (c == '-') {
+ indent = TRUE;
+ c = nextc(p);
+ }
+ if (c == '\'' || c == '"') {
+ int term = c;
+ if (c == '\'')
+ quote = TRUE;
+ newtok(p);
+ while ((c = nextc(p)) >= 0 && c != term) {
+ if (c == '\n') {
+ c = -1;
+ break;
+ }
+ tokadd(p, c);
+ }
+ if (c < 0) {
+ yyerror(p, "unterminated here document identifier");
+ return 0;
+ }
+ }
+ else {
+ if (c < 0) {
+ return 0; /* missing here document identifier */
+ }
+ if (! identchar(c)) {
+ pushback(p, c);
+ if (indent) pushback(p, '-');
+ return 0;
+ }
+ newtok(p);
+ do {
+ tokadd(p, c);
+ } while ((c = nextc(p)) >= 0 && identchar(c));
+ pushback(p, c);
+ }
+ tokfix(p);
+ newnode = new_heredoc(p);
+ info = (parser_heredoc_info*)newnode->cdr;
+ info->term = strndup(tok(p), toklen(p));
+ info->term_len = toklen(p);
+ if (! quote)
+ type |= STR_FUNC_EXPAND;
+ info->type = (string_type)type;
+ info->allow_indent = indent;
+ info->line_head = TRUE;
+ info->doc = NULL;
+ p->heredocs_from_nextline = push(p->heredocs_from_nextline, newnode);
+ p->lstate = EXPR_END;
+
+ pylval.nd = newnode;
+ return tHEREDOC_BEG;
+}
+
+static int
+arg_ambiguous(parser_state *p)
+{
+ yywarning(p, "ambiguous first argument; put parentheses or even spaces");
+ return 1;
+}
+
+#include "lex.def"
+
+static int
+parser_yylex(parser_state *p)
+{
+ int32_t c;
+ int space_seen = 0;
+ int cmd_state;
+ enum mrb_lex_state_enum last_state;
+ int token_column;
+
+ if (p->lex_strterm) {
+ if (is_strterm_type(p, STR_FUNC_HEREDOC)) {
+ if (p->parsing_heredoc != NULL)
+ return parse_string(p);
+ }
+ else
+ return parse_string(p);
+ }
+ cmd_state = p->cmd_start;
+ p->cmd_start = FALSE;
+ retry:
+ last_state = p->lstate;
+ switch (c = nextc(p)) {
+ case '\004': /* ^D */
+ case '\032': /* ^Z */
+ case '\0': /* NUL */
+ case -1: /* end of script. */
+ if (p->heredocs_from_nextline)
+ goto maybe_heredoc;
+ return 0;
+
+ /* white spaces */
+ case ' ': case '\t': case '\f': case '\r':
+ case '\13': /* '\v' */
+ space_seen = 1;
+ goto retry;
+
+ case '#': /* it's a comment */
+ skip(p, '\n');
+ /* fall through */
+ case -2: /* end of a file */
+ case '\n':
+ maybe_heredoc:
+ heredoc_treat_nextline(p);
+ switch (p->lstate) {
+ case EXPR_BEG:
+ case EXPR_FNAME:
+ case EXPR_DOT:
+ case EXPR_CLASS:
+ case EXPR_VALUE:
+ p->lineno++;
+ p->column = 0;
+ if (p->parsing_heredoc != NULL) {
+ if (p->lex_strterm) {
+ return parse_string(p);
+ }
+ }
+ goto retry;
+ default:
+ break;
+ }
+ if (p->parsing_heredoc != NULL) {
+ return '\n';
+ }
+ while ((c = nextc(p))) {
+ switch (c) {
+ case ' ': case '\t': case '\f': case '\r':
+ case '\13': /* '\v' */
+ space_seen = 1;
+ break;
+ case '.':
+ if ((c = nextc(p)) != '.') {
+ pushback(p, c);
+ pushback(p, '.');
+ goto retry;
+ }
+ case -1: /* EOF */
+ case -2: /* end of a file */
+ goto normal_newline;
+ default:
+ pushback(p, c);
+ goto normal_newline;
+ }
+ }
+ normal_newline:
+ p->cmd_start = TRUE;
+ p->lstate = EXPR_BEG;
+ return '\n';
+
+ case '*':
+ if ((c = nextc(p)) == '*') {
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern("**",2);
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ c = tPOW;
+ }
+ else {
+ if (c == '=') {
+ pylval.id = intern_c('*');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ if (IS_SPCARG(c)) {
+ yywarning(p, "'*' interpreted as argument prefix");
+ c = tSTAR;
+ }
+ else if (IS_BEG()) {
+ c = tSTAR;
+ }
+ else {
+ c = '*';
+ }
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ return c;
+
+ case '!':
+ c = nextc(p);
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ if (c == '@') {
+ return '!';
+ }
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ if (c == '=') {
+ return tNEQ;
+ }
+ if (c == '~') {
+ return tNMATCH;
+ }
+ pushback(p, c);
+ return '!';
+
+ case '=':
+ if (p->column == 1) {
+ static const char begin[] = "begin";
+ static const char end[] = "\n=end";
+ if (peeks(p, begin)) {
+ c = peekc_n(p, sizeof(begin)-1);
+ if (c < 0 || ISSPACE(c)) {
+ do {
+ if (!skips(p, end)) {
+ yyerror(p, "embedded document meets end of file");
+ return 0;
+ }
+ c = nextc(p);
+ } while (!(c < 0 || ISSPACE(c)));
+ if (c != '\n') skip(p, '\n');
+ p->lineno++;
+ p->column = 0;
+ goto retry;
+ }
+ }
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ if ((c = nextc(p)) == '=') {
+ if ((c = nextc(p)) == '=') {
+ return tEQQ;
+ }
+ pushback(p, c);
+ return tEQ;
+ }
+ if (c == '~') {
+ return tMATCH;
+ }
+ else if (c == '>') {
+ return tASSOC;
+ }
+ pushback(p, c);
+ return '=';
+
+ case '<':
+ c = nextc(p);
+ if (c == '<' &&
+ p->lstate != EXPR_DOT &&
+ p->lstate != EXPR_CLASS &&
+ !IS_END() &&
+ (!IS_ARG() || space_seen)) {
+ int token = heredoc_identifier(p);
+ if (token)
+ return token;
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ if (p->lstate == EXPR_CLASS) {
+ p->cmd_start = TRUE;
+ }
+ }
+ if (c == '=') {
+ if ((c = nextc(p)) == '>') {
+ return tCMP;
+ }
+ pushback(p, c);
+ return tLEQ;
+ }
+ if (c == '<') {
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern("<<",2);
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ return tLSHFT;
+ }
+ pushback(p, c);
+ return '<';
+
+ case '>':
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ if ((c = nextc(p)) == '=') {
+ return tGEQ;
+ }
+ if (c == '>') {
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern(">>",2);
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ return tRSHFT;
+ }
+ pushback(p, c);
+ return '>';
+
+ case '"':
+ p->lex_strterm = new_strterm(p, str_dquote, '"', 0);
+ return tSTRING_BEG;
+
+ case '\'':
+ p->lex_strterm = new_strterm(p, str_squote, '\'', 0);
+ return parse_string(p);
+
+ case '`':
+ if (p->lstate == EXPR_FNAME) {
+ p->lstate = EXPR_ENDFN;
+ return '`';
+ }
+ if (p->lstate == EXPR_DOT) {
+ if (cmd_state)
+ p->lstate = EXPR_CMDARG;
+ else
+ p->lstate = EXPR_ARG;
+ return '`';
+ }
+ p->lex_strterm = new_strterm(p, str_xquote, '`', 0);
+ return tXSTRING_BEG;
+
+ case '?':
+ if (IS_END()) {
+ p->lstate = EXPR_VALUE;
+ return '?';
+ }
+ c = nextc(p);
+ if (c < 0) {
+ yyerror(p, "incomplete character syntax");
+ return 0;
+ }
+ if (ISSPACE(c)) {
+ if (!IS_ARG()) {
+ int c2;
+ switch (c) {
+ case ' ':
+ c2 = 's';
+ break;
+ case '\n':
+ c2 = 'n';
+ break;
+ case '\t':
+ c2 = 't';
+ break;
+ case '\v':
+ c2 = 'v';
+ break;
+ case '\r':
+ c2 = 'r';
+ break;
+ case '\f':
+ c2 = 'f';
+ break;
+ default:
+ c2 = 0;
+ break;
+ }
+ if (c2) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
+ yyerror(p, buf);
+ }
+ }
+ ternary:
+ pushback(p, c);
+ p->lstate = EXPR_VALUE;
+ return '?';
+ }
+ newtok(p);
+ /* need support UTF-8 if configured */
+ if ((isalnum(c) || c == '_')) {
+ int c2 = nextc(p);
+ pushback(p, c2);
+ if ((isalnum(c2) || c2 == '_')) {
+ goto ternary;
+ }
+ }
+ if (c == '\\') {
+ c = read_escape(p);
+ tokadd(p, c);
+ }
+ else {
+ tokadd(p, c);
+ }
+ tokfix(p);
+ pylval.nd = new_str(p, tok(p), toklen(p));
+ p->lstate = EXPR_END;
+ return tCHAR;
+
+ case '&':
+ if ((c = nextc(p)) == '&') {
+ p->lstate = EXPR_BEG;
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern("&&",2);
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ return tANDOP;
+ }
+ else if (c == '.') {
+ p->lstate = EXPR_DOT;
+ return tANDDOT;
+ }
+ else if (c == '=') {
+ pylval.id = intern_c('&');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ if (IS_SPCARG(c)) {
+ yywarning(p, "'&' interpreted as argument prefix");
+ c = tAMPER;
+ }
+ else if (IS_BEG()) {
+ c = tAMPER;
+ }
+ else {
+ c = '&';
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ return c;
+
+ case '|':
+ if ((c = nextc(p)) == '|') {
+ p->lstate = EXPR_BEG;
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern("||",2);
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ return tOROP;
+ }
+ if (c == '=') {
+ pylval.id = intern_c('|');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ pushback(p, c);
+ return '|';
+
+ case '+':
+ c = nextc(p);
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ if (c == '@') {
+ return tUPLUS;
+ }
+ pushback(p, c);
+ return '+';
+ }
+ if (c == '=') {
+ pylval.id = intern_c('+');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
+ p->lstate = EXPR_BEG;
+ pushback(p, c);
+ if (c >= 0 && ISDIGIT(c)) {
+ c = '+';
+ goto start_num;
+ }
+ return tUPLUS;
+ }
+ p->lstate = EXPR_BEG;
+ pushback(p, c);
+ return '+';
+
+ case '-':
+ c = nextc(p);
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ if (c == '@') {
+ return tUMINUS;
+ }
+ pushback(p, c);
+ return '-';
+ }
+ if (c == '=') {
+ pylval.id = intern_c('-');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ if (c == '>') {
+ p->lstate = EXPR_ENDFN;
+ return tLAMBDA;
+ }
+ if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
+ p->lstate = EXPR_BEG;
+ pushback(p, c);
+ if (c >= 0 && ISDIGIT(c)) {
+ return tUMINUS_NUM;
+ }
+ return tUMINUS;
+ }
+ p->lstate = EXPR_BEG;
+ pushback(p, c);
+ return '-';
+
+ case '.':
+ p->lstate = EXPR_BEG;
+ if ((c = nextc(p)) == '.') {
+ if ((c = nextc(p)) == '.') {
+ return tDOT3;
+ }
+ pushback(p, c);
+ return tDOT2;
+ }
+ pushback(p, c);
+ if (c >= 0 && ISDIGIT(c)) {
+ yyerror(p, "no .<digit> floating literal anymore; put 0 before dot");
+ }
+ p->lstate = EXPR_DOT;
+ return '.';
+
+ start_num:
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ int is_float, seen_point, seen_e, nondigit;
+
+ is_float = seen_point = seen_e = nondigit = 0;
+ p->lstate = EXPR_END;
+ newtok(p);
+ if (c == '-' || c == '+') {
+ tokadd(p, c);
+ c = nextc(p);
+ }
+ if (c == '0') {
+#define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0)
+ int start = toklen(p);
+ c = nextc(p);
+ if (c == 'x' || c == 'X') {
+ /* hexadecimal */
+ c = nextc(p);
+ if (c >= 0 && ISXDIGIT(c)) {
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (!ISXDIGIT(c)) break;
+ nondigit = 0;
+ tokadd(p, tolower(c));
+ } while ((c = nextc(p)) >= 0);
+ }
+ pushback(p, c);
+ tokfix(p);
+ if (toklen(p) == start) {
+ no_digits();
+ }
+ else if (nondigit) goto trailing_uc;
+ pylval.nd = new_int(p, tok(p), 16);
+ return tINTEGER;
+ }
+ if (c == 'b' || c == 'B') {
+ /* binary */
+ c = nextc(p);
+ if (c == '0' || c == '1') {
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (c != '0' && c != '1') break;
+ nondigit = 0;
+ tokadd(p, c);
+ } while ((c = nextc(p)) >= 0);
+ }
+ pushback(p, c);
+ tokfix(p);
+ if (toklen(p) == start) {
+ no_digits();
+ }
+ else if (nondigit) goto trailing_uc;
+ pylval.nd = new_int(p, tok(p), 2);
+ return tINTEGER;
+ }
+ if (c == 'd' || c == 'D') {
+ /* decimal */
+ c = nextc(p);
+ if (c >= 0 && ISDIGIT(c)) {
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (!ISDIGIT(c)) break;
+ nondigit = 0;
+ tokadd(p, c);
+ } while ((c = nextc(p)) >= 0);
+ }
+ pushback(p, c);
+ tokfix(p);
+ if (toklen(p) == start) {
+ no_digits();
+ }
+ else if (nondigit) goto trailing_uc;
+ pylval.nd = new_int(p, tok(p), 10);
+ return tINTEGER;
+ }
+ if (c == '_') {
+ /* 0_0 */
+ goto octal_number;
+ }
+ if (c == 'o' || c == 'O') {
+ /* prefixed octal */
+ c = nextc(p);
+ if (c < 0 || c == '_' || !ISDIGIT(c)) {
+ no_digits();
+ }
+ }
+ if (c >= '0' && c <= '7') {
+ /* octal */
+ octal_number:
+ do {
+ if (c == '_') {
+ if (nondigit) break;
+ nondigit = c;
+ continue;
+ }
+ if (c < '0' || c > '9') break;
+ if (c > '7') goto invalid_octal;
+ nondigit = 0;
+ tokadd(p, c);
+ } while ((c = nextc(p)) >= 0);
+
+ if (toklen(p) > start) {
+ pushback(p, c);
+ tokfix(p);
+ if (nondigit) goto trailing_uc;
+ pylval.nd = new_int(p, tok(p), 8);
+ return tINTEGER;
+ }
+ if (nondigit) {
+ pushback(p, c);
+ goto trailing_uc;
+ }
+ }
+ if (c > '7' && c <= '9') {
+ invalid_octal:
+ yyerror(p, "Invalid octal digit");
+ }
+ else if (c == '.' || c == 'e' || c == 'E') {
+ tokadd(p, '0');
+ }
+ else {
+ pushback(p, c);
+ pylval.nd = new_int(p, "0", 10);
+ return tINTEGER;
+ }
+ }
+
+ for (;;) {
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ nondigit = 0;
+ tokadd(p, c);
+ break;
+
+ case '.':
+ if (nondigit) goto trailing_uc;
+ if (seen_point || seen_e) {
+ goto decode_num;
+ }
+ else {
+ int c0 = nextc(p);
+ if (c0 < 0 || !ISDIGIT(c0)) {
+ pushback(p, c0);
+ goto decode_num;
+ }
+ c = c0;
+ }
+ tokadd(p, '.');
+ tokadd(p, c);
+ is_float++;
+ seen_point++;
+ nondigit = 0;
+ break;
+
+ case 'e':
+ case 'E':
+ if (nondigit) {
+ pushback(p, c);
+ c = nondigit;
+ goto decode_num;
+ }
+ if (seen_e) {
+ goto decode_num;
+ }
+ tokadd(p, c);
+ seen_e++;
+ is_float++;
+ nondigit = c;
+ c = nextc(p);
+ if (c != '-' && c != '+') continue;
+ tokadd(p, c);
+ nondigit = c;
+ break;
+
+ case '_': /* '_' in number just ignored */
+ if (nondigit) goto decode_num;
+ nondigit = c;
+ break;
+
+ default:
+ goto decode_num;
+ }
+ c = nextc(p);
+ }
+
+ decode_num:
+ pushback(p, c);
+ if (nondigit) {
+ trailing_uc:
+ yyerror_i(p, "trailing '%c' in number", nondigit);
+ }
+ tokfix(p);
+ if (is_float) {
+ double d;
+ char *endp;
+
+ errno = 0;
+ d = mrb_float_read(tok(p), &endp);
+ if (d == 0 && endp == tok(p)) {
+ yywarning_s(p, "corrupted float value %s", tok(p));
+ }
+ else if (errno == ERANGE) {
+ yywarning_s(p, "float %s out of range", tok(p));
+ errno = 0;
+ }
+ pylval.nd = new_float(p, tok(p));
+ return tFLOAT;
+ }
+ pylval.nd = new_int(p, tok(p), 10);
+ return tINTEGER;
+ }
+
+ case ')':
+ case ']':
+ p->paren_nest--;
+ /* fall through */
+ case '}':
+ COND_LEXPOP();
+ CMDARG_LEXPOP();
+ if (c == ')')
+ p->lstate = EXPR_ENDFN;
+ else
+ p->lstate = EXPR_ENDARG;
+ return c;
+
+ case ':':
+ c = nextc(p);
+ if (c == ':') {
+ if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) {
+ p->lstate = EXPR_BEG;
+ return tCOLON3;
+ }
+ p->lstate = EXPR_DOT;
+ return tCOLON2;
+ }
+ if (IS_END() || ISSPACE(c)) {
+ pushback(p, c);
+ p->lstate = EXPR_BEG;
+ return ':';
+ }
+ pushback(p, c);
+ p->lstate = EXPR_FNAME;
+ return tSYMBEG;
+
+ case '/':
+ if (IS_BEG()) {
+ p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
+ return tREGEXP_BEG;
+ }
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern_c('/');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ pushback(p, c);
+ if (IS_SPCARG(c)) {
+ p->lex_strterm = new_strterm(p, str_regexp, '/', 0);
+ return tREGEXP_BEG;
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ return '/';
+
+ case '^':
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern_c('^');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ pushback(p, c);
+ return '^';
+
+ case ';':
+ p->lstate = EXPR_BEG;
+ return ';';
+
+ case ',':
+ p->lstate = EXPR_BEG;
+ return ',';
+
+ case '~':
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ if ((c = nextc(p)) != '@') {
+ pushback(p, c);
+ }
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ return '~';
+
+ case '(':
+ if (IS_BEG()) {
+ c = tLPAREN;
+ }
+ else if (IS_SPCARG(-1)) {
+ c = tLPAREN_ARG;
+ }
+ p->paren_nest++;
+ COND_PUSH(0);
+ CMDARG_PUSH(0);
+ p->lstate = EXPR_BEG;
+ return c;
+
+ case '[':
+ p->paren_nest++;
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ if ((c = nextc(p)) == ']') {
+ if ((c = nextc(p)) == '=') {
+ return tASET;
+ }
+ pushback(p, c);
+ return tAREF;
+ }
+ pushback(p, c);
+ return '[';
+ }
+ else if (IS_BEG()) {
+ c = tLBRACK;
+ }
+ else if (IS_ARG() && space_seen) {
+ c = tLBRACK;
+ }
+ p->lstate = EXPR_BEG;
+ COND_PUSH(0);
+ CMDARG_PUSH(0);
+ return c;
+
+ case '{':
+ if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
+ p->lstate = EXPR_BEG;
+ p->lpar_beg = 0;
+ p->paren_nest--;
+ COND_PUSH(0);
+ CMDARG_PUSH(0);
+ return tLAMBEG;
+ }
+ if (IS_ARG() || p->lstate == EXPR_END || p->lstate == EXPR_ENDFN)
+ c = '{'; /* block (primary) */
+ else if (p->lstate == EXPR_ENDARG)
+ c = tLBRACE_ARG; /* block (expr) */
+ else
+ c = tLBRACE; /* hash */
+ COND_PUSH(0);
+ CMDARG_PUSH(0);
+ p->lstate = EXPR_BEG;
+ return c;
+
+ case '\\':
+ c = nextc(p);
+ if (c == '\n') {
+ p->lineno++;
+ p->column = 0;
+ space_seen = 1;
+ goto retry; /* skip \\n */
+ }
+ pushback(p, c);
+ return '\\';
+
+ case '%':
+ if (IS_BEG()) {
+ int term;
+ int paren;
+
+ c = nextc(p);
+ quotation:
+ if (c < 0 || !ISALNUM(c)) {
+ term = c;
+ c = 'Q';
+ }
+ else {
+ term = nextc(p);
+ if (isalnum(term)) {
+ yyerror(p, "unknown type of %string");
+ return 0;
+ }
+ }
+ if (c < 0 || term < 0) {
+ yyerror(p, "unterminated quoted string meets end of file");
+ return 0;
+ }
+ paren = term;
+ if (term == '(') term = ')';
+ else if (term == '[') term = ']';
+ else if (term == '{') term = '}';
+ else if (term == '<') term = '>';
+ else paren = 0;
+
+ switch (c) {
+ case 'Q':
+ p->lex_strterm = new_strterm(p, str_dquote, term, paren);
+ return tSTRING_BEG;
+
+ case 'q':
+ p->lex_strterm = new_strterm(p, str_squote, term, paren);
+ return parse_string(p);
+
+ case 'W':
+ p->lex_strterm = new_strterm(p, str_dword, term, paren);
+ return tWORDS_BEG;
+
+ case 'w':
+ p->lex_strterm = new_strterm(p, str_sword, term, paren);
+ return tWORDS_BEG;
+
+ case 'x':
+ p->lex_strterm = new_strterm(p, str_xquote, term, paren);
+ return tXSTRING_BEG;
+
+ case 'r':
+ p->lex_strterm = new_strterm(p, str_regexp, term, paren);
+ return tREGEXP_BEG;
+
+ case 's':
+ p->lex_strterm = new_strterm(p, str_ssym, term, paren);
+ return tSYMBEG;
+
+ case 'I':
+ p->lex_strterm = new_strterm(p, str_dsymbols, term, paren);
+ return tSYMBOLS_BEG;
+
+ case 'i':
+ p->lex_strterm = new_strterm(p, str_ssymbols, term, paren);
+ return tSYMBOLS_BEG;
+
+ default:
+ yyerror(p, "unknown type of %string");
+ return 0;
+ }
+ }
+ if ((c = nextc(p)) == '=') {
+ pylval.id = intern_c('%');
+ p->lstate = EXPR_BEG;
+ return tOP_ASGN;
+ }
+ if (IS_SPCARG(c)) {
+ goto quotation;
+ }
+ if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) {
+ p->lstate = EXPR_ARG;
+ }
+ else {
+ p->lstate = EXPR_BEG;
+ }
+ pushback(p, c);
+ return '%';
+
+ case '$':
+ p->lstate = EXPR_END;
+ token_column = newtok(p);
+ c = nextc(p);
+ if (c < 0) {
+ yyerror(p, "incomplete global variable syntax");
+ return 0;
+ }
+ switch (c) {
+ case '_': /* $_: last read line string */
+ c = nextc(p);
+ if (c >= 0 && identchar(c)) { /* if there is more after _ it is a variable */
+ tokadd(p, '$');
+ tokadd(p, c);
+ break;
+ }
+ pushback(p, c);
+ c = '_';
+ /* fall through */
+ case '~': /* $~: match-data */
+ case '*': /* $*: argv */
+ case '$': /* $$: pid */
+ case '?': /* $?: last status */
+ case '!': /* $!: error string */
+ case '@': /* $@: error position */
+ case '/': /* $/: input record separator */
+ case '\\': /* $\: output record separator */
+ case ';': /* $;: field separator */
+ case ',': /* $,: output field separator */
+ case '.': /* $.: last read line number */
+ case '=': /* $=: ignorecase */
+ case ':': /* $:: load path */
+ case '<': /* $<: reading filename */
+ case '>': /* $>: default output handle */
+ case '\"': /* $": already loaded files */
+ tokadd(p, '$');
+ tokadd(p, c);
+ tokfix(p);
+ pylval.id = intern_cstr(tok(p));
+ return tGVAR;
+
+ case '-':
+ tokadd(p, '$');
+ tokadd(p, c);
+ c = nextc(p);
+ pushback(p, c);
+ gvar:
+ tokfix(p);
+ pylval.id = intern_cstr(tok(p));
+ return tGVAR;
+
+ case '&': /* $&: last match */
+ case '`': /* $`: string before last match */
+ case '\'': /* $': string after last match */
+ case '+': /* $+: string matches last pattern */
+ if (last_state == EXPR_FNAME) {
+ tokadd(p, '$');
+ tokadd(p, c);
+ goto gvar;
+ }
+ pylval.nd = new_back_ref(p, c);
+ return tBACK_REF;
+
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ do {
+ tokadd(p, c);
+ c = nextc(p);
+ } while (c >= 0 && isdigit(c));
+ pushback(p, c);
+ if (last_state == EXPR_FNAME) goto gvar;
+ tokfix(p);
+ {
+ unsigned long n = strtoul(tok(p), NULL, 10);
+ if (n > INT_MAX) {
+ yyerror_i(p, "capture group index must be <= %d", INT_MAX);
+ return 0;
+ }
+ pylval.nd = new_nth_ref(p, (int)n);
+ }
+ return tNTH_REF;
+
+ default:
+ if (!identchar(c)) {
+ pushback(p, c);
+ return '$';
+ }
+ /* fall through */
+ case '0':
+ tokadd(p, '$');
+ }
+ break;
+
+ case '@':
+ c = nextc(p);
+ token_column = newtok(p);
+ tokadd(p, '@');
+ if (c == '@') {
+ tokadd(p, '@');
+ c = nextc(p);
+ }
+ if (c < 0) {
+ if (p->tidx == 1) {
+ yyerror(p, "incomplete instance variable syntax");
+ }
+ else {
+ yyerror(p, "incomplete class variable syntax");
+ }
+ return 0;
+ }
+ else if (isdigit(c)) {
+ if (p->tidx == 1) {
+ yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
+ }
+ else {
+ yyerror_i(p, "'@@%c' is not allowed as a class variable name", c);
+ }
+ return 0;
+ }
+ if (!identchar(c)) {
+ pushback(p, c);
+ return '@';
+ }
+ break;
+
+ case '_':
+ token_column = newtok(p);
+ break;
+
+ default:
+ if (!identchar(c)) {
+ yyerror_i(p, "Invalid char '\\x%02X' in expression", c);
+ goto retry;
+ }
+
+ token_column = newtok(p);
+ break;
+ }
+
+ do {
+ tokadd(p, c);
+ c = nextc(p);
+ if (c < 0) break;
+ } while (identchar(c));
+ if (token_column == 0 && toklen(p) == 7 && (c < 0 || c == '\n') &&
+ strncmp(tok(p), "__END__", toklen(p)) == 0)
+ return -1;
+
+ switch (tok(p)[0]) {
+ case '@': case '$':
+ pushback(p, c);
+ break;
+ default:
+ if ((c == '!' || c == '?') && !peek(p, '=')) {
+ tokadd(p, c);
+ }
+ else {
+ pushback(p, c);
+ }
+ }
+ tokfix(p);
+ {
+ int result = 0;
+
+ switch (tok(p)[0]) {
+ case '$':
+ p->lstate = EXPR_END;
+ result = tGVAR;
+ break;
+ case '@':
+ p->lstate = EXPR_END;
+ if (tok(p)[1] == '@')
+ result = tCVAR;
+ else
+ result = tIVAR;
+ break;
+
+ default:
+ if (toklast(p) == '!' || toklast(p) == '?') {
+ result = tFID;
+ }
+ else {
+ if (p->lstate == EXPR_FNAME) {
+ if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
+ (!peek(p, '=') || (peek_n(p, '>', 1)))) {
+ result = tIDENTIFIER;
+ tokadd(p, c);
+ tokfix(p);
+ }
+ else {
+ pushback(p, c);
+ }
+ }
+ if (result == 0 && ISUPPER(tok(p)[0])) {
+ result = tCONSTANT;
+ }
+ else {
+ result = tIDENTIFIER;
+ }
+ }
+
+ if (IS_LABEL_POSSIBLE()) {
+ if (IS_LABEL_SUFFIX(0)) {
+ p->lstate = EXPR_BEG;
+ nextc(p);
+ tokfix(p);
+ pylval.id = intern_cstr(tok(p));
+ return tLABEL;
+ }
+ }
+ if (p->lstate != EXPR_DOT) {
+ const struct kwtable *kw;
+
+ /* See if it is a reserved word. */
+ kw = mrb_reserved_word(tok(p), toklen(p));
+ if (kw) {
+ enum mrb_lex_state_enum state = p->lstate;
+ pylval.num = p->lineno;
+ p->lstate = kw->state;
+ if (state == EXPR_FNAME) {
+ pylval.id = intern_cstr(kw->name);
+ return kw->id[0];
+ }
+ if (p->lstate == EXPR_BEG) {
+ p->cmd_start = TRUE;
+ }
+ if (kw->id[0] == keyword_do) {
+ if (p->lpar_beg && p->lpar_beg == p->paren_nest) {
+ p->lpar_beg = 0;
+ p->paren_nest--;
+ return keyword_do_LAMBDA;
+ }
+ if (COND_P()) return keyword_do_cond;
+ if (CMDARG_P() && state != EXPR_CMDARG)
+ return keyword_do_block;
+ if (state == EXPR_ENDARG || state == EXPR_BEG)
+ return keyword_do_block;
+ return keyword_do;
+ }
+ if (state == EXPR_BEG || state == EXPR_VALUE)
+ return kw->id[0];
+ else {
+ if (kw->id[0] != kw->id[1])
+ p->lstate = EXPR_BEG;
+ return kw->id[1];
+ }
+ }
+ }
+
+ if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) {
+ if (cmd_state) {
+ p->lstate = EXPR_CMDARG;
+ }
+ else {
+ p->lstate = EXPR_ARG;
+ }
+ }
+ else if (p->lstate == EXPR_FNAME) {
+ p->lstate = EXPR_ENDFN;
+ }
+ else {
+ p->lstate = EXPR_END;
+ }
+ }
+ {
+ mrb_sym ident = intern_cstr(tok(p));
+
+ pylval.id = ident;
+#if 0
+ if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
+ p->lstate = EXPR_END;
+ }
+#endif
+ }
+ return result;
+ }
+}
+
+static int
+yylex(void *lval, parser_state *p)
+{
+ p->ylval = lval;
+ return parser_yylex(p);
+}
+
+static void
+parser_init_cxt(parser_state *p, mrbc_context *cxt)
+{
+ if (!cxt) return;
+ if (cxt->filename) mrb_parser_set_filename(p, cxt->filename);
+ if (cxt->lineno) p->lineno = cxt->lineno;
+ if (cxt->syms) {
+ int i;
+
+ p->locals = cons(0,0);
+ for (i=0; i<cxt->slen; i++) {
+ local_add_f(p, cxt->syms[i]);
+ }
+ }
+ p->capture_errors = cxt->capture_errors;
+ p->no_optimize = cxt->no_optimize;
+ if (cxt->partial_hook) {
+ p->cxt = cxt;
+ }
+}
+
+static void
+parser_update_cxt(parser_state *p, mrbc_context *cxt)
+{
+ node *n, *n0;
+ int i = 0;
+
+ if (!cxt) return;
+ if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
+ n0 = n = p->tree->cdr->car;
+ while (n) {
+ i++;
+ n = n->cdr;
+ }
+ cxt->syms = (mrb_sym *)mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
+ cxt->slen = i;
+ for (i=0, n=n0; n; i++,n=n->cdr) {
+ cxt->syms[i] = sym(n->car);
+ }
+}
+
+void mrb_codedump_all(mrb_state*, struct RProc*);
+void mrb_parser_dump(mrb_state *mrb, node *tree, int offset);
+
+MRB_API void
+mrb_parser_parse(parser_state *p, mrbc_context *c)
+{
+ struct mrb_jmpbuf buf1;
+ p->jmp = &buf1;
+
+ MRB_TRY(p->jmp) {
+ int n = 1;
+
+ p->cmd_start = TRUE;
+ p->in_def = p->in_single = 0;
+ p->nerr = p->nwarn = 0;
+ p->lex_strterm = NULL;
+
+ parser_init_cxt(p, c);
+
+ if (p->mrb->jmp) {
+ n = yyparse(p);
+ }
+ else {
+ struct mrb_jmpbuf buf2;
+
+ p->mrb->jmp = &buf2;
+ MRB_TRY(p->mrb->jmp) {
+ n = yyparse(p);
+ }
+ MRB_CATCH(p->mrb->jmp) {
+ p->nerr++;
+ }
+ MRB_END_EXC(p->mrb->jmp);
+ p->mrb->jmp = 0;
+ }
+ if (n != 0 || p->nerr > 0) {
+ p->tree = 0;
+ return;
+ }
+ if (!p->tree) {
+ p->tree = new_nil(p);
+ }
+ parser_update_cxt(p, c);
+ if (c && c->dump_result) {
+ mrb_parser_dump(p->mrb, p->tree, 0);
+ }
+ }
+ MRB_CATCH(p->jmp) {
+ yyerror(p, "memory allocation error");
+ p->nerr++;
+ p->tree = 0;
+ return;
+ }
+ MRB_END_EXC(p->jmp);
+}
+
+MRB_API parser_state*
+mrb_parser_new(mrb_state *mrb)
+{
+ mrb_pool *pool;
+ parser_state *p;
+ static const parser_state parser_state_zero = { 0 };
+
+ pool = mrb_pool_open(mrb);
+ if (!pool) return NULL;
+ p = (parser_state *)mrb_pool_alloc(pool, sizeof(parser_state));
+ if (!p) return NULL;
+
+ *p = parser_state_zero;
+ p->mrb = mrb;
+ p->pool = pool;
+
+ p->s = p->send = NULL;
+#ifndef MRB_DISABLE_STDIO
+ p->f = NULL;
+#endif
+
+ p->cmd_start = TRUE;
+ p->in_def = p->in_single = 0;
+
+ p->capture_errors = FALSE;
+ p->lineno = 1;
+ p->column = 0;
+#if defined(PARSER_TEST) || defined(PARSER_DEBUG)
+ yydebug = 1;
+#endif
+ p->tsiz = MRB_PARSER_TOKBUF_SIZE;
+ p->tokbuf = p->buf;
+
+ p->lex_strterm = NULL;
+ p->all_heredocs = p->parsing_heredoc = NULL;
+ p->lex_strterm_before_heredoc = NULL;
+
+ p->current_filename_index = -1;
+ p->filename_table = NULL;
+ p->filename_table_length = 0;
+
+ return p;
+}
+
+MRB_API void
+mrb_parser_free(parser_state *p) {
+ if (p->tokbuf != p->buf) {
+ mrb_free(p->mrb, p->tokbuf);
+ }
+ mrb_pool_close(p->pool);
+}
+
+MRB_API mrbc_context*
+mrbc_context_new(mrb_state *mrb)
+{
+ return (mrbc_context *)mrb_calloc(mrb, 1, sizeof(mrbc_context));
+}
+
+MRB_API void
+mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
+{
+ mrb_free(mrb, cxt->filename);
+ mrb_free(mrb, cxt->syms);
+ mrb_free(mrb, cxt);
+}
+
+MRB_API const char*
+mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
+{
+ if (s) {
+ size_t len = strlen(s);
+ char *p = (char *)mrb_malloc(mrb, len + 1);
+
+ memcpy(p, s, len + 1);
+ if (c->filename) {
+ mrb_free(mrb, c->filename);
+ }
+ c->filename = p;
+ }
+ return c->filename;
+}
+
+MRB_API void
+mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser_state*), void *data)
+{
+ c->partial_hook = func;
+ c->partial_data = data;
+}
+
+MRB_API void
+mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
+{
+ mrb_sym sym;
+ size_t i;
+ mrb_sym* new_table;
+
+ sym = mrb_intern_cstr(p->mrb, f);
+ p->filename = mrb_sym2name_len(p->mrb, sym, NULL);
+ p->lineno = (p->filename_table_length > 0)? 0 : 1;
+
+ for (i = 0; i < p->filename_table_length; ++i) {
+ if (p->filename_table[i] == sym) {
+ p->current_filename_index = (int)i;
+ return;
+ }
+ }
+
+ p->current_filename_index = (int)p->filename_table_length++;
+
+ new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
+ if (p->filename_table) {
+ memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length);
+ }
+ p->filename_table = new_table;
+ p->filename_table[p->filename_table_length - 1] = sym;
+}
+
+MRB_API char const*
+mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
+ if (idx >= p->filename_table_length) { return NULL; }
+ else {
+ return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL);
+ }
+}
+
+#ifndef MRB_DISABLE_STDIO
+MRB_API parser_state*
+mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
+{
+ parser_state *p;
+
+ p = mrb_parser_new(mrb);
+ if (!p) return NULL;
+ p->s = p->send = NULL;
+ p->f = f;
+
+ mrb_parser_parse(p, c);
+ return p;
+}
+#endif
+
+MRB_API parser_state*
+mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
+{
+ parser_state *p;
+
+ p = mrb_parser_new(mrb);
+ if (!p) return NULL;
+ p->s = s;
+ p->send = s + len;
+
+ mrb_parser_parse(p, c);
+ return p;
+}
+
+MRB_API parser_state*
+mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
+{
+ return mrb_parse_nstring(mrb, s, strlen(s), c);
+}
+
+MRB_API mrb_value
+mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
+{
+ struct RClass *target = mrb->object_class;
+ struct RProc *proc;
+ mrb_value v;
+ unsigned int keep = 0;
+
+ if (!p) {
+ return mrb_undef_value();
+ }
+ if (!p->tree || p->nerr) {
+ if (c) c->parser_nerr = p->nerr;
+ if (p->capture_errors) {
+ char buf[256];
+ int n;
+
+ n = snprintf(buf, sizeof(buf), "line %d: %s\n",
+ p->error_buffer[0].lineno, p->error_buffer[0].message);
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ mrb_parser_free(p);
+ return mrb_undef_value();
+ }
+ else {
+ if (mrb->exc == NULL) {
+ mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SYNTAX_ERROR, "syntax error"));
+ }
+ mrb_parser_free(p);
+ return mrb_undef_value();
+ }
+ }
+ proc = mrb_generate_code(mrb, p);
+ mrb_parser_free(p);
+ if (proc == NULL) {
+ if (mrb->exc == NULL) {
+ mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "codegen error"));
+ }
+ return mrb_undef_value();
+ }
+ if (c) {
+ if (c->dump_result) mrb_codedump_all(mrb, proc);
+ if (c->no_exec) return mrb_obj_value(proc);
+ if (c->target_class) {
+ target = c->target_class;
+ }
+ if (c->keep_lv) {
+ keep = c->slen + 1;
+ }
+ else {
+ c->keep_lv = TRUE;
+ }
+ }
+ proc->target_class = target;
+ if (mrb->c->ci) {
+ mrb->c->ci->target_class = target;
+ }
+ v = mrb_top_run(mrb, proc, mrb_top_self(mrb), keep);
+ if (mrb->exc) return mrb_nil_value();
+ return v;
+}
+
+#ifndef MRB_DISABLE_STDIO
+MRB_API mrb_value
+mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
+{
+ return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c);
+}
+
+MRB_API mrb_value
+mrb_load_file(mrb_state *mrb, FILE *f)
+{
+ return mrb_load_file_cxt(mrb, f, NULL);
+}
+#endif
+
+MRB_API mrb_value
+mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
+{
+ return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
+}
+
+MRB_API mrb_value
+mrb_load_nstring(mrb_state *mrb, const char *s, size_t len)
+{
+ return mrb_load_nstring_cxt(mrb, s, len, NULL);
+}
+
+MRB_API mrb_value
+mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c)
+{
+ return mrb_load_nstring_cxt(mrb, s, strlen(s), c);
+}
+
+MRB_API mrb_value
+mrb_load_string(mrb_state *mrb, const char *s)
+{
+ return mrb_load_string_cxt(mrb, s, NULL);
+}
+
+#ifndef MRB_DISABLE_STDIO
+
+static void
+dump_prefix(node *tree, int offset)
+{
+ printf("%05d ", tree->lineno);
+ while (offset--) {
+ putc(' ', stdout);
+ putc(' ', stdout);
+ }
+}
+
+static void
+dump_recur(mrb_state *mrb, node *tree, int offset)
+{
+ while (tree) {
+ mrb_parser_dump(mrb, tree->car, offset);
+ tree = tree->cdr;
+ }
+}
+
+#endif
+
+void
+mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
+{
+#ifndef MRB_DISABLE_STDIO
+ int nodetype;
+
+ if (!tree) return;
+ again:
+ dump_prefix(tree, offset);
+ nodetype = (int)(intptr_t)tree->car;
+ tree = tree->cdr;
+ switch (nodetype) {
+ case NODE_BEGIN:
+ printf("NODE_BEGIN:\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
+ case NODE_RESCUE:
+ printf("NODE_RESCUE:\n");
+ if (tree->car) {
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ }
+ tree = tree->cdr;
+ if (tree->car) {
+ node *n2 = tree->car;
+
+ dump_prefix(n2, offset+1);
+ printf("rescue:\n");
+ while (n2) {
+ node *n3 = n2->car;
+ if (n3->car) {
+ dump_prefix(n2, offset+2);
+ printf("handle classes:\n");
+ dump_recur(mrb, n3->car, offset+3);
+ }
+ if (n3->cdr->car) {
+ dump_prefix(n3, offset+2);
+ printf("exc_var:\n");
+ mrb_parser_dump(mrb, n3->cdr->car, offset+3);
+ }
+ if (n3->cdr->cdr->car) {
+ dump_prefix(n3, offset+2);
+ printf("rescue body:\n");
+ mrb_parser_dump(mrb, n3->cdr->cdr->car, offset+3);
+ }
+ n2 = n2->cdr;
+ }
+ }
+ tree = tree->cdr;
+ if (tree->car) {
+ dump_prefix(tree, offset+1);
+ printf("else:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ }
+ break;
+
+ case NODE_ENSURE:
+ printf("NODE_ENSURE:\n");
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("ensure:\n");
+ mrb_parser_dump(mrb, tree->cdr->cdr, offset+2);
+ break;
+
+ case NODE_LAMBDA:
+ printf("NODE_BLOCK:\n");
+ goto block;
+
+ case NODE_BLOCK:
+ block:
+ printf("NODE_BLOCK:\n");
+ tree = tree->cdr;
+ if (tree->car) {
+ node *n = tree->car;
+
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(n2, offset+2);
+ printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
+ mrb_parser_dump(mrb, n2->car->cdr, 0);
+ n2 = n2->cdr;
+ }
+ }
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ if (n->cdr) {
+ dump_prefix(n, offset+1);
+ printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
+ }
+ }
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->cdr->car, offset+2);
+ break;
+
+ case NODE_IF:
+ printf("NODE_IF:\n");
+ dump_prefix(tree, offset+1);
+ printf("cond:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("then:\n");
+ mrb_parser_dump(mrb, tree->cdr->car, offset+2);
+ if (tree->cdr->cdr->car) {
+ dump_prefix(tree, offset+1);
+ printf("else:\n");
+ mrb_parser_dump(mrb, tree->cdr->cdr->car, offset+2);
+ }
+ break;
+
+ case NODE_AND:
+ printf("NODE_AND:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ mrb_parser_dump(mrb, tree->cdr, offset+1);
+ break;
+
+ case NODE_OR:
+ printf("NODE_OR:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ mrb_parser_dump(mrb, tree->cdr, offset+1);
+ break;
+
+ case NODE_CASE:
+ printf("NODE_CASE:\n");
+ if (tree->car) {
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ }
+ tree = tree->cdr;
+ while (tree) {
+ dump_prefix(tree, offset+1);
+ printf("case:\n");
+ dump_recur(mrb, tree->car->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->car->cdr, offset+2);
+ tree = tree->cdr;
+ }
+ break;
+
+ case NODE_WHILE:
+ printf("NODE_WHILE:\n");
+ dump_prefix(tree, offset+1);
+ printf("cond:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset+2);
+ break;
+
+ case NODE_UNTIL:
+ printf("NODE_UNTIL:\n");
+ dump_prefix(tree, offset+1);
+ printf("cond:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset+2);
+ break;
+
+ case NODE_FOR:
+ printf("NODE_FOR:\n");
+ dump_prefix(tree, offset+1);
+ printf("var:\n");
+ {
+ node *n2 = tree->car;
+
+ if (n2->car) {
+ dump_prefix(n2, offset+2);
+ printf("pre:\n");
+ dump_recur(mrb, n2->car, offset+3);
+ }
+ n2 = n2->cdr;
+ if (n2) {
+ if (n2->car) {
+ dump_prefix(n2, offset+2);
+ printf("rest:\n");
+ mrb_parser_dump(mrb, n2->car, offset+3);
+ }
+ n2 = n2->cdr;
+ if (n2) {
+ if (n2->car) {
+ dump_prefix(n2, offset+2);
+ printf("post:\n");
+ dump_recur(mrb, n2->car, offset+3);
+ }
+ }
+ }
+ }
+ tree = tree->cdr;
+ dump_prefix(tree, offset+1);
+ printf("in:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ tree = tree->cdr;
+ dump_prefix(tree, offset+1);
+ printf("do:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ break;
+
+ case NODE_SCOPE:
+ printf("NODE_SCOPE:\n");
+ {
+ node *n2 = tree->car;
+ mrb_bool first_lval = TRUE;
+
+ if (n2 && (n2->car || n2->cdr)) {
+ dump_prefix(n2, offset+1);
+ printf("local variables:\n");
+ dump_prefix(n2, offset+2);
+ while (n2) {
+ if (n2->car) {
+ if (!first_lval) printf(", ");
+ printf("%s", mrb_sym2name(mrb, sym(n2->car)));
+ first_lval = FALSE;
+ }
+ n2 = n2->cdr;
+ }
+ printf("\n");
+ }
+ }
+ tree = tree->cdr;
+ offset++;
+ goto again;
+
+ case NODE_FCALL:
+ case NODE_CALL:
+ case NODE_SCALL:
+ switch (nodetype) {
+ case NODE_FCALL:
+ printf("NODE_FCALL:\n"); break;
+ case NODE_CALL:
+ printf("NODE_CALL(.):\n"); break;
+ case NODE_SCALL:
+ printf("NODE_SCALL(&.):\n"); break;
+ default:
+ break;
+ }
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ dump_prefix(tree, offset+1);
+ printf("method='%s' (%d)\n",
+ mrb_sym2name(mrb, sym(tree->cdr->car)),
+ (int)(intptr_t)tree->cdr->car);
+ tree = tree->cdr->cdr->car;
+ if (tree) {
+ dump_prefix(tree, offset+1);
+ printf("args:\n");
+ dump_recur(mrb, tree->car, offset+2);
+ if (tree->cdr) {
+ dump_prefix(tree, offset+1);
+ printf("block:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset+2);
+ }
+ }
+ break;
+
+ case NODE_DOT2:
+ printf("NODE_DOT2:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ mrb_parser_dump(mrb, tree->cdr, offset+1);
+ break;
+
+ case NODE_DOT3:
+ printf("NODE_DOT3:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ mrb_parser_dump(mrb, tree->cdr, offset+1);
+ break;
+
+ case NODE_COLON2:
+ printf("NODE_COLON2:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ dump_prefix(tree, offset+1);
+ printf("::%s\n", mrb_sym2name(mrb, sym(tree->cdr)));
+ break;
+
+ case NODE_COLON3:
+ printf("NODE_COLON3: ::%s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_ARRAY:
+ printf("NODE_ARRAY:\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
+ case NODE_HASH:
+ printf("NODE_HASH:\n");
+ while (tree) {
+ dump_prefix(tree, offset+1);
+ printf("key:\n");
+ mrb_parser_dump(mrb, tree->car->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("value:\n");
+ mrb_parser_dump(mrb, tree->car->cdr, offset+2);
+ tree = tree->cdr;
+ }
+ break;
+
+ case NODE_SPLAT:
+ printf("NODE_SPLAT:\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_ASGN:
+ printf("NODE_ASGN:\n");
+ dump_prefix(tree, offset+1);
+ printf("lhs:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("rhs:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset+2);
+ break;
+
+ case NODE_MASGN:
+ printf("NODE_MASGN:\n");
+ dump_prefix(tree, offset+1);
+ printf("mlhs:\n");
+ {
+ node *n2 = tree->car;
+
+ if (n2->car) {
+ dump_prefix(tree, offset+2);
+ printf("pre:\n");
+ dump_recur(mrb, n2->car, offset+3);
+ }
+ n2 = n2->cdr;
+ if (n2) {
+ if (n2->car) {
+ dump_prefix(n2, offset+2);
+ printf("rest:\n");
+ if (n2->car == (node*)-1) {
+ dump_prefix(n2, offset+2);
+ printf("(empty)\n");
+ }
+ else {
+ mrb_parser_dump(mrb, n2->car, offset+3);
+ }
+ }
+ n2 = n2->cdr;
+ if (n2) {
+ if (n2->car) {
+ dump_prefix(n2, offset+2);
+ printf("post:\n");
+ dump_recur(mrb, n2->car, offset+3);
+ }
+ }
+ }
+ }
+ dump_prefix(tree, offset+1);
+ printf("rhs:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset+2);
+ break;
+
+ case NODE_OP_ASGN:
+ printf("NODE_OP_ASGN:\n");
+ dump_prefix(tree, offset+1);
+ printf("lhs:\n");
+ mrb_parser_dump(mrb, tree->car, offset+2);
+ tree = tree->cdr;
+ dump_prefix(tree, offset+1);
+ printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car);
+ tree = tree->cdr;
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ break;
+
+ case NODE_SUPER:
+ printf("NODE_SUPER:\n");
+ if (tree) {
+ dump_prefix(tree, offset+1);
+ printf("args:\n");
+ dump_recur(mrb, tree->car, offset+2);
+ if (tree->cdr) {
+ dump_prefix(tree, offset+1);
+ printf("block:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset+2);
+ }
+ }
+ break;
+
+ case NODE_ZSUPER:
+ printf("NODE_ZSUPER\n");
+ break;
+
+ case NODE_RETURN:
+ printf("NODE_RETURN:\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_YIELD:
+ printf("NODE_YIELD:\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
+ case NODE_BREAK:
+ printf("NODE_BREAK:\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_NEXT:
+ printf("NODE_NEXT:\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_REDO:
+ printf("NODE_REDO\n");
+ break;
+
+ case NODE_RETRY:
+ printf("NODE_RETRY\n");
+ break;
+
+ case NODE_LVAR:
+ printf("NODE_LVAR %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_GVAR:
+ printf("NODE_GVAR %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_IVAR:
+ printf("NODE_IVAR %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_CVAR:
+ printf("NODE_CVAR %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_CONST:
+ printf("NODE_CONST %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_MATCH:
+ printf("NODE_MATCH:\n");
+ dump_prefix(tree, offset + 1);
+ printf("lhs:\n");
+ mrb_parser_dump(mrb, tree->car, offset + 2);
+ dump_prefix(tree, offset + 1);
+ printf("rhs:\n");
+ mrb_parser_dump(mrb, tree->cdr, offset + 2);
+ break;
+
+ case NODE_BACK_REF:
+ printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree);
+ break;
+
+ case NODE_NTH_REF:
+ printf("NODE_NTH_REF: $%" MRB_PRId "\n", (mrb_int)(intptr_t)tree);
+ break;
+
+ case NODE_ARG:
+ printf("NODE_ARG %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
+ case NODE_BLOCK_ARG:
+ printf("NODE_BLOCK_ARG:\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_INT:
+ printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
+ break;
+
+ case NODE_FLOAT:
+ printf("NODE_FLOAT %s\n", (char*)tree);
+ break;
+
+ case NODE_NEGATE:
+ printf("NODE_NEGATE\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_STR:
+ printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
+ break;
+
+ case NODE_DSTR:
+ printf("NODE_DSTR\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
+ case NODE_XSTR:
+ printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
+ break;
+
+ case NODE_DXSTR:
+ printf("NODE_DXSTR\n");
+ dump_recur(mrb, tree, offset+1);
+ break;
+
+ case NODE_REGX:
+ printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr);
+ break;
+
+ case NODE_DREGX:
+ printf("NODE_DREGX\n");
+ dump_recur(mrb, tree->car, offset+1);
+ dump_prefix(tree, offset);
+ printf("tail: %s\n", (char*)tree->cdr->cdr->car);
+ if (tree->cdr->cdr->cdr->car) {
+ dump_prefix(tree, offset);
+ printf("opt: %s\n", (char*)tree->cdr->cdr->cdr->car);
+ }
+ if (tree->cdr->cdr->cdr->cdr) {
+ dump_prefix(tree, offset);
+ printf("enc: %s\n", (char*)tree->cdr->cdr->cdr->cdr);
+ }
+ break;
+
+ case NODE_SYM:
+ printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
+ (int)(intptr_t)tree);
+ break;
+
+ case NODE_SELF:
+ printf("NODE_SELF\n");
+ break;
+
+ case NODE_NIL:
+ printf("NODE_NIL\n");
+ break;
+
+ case NODE_TRUE:
+ printf("NODE_TRUE\n");
+ break;
+
+ case NODE_FALSE:
+ printf("NODE_FALSE\n");
+ break;
+
+ case NODE_ALIAS:
+ printf("NODE_ALIAS %s %s:\n",
+ mrb_sym2name(mrb, sym(tree->car)),
+ mrb_sym2name(mrb, sym(tree->cdr)));
+ break;
+
+ case NODE_UNDEF:
+ printf("NODE_UNDEF");
+ {
+ node *t = tree;
+ while (t) {
+ printf(" %s", mrb_sym2name(mrb, sym(t->car)));
+ t = t->cdr;
+ }
+ }
+ printf(":\n");
+ break;
+
+ case NODE_CLASS:
+ printf("NODE_CLASS:\n");
+ if (tree->car->car == (node*)0) {
+ dump_prefix(tree, offset+1);
+ printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
+ }
+ else if (tree->car->car == (node*)1) {
+ dump_prefix(tree, offset+1);
+ printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
+ }
+ else {
+ mrb_parser_dump(mrb, tree->car->car, offset+1);
+ dump_prefix(tree, offset+1);
+ printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
+ }
+ if (tree->cdr->car) {
+ dump_prefix(tree, offset+1);
+ printf("super:\n");
+ mrb_parser_dump(mrb, tree->cdr->car, offset+2);
+ }
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2);
+ break;
+
+ case NODE_MODULE:
+ printf("NODE_MODULE:\n");
+ if (tree->car->car == (node*)0) {
+ dump_prefix(tree, offset+1);
+ printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
+ }
+ else if (tree->car->car == (node*)1) {
+ dump_prefix(tree, offset+1);
+ printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
+ }
+ else {
+ mrb_parser_dump(mrb, tree->car->car, offset+1);
+ dump_prefix(tree, offset+1);
+ printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
+ }
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2);
+ break;
+
+ case NODE_SCLASS:
+ printf("NODE_SCLASS:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ dump_prefix(tree, offset+1);
+ printf("body:\n");
+ mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2);
+ break;
+
+ case NODE_DEF:
+ printf("NODE_DEF:\n");
+ dump_prefix(tree, offset+1);
+ printf("%s\n", mrb_sym2name(mrb, sym(tree->car)));
+ tree = tree->cdr;
+ {
+ node *n2 = tree->car;
+ mrb_bool first_lval = TRUE;
+
+ if (n2 && (n2->car || n2->cdr)) {
+ dump_prefix(n2, offset+1);
+ printf("local variables:\n");
+ dump_prefix(n2, offset+2);
+ while (n2) {
+ if (n2->car) {
+ if (!first_lval) printf(", ");
+ printf("%s", mrb_sym2name(mrb, sym(n2->car)));
+ first_lval = FALSE;
+ }
+ n2 = n2->cdr;
+ }
+ printf("\n");
+ }
+ }
+ tree = tree->cdr;
+ if (tree->car) {
+ node *n = tree->car;
+
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(n2, offset+2);
+ printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
+ mrb_parser_dump(mrb, n2->car->cdr, 0);
+ n2 = n2->cdr;
+ }
+ }
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ if (n->cdr) {
+ dump_prefix(n, offset+1);
+ printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
+ }
+ }
+ mrb_parser_dump(mrb, tree->cdr->car, offset+1);
+ break;
+
+ case NODE_SDEF:
+ printf("NODE_SDEF:\n");
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ tree = tree->cdr;
+ dump_prefix(tree, offset+1);
+ printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
+ tree = tree->cdr->cdr;
+ if (tree->car) {
+ node *n = tree->car;
+
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(n2, offset+2);
+ printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
+ mrb_parser_dump(mrb, n2->car->cdr, 0);
+ n2 = n2->cdr;
+ }
+ }
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ n = n->cdr;
+ if (n) {
+ dump_prefix(n, offset+1);
+ printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
+ }
+ }
+ tree = tree->cdr;
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ break;
+
+ case NODE_POSTEXE:
+ printf("NODE_POSTEXE:\n");
+ mrb_parser_dump(mrb, tree, offset+1);
+ break;
+
+ case NODE_HEREDOC:
+ printf("NODE_HEREDOC (<<%s):\n", ((parser_heredoc_info*)tree)->term);
+ dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
+ break;
+
+ default:
+ printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
+ break;
+ }
+#endif
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/mrbgem.rake
new file mode 100644
index 00000000..3bf6d6ae
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-compiler/mrbgem.rake
@@ -0,0 +1,40 @@
+MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mruby compiler library'
+
+ current_dir = spec.dir
+ current_build_dir = spec.build_dir
+
+ lex_def = "#{current_dir}/core/lex.def"
+ core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f|
+ next nil if build.cxx_exception_enabled? and f =~ /(codegen).c$/
+ objfile(f.pathmap("#{current_build_dir}/core/%n"))
+ }.compact
+
+ if build.cxx_exception_enabled?
+ core_objs <<
+ build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx",
+ objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) <<
+ build.compile_as_cxx("#{current_dir}/core/codegen.c", "#{current_build_dir}/core/codegen.cxx")
+ else
+ core_objs << objfile("#{current_build_dir}/core/y.tab")
+ file objfile("#{current_build_dir}/core/y.tab") => "#{current_build_dir}/core/y.tab.c" do |t|
+ cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
+ end
+ end
+ file objfile("#{current_build_dir}/core/y.tab") => lex_def
+
+ # Parser
+ file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t|
+ yacc.run t.name, t.prerequisites.first
+ end
+
+ # Lexical analyzer
+ file lex_def => "#{current_dir}/core/keywords" do |t|
+ gperf.run t.name, t.prerequisites.first
+ end
+
+ file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs
+ build.libmruby << core_objs
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrbgem.rake
new file mode 100644
index 00000000..d5816b80
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-enum-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Enumerable module extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb
new file mode 100644
index 00000000..7741e515
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -0,0 +1,711 @@
+##
+# Enumerable
+#
+module Enumerable
+ ##
+ # call-seq:
+ # enum.drop(n) -> array
+ #
+ # Drops first n elements from <i>enum</i>, and returns rest elements
+ # in an array.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.drop(3) #=> [4, 5, 0]
+
+ def drop(n)
+ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
+ raise ArgumentError, "attempt to drop negative size" if n < 0
+
+ n = n.to_int
+ ary = []
+ self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 }
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.drop_while {|arr| block } -> array
+ # enum.drop_while -> an_enumerator
+ #
+ # Drops elements up to, but not including, the first element for
+ # which the block returns +nil+ or +false+ and returns an array
+ # containing the remaining elements.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
+
+ def drop_while(&block)
+ return to_enum :drop_while unless block
+
+ ary, state = [], false
+ self.each do |*val|
+ state = true if !state and !block.call(*val)
+ ary << val.__svalue if state
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.take(n) -> array
+ #
+ # Returns first n elements from <i>enum</i>.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.take(3) #=> [1, 2, 3]
+
+ def take(n)
+ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
+ i = n.to_int
+ raise ArgumentError, "attempt to take negative size" if i < 0
+ ary = []
+ return ary if i == 0
+ self.each do |*val|
+ ary << val.__svalue
+ i -= 1
+ break if i == 0
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.take_while {|arr| block } -> array
+ # enum.take_while -> an_enumerator
+ #
+ # Passes elements to the block until the block returns +nil+ or +false+,
+ # then stops iterating and returns an array of all prior elements.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # a = [1, 2, 3, 4, 5, 0]
+ # a.take_while {|i| i < 3 } #=> [1, 2]
+ #
+ def take_while(&block)
+ return to_enum :take_while unless block
+
+ ary = []
+ self.each do |*val|
+ return ary unless block.call(*val)
+ ary << val.__svalue
+ end
+ ary
+ end
+
+ ##
+ # Iterates the given block for each array of consecutive <n>
+ # elements.
+ #
+ # @return [nil]
+ #
+ # @example
+ # (1..10).each_cons(3) {|a| p a}
+ # # outputs below
+ # [1, 2, 3]
+ # [2, 3, 4]
+ # [3, 4, 5]
+ # [4, 5, 6]
+ # [5, 6, 7]
+ # [6, 7, 8]
+ # [7, 8, 9]
+ # [8, 9, 10]
+
+ def each_cons(n, &block)
+ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
+ raise ArgumentError, "invalid size" if n <= 0
+
+ return to_enum(:each_cons,n) unless block
+ ary = []
+ n = n.to_int
+ self.each do |*val|
+ ary.shift if ary.size == n
+ ary << val.__svalue
+ block.call(ary.dup) if ary.size == n
+ end
+ nil
+ end
+
+ ##
+ # Iterates the given block for each slice of <n> elements.
+ #
+ # @return [nil]
+ #
+ # @example
+ # (1..10).each_slice(3) {|a| p a}
+ # # outputs below
+ # [1, 2, 3]
+ # [4, 5, 6]
+ # [7, 8, 9]
+ # [10]
+
+ def each_slice(n, &block)
+ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
+ raise ArgumentError, "invalid slice size" if n <= 0
+
+ return to_enum(:each_slice,n) unless block
+ ary = []
+ n = n.to_int
+ self.each do |*val|
+ ary << val.__svalue
+ if ary.size == n
+ block.call(ary)
+ ary = []
+ end
+ end
+ block.call(ary) unless ary.empty?
+ nil
+ end
+
+ ##
+ # call-seq:
+ # enum.group_by {| obj | block } -> a_hash
+ # enum.group_by -> an_enumerator
+ #
+ # Returns a hash, which keys are evaluated result from the
+ # block, and values are arrays of elements in <i>enum</i>
+ # corresponding to the key.
+ #
+ # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+ #
+ def group_by(&block)
+ return to_enum :group_by unless block
+
+ h = {}
+ self.each do |*val|
+ key = block.call(*val)
+ sv = val.__svalue
+ h.key?(key) ? (h[key] << sv) : (h[key] = [sv])
+ end
+ h
+ end
+
+ ##
+ # call-seq:
+ # enum.sort_by { |obj| block } -> array
+ # enum.sort_by -> an_enumerator
+ #
+ # Sorts <i>enum</i> using a set of keys generated by mapping the
+ # values in <i>enum</i> through the given block.
+ #
+ # If no block is given, an enumerator is returned instead.
+
+ def sort_by(&block)
+ return to_enum :sort_by unless block
+
+ ary = []
+ orig = []
+ self.each_with_index{|e, i|
+ orig.push(e)
+ ary.push([block.call(e), i])
+ }
+ if ary.size > 1
+ __sort_sub__(ary, 0, ary.size - 1) do |a,b|
+ a <=> b
+ end
+ end
+ ary.collect{|e,i| orig[i]}
+ end
+
+ NONE = Object.new
+ ##
+ # call-seq:
+ # enum.first -> obj or nil
+ # enum.first(n) -> an_array
+ #
+ # Returns the first element, or the first +n+ elements, of the enumerable.
+ # If the enumerable is empty, the first form returns <code>nil</code>, and the
+ # second form returns an empty array.
+ def first(*args)
+ case args.length
+ when 0
+ self.each do |*val|
+ return val.__svalue
+ end
+ return nil
+ when 1
+ n = args[0]
+ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
+ i = n.to_int
+ raise ArgumentError, "attempt to take negative size" if i < 0
+ ary = []
+ return ary if i == 0
+ self.each do |*val|
+ ary << val.__svalue
+ i -= 1
+ break if i == 0
+ end
+ ary
+ else
+ raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 0..1)"
+ end
+ end
+
+ ##
+ # call-seq:
+ # enum.count -> int
+ # enum.count(item) -> int
+ # enum.count { |obj| block } -> int
+ #
+ # Returns the number of items in +enum+ through enumeration.
+ # If an argument is given, the number of items in +enum+ that
+ # are equal to +item+ are counted. If a block is given, it
+ # counts the number of elements yielding a true value.
+ def count(v=NONE, &block)
+ count = 0
+ if block
+ self.each do |*val|
+ count += 1 if block.call(*val)
+ end
+ else
+ if v == NONE
+ self.each { count += 1 }
+ else
+ self.each do |*val|
+ count += 1 if val.__svalue == v
+ end
+ end
+ end
+ count
+ end
+
+ ##
+ # call-seq:
+ # enum.flat_map { |obj| block } -> array
+ # enum.collect_concat { |obj| block } -> array
+ # enum.flat_map -> an_enumerator
+ # enum.collect_concat -> an_enumerator
+ #
+ # Returns a new array with the concatenated results of running
+ # <em>block</em> once for every element in <i>enum</i>.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # [1, 2, 3, 4].flat_map { |e| [e, -e] } #=> [1, -1, 2, -2, 3, -3, 4, -4]
+ # [[1, 2], [3, 4]].flat_map { |e| e + [100] } #=> [1, 2, 100, 3, 4, 100]
+ def flat_map(&block)
+ return to_enum :flat_map unless block
+
+ ary = []
+ self.each do |*e|
+ e2 = block.call(*e)
+ if e2.respond_to? :each
+ e2.each {|e3| ary.push(e3) }
+ else
+ ary.push(e2)
+ end
+ end
+ ary
+ end
+ alias collect_concat flat_map
+
+ ##
+ # call-seq:
+ # enum.max_by {|obj| block } -> obj
+ # enum.max_by -> an_enumerator
+ #
+ # Returns the object in <i>enum</i> that gives the maximum
+ # value from the given block.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # %w[albatross dog horse].max_by {|x| x.length } #=> "albatross"
+
+ def max_by(&block)
+ return to_enum :max_by unless block
+
+ first = true
+ max = nil
+ max_cmp = nil
+
+ self.each do |*val|
+ if first
+ max = val.__svalue
+ max_cmp = block.call(*val)
+ first = false
+ else
+ if (cmp = block.call(*val)) > max_cmp
+ max = val.__svalue
+ max_cmp = cmp
+ end
+ end
+ end
+ max
+ end
+
+ ##
+ # call-seq:
+ # enum.min_by {|obj| block } -> obj
+ # enum.min_by -> an_enumerator
+ #
+ # Returns the object in <i>enum</i> that gives the minimum
+ # value from the given block.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # %w[albatross dog horse].min_by {|x| x.length } #=> "dog"
+
+ def min_by(&block)
+ return to_enum :min_by unless block
+
+ first = true
+ min = nil
+ min_cmp = nil
+
+ self.each do |*val|
+ if first
+ min = val.__svalue
+ min_cmp = block.call(*val)
+ first = false
+ else
+ if (cmp = block.call(*val)) < min_cmp
+ min = val.__svalue
+ min_cmp = cmp
+ end
+ end
+ end
+ min
+ end
+
+ ##
+ # call-seq:
+ # enum.minmax -> [min, max]
+ # enum.minmax { |a, b| block } -> [min, max]
+ #
+ # Returns two elements array which contains the minimum and the
+ # maximum value in the enumerable. The first form assumes all
+ # objects implement <code>Comparable</code>; the second uses the
+ # block to return <em>a <=> b</em>.
+ #
+ # a = %w(albatross dog horse)
+ # a.minmax #=> ["albatross", "horse"]
+ # a.minmax { |a, b| a.length <=> b.length } #=> ["dog", "albatross"]
+
+ def minmax(&block)
+ max = nil
+ min = nil
+ first = true
+
+ self.each do |*val|
+ if first
+ val = val.__svalue
+ max = val
+ min = val
+ first = false
+ else
+ val = val.__svalue
+ if block
+ max = val if block.call(val, max) > 0
+ min = val if block.call(val, min) < 0
+ else
+ max = val if (val <=> max) > 0
+ min = val if (val <=> min) < 0
+ end
+ end
+ end
+ [min, max]
+ end
+
+ ##
+ # call-seq:
+ # enum.minmax_by { |obj| block } -> [min, max]
+ # enum.minmax_by -> an_enumerator
+ #
+ # Returns a two element array containing the objects in
+ # <i>enum</i> that correspond to the minimum and maximum values respectively
+ # from the given block.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # %w(albatross dog horse).minmax_by { |x| x.length } #=> ["dog", "albatross"]
+
+ def minmax_by(&block)
+ return to_enum :minmax_by unless block
+
+ max = nil
+ max_cmp = nil
+ min = nil
+ min_cmp = nil
+ first = true
+
+ self.each do |*val|
+ if first
+ max = min = val.__svalue
+ max_cmp = min_cmp = block.call(*val)
+ first = false
+ else
+ if (cmp = block.call(*val)) > max_cmp
+ max = val.__svalue
+ max_cmp = cmp
+ end
+ if (cmp = block.call(*val)) < min_cmp
+ min = val.__svalue
+ min_cmp = cmp
+ end
+ end
+ end
+ [min, max]
+ end
+
+ ##
+ # call-seq:
+ # enum.none? [{ |obj| block }] -> true or false
+ #
+ # Passes each element of the collection to the given block. The method
+ # returns <code>true</code> if the block never returns <code>true</code>
+ # for all elements. If the block is not given, <code>none?</code> will return
+ # <code>true</code> only if none of the collection members is true.
+ #
+ # %w(ant bear cat).none? { |word| word.length == 5 } #=> true
+ # %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
+ # [].none? #=> true
+ # [nil, false].none? #=> true
+ # [nil, true].none? #=> false
+
+ def none?(&block)
+ if block
+ self.each do |*val|
+ return false if block.call(*val)
+ end
+ else
+ self.each do |*val|
+ return false if val.__svalue
+ end
+ end
+ true
+ end
+
+ ##
+ # call-seq:
+ # enum.one? [{ |obj| block }] -> true or false
+ #
+ # Passes each element of the collection to the given block. The method
+ # returns <code>true</code> if the block returns <code>true</code>
+ # exactly once. If the block is not given, <code>one?</code> will return
+ # <code>true</code> only if exactly one of the collection members is
+ # true.
+ #
+ # %w(ant bear cat).one? { |word| word.length == 4 } #=> true
+ # %w(ant bear cat).one? { |word| word.length > 4 } #=> false
+ # %w(ant bear cat).one? { |word| word.length < 4 } #=> false
+ # [nil, true, 99].one? #=> false
+ # [nil, true, false].one? #=> true
+ #
+
+ def one?(&block)
+ count = 0
+ if block
+ self.each do |*val|
+ count += 1 if block.call(*val)
+ return false if count > 1
+ end
+ else
+ self.each do |*val|
+ count += 1 if val.__svalue
+ return false if count > 1
+ end
+ end
+
+ count == 1 ? true : false
+ end
+
+ ##
+ # call-seq:
+ # enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
+ # enum.each_with_object(obj) -> an_enumerator
+ #
+ # Iterates the given block for each element with an arbitrary
+ # object given, and returns the initially given object.
+ #
+ # If no block is given, returns an enumerator.
+ #
+ # (1..10).each_with_object([]) { |i, a| a << i*2 }
+ # #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
+ #
+
+ def each_with_object(obj=nil, &block)
+ raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil?
+
+ return to_enum(:each_with_object, obj) unless block
+
+ self.each {|*val| block.call(val.__svalue, obj) }
+ obj
+ end
+
+ ##
+ # call-seq:
+ # enum.reverse_each { |item| block } -> enum
+ # enum.reverse_each -> an_enumerator
+ #
+ # Builds a temporary array and traverses that array in reverse order.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # (1..3).reverse_each { |v| p v }
+ #
+ # produces:
+ #
+ # 3
+ # 2
+ # 1
+ #
+
+ def reverse_each(&block)
+ return to_enum :reverse_each unless block
+
+ ary = self.to_a
+ i = ary.size - 1
+ while i>=0
+ block.call(ary[i])
+ i -= 1
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # enum.cycle(n=nil) { |obj| block } -> nil
+ # enum.cycle(n=nil) -> an_enumerator
+ #
+ # Calls <i>block</i> for each element of <i>enum</i> repeatedly _n_
+ # times or forever if none or +nil+ is given. If a non-positive
+ # number is given or the collection is empty, does nothing. Returns
+ # +nil+ if the loop has finished without getting interrupted.
+ #
+ # Enumerable#cycle saves elements in an internal array so changes
+ # to <i>enum</i> after the first pass have no effect.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # a = ["a", "b", "c"]
+ # a.cycle { |x| puts x } # print, a, b, c, a, b, c,.. forever.
+ # a.cycle(2) { |x| puts x } # print, a, b, c, a, b, c.
+ #
+
+ def cycle(nv = nil, &block)
+ return to_enum(:cycle, nv) unless block
+
+ n = nil
+
+ if nv.nil?
+ n = -1
+ else
+ unless nv.respond_to?(:to_int)
+ raise TypeError, "no implicit conversion of #{nv.class} into Integer"
+ end
+ n = nv.to_int
+ unless n.kind_of?(Integer)
+ raise TypeError, "no implicit conversion of #{nv.class} into Integer"
+ end
+ return nil if n <= 0
+ end
+
+ ary = []
+ each do |*i|
+ ary.push(i)
+ yield(*i)
+ end
+ return nil if ary.empty?
+
+ while n < 0 || 0 < (n -= 1)
+ ary.each do |i|
+ yield(*i)
+ end
+ end
+
+ nil
+ end
+
+ ##
+ # call-seq:
+ # enum.find_index(value) -> int or nil
+ # enum.find_index { |obj| block } -> int or nil
+ # enum.find_index -> an_enumerator
+ #
+ # Compares each entry in <i>enum</i> with <em>value</em> or passes
+ # to <em>block</em>. Returns the index for the first for which the
+ # evaluated value is non-false. If no object matches, returns
+ # <code>nil</code>
+ #
+ # If neither block nor argument is given, an enumerator is returned instead.
+ #
+ # (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> nil
+ # (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 } #=> 34
+ # (1..100).find_index(50) #=> 49
+ #
+
+ def find_index(val=NONE, &block)
+ return to_enum(:find_index, val) if !block && val == NONE
+
+ idx = 0
+ if block
+ self.each do |*e|
+ return idx if block.call(*e)
+ idx += 1
+ end
+ else
+ self.each do |*e|
+ return idx if e.__svalue == val
+ idx += 1
+ end
+ end
+ nil
+ end
+
+ ##
+ # call-seq:
+ # enum.zip(arg, ...) -> an_array_of_array
+ #
+ # Takes one element from <i>enum</i> and merges corresponding
+ # elements from each <i>args</i>. This generates a sequence of
+ # <em>n</em>-element arrays, where <em>n</em> is one more than the
+ # count of arguments. The length of the resulting sequence will be
+ # <code>enum#size</code>. If the size of any argument is less than
+ # <code>enum#size</code>, <code>nil</code> values are supplied.
+ #
+
+ def zip(*arg)
+ ary = []
+ arg = arg.map{|a|a.to_a}
+ i = 0
+ self.each do |*val|
+ a = []
+ a.push(val.__svalue)
+ idx = 0
+ while idx < arg.size
+ a.push(arg[idx][i])
+ idx += 1
+ end
+ ary.push(a)
+ i += 1
+ end
+ ary
+ end
+
+ ##
+ # call-seq:
+ # enum.to_h -> hash
+ #
+ # Returns the result of interpreting <i>enum</i> as a list of
+ # <tt>[key, value]</tt> pairs.
+ #
+ # %i[hello world].each_with_index.to_h
+ # # => {:hello => 0, :world => 1}
+ #
+
+ def to_h
+ h = {}
+ self.each do |*v|
+ v = v.__svalue
+ raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
+ raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
+ h[v[0]] = v[1]
+ end
+ h
+ end
+
+ def nil.to_h
+ {}
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/test/enum.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/test/enum.rb
new file mode 100644
index 00000000..e772f85b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-ext/test/enum.rb
@@ -0,0 +1,171 @@
+##
+# Enumerable(Ext) Test
+
+assert("Enumerable#drop") do
+ a = [1, 2, 3, 4, 5, 0]
+
+ assert_equal [4, 5, 0], a.drop(3)
+ assert_equal [], a.drop(6)
+end
+
+assert("Enumerable#drop_while") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal [3, 4, 5, 0], a.drop_while {|i| i < 3 }
+end
+
+assert("Enumerable#take") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal [1, 2, 3], a.take(3)
+end
+
+assert("Enumerable#take_while") do
+ a = [1, 2, 3, 4, 5, 0]
+ assert_equal [1, 2], a.take_while {|i| i < 3}
+end
+
+assert("Enumerable#each_cons") do
+ a = []
+ b = (1..5).each_cons(3){|e| a << e}
+ assert_equal [[1, 2, 3], [2, 3, 4], [3, 4, 5]], a
+ assert_equal nil, b
+end
+
+assert("Enumerable#each_slice") do
+ a = []
+ b = (1..10).each_slice(3){|e| a << e}
+ assert_equal [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]], a
+ assert_equal nil, b
+end
+
+assert("Enumerable#group_by") do
+ r = (1..6).group_by {|i| i % 3 }
+ assert_equal [3, 6], r[0]
+ assert_equal [1, 4], r[1]
+ assert_equal [2, 5], r[2]
+end
+
+assert("Enumerable#sort_by") do
+ assert_equal ["car", "train", "bicycle"], %w{car bicycle train}.sort_by {|e| e.length}
+end
+
+assert("Enumerable#first") do
+ a = Object.new
+ a.extend Enumerable
+ def a.each
+ yield 1
+ yield 2
+ yield 3
+ end
+ assert_equal 1, a.first
+ assert_equal [1, 2], a.first(2)
+ assert_equal [1, 2, 3], a.first(10)
+ a = Object.new
+ a.extend Enumerable
+ def a.each
+ end
+ assert_nil a.first
+end
+
+assert("Enumerable#count") do
+ a = [1, 2, 4, 2]
+ assert_equal 4, a.count
+ assert_equal 2, a.count(2)
+ assert_equal 3, a.count{|x| x % 2 == 0}
+end
+
+assert("Enumerable#flat_map") do
+ assert_equal [1, 2, 3, 4], [1, 2, 3, 4].flat_map { |e| e }
+ assert_equal [1, -1, 2, -2, 3, -3, 4, -4], [1, 2, 3, 4].flat_map { |e| [e, -e] }
+ assert_equal [1, 2, 100, 3, 4, 100], [[1, 2], [3, 4]].flat_map { |e| e + [100] }
+end
+
+assert("Enumerable#max_by") do
+ assert_equal "albatross", %w[albatross dog horse].max_by { |x| x.length }
+end
+
+assert("Enumerable#min_by") do
+ assert_equal "dog", %w[albatross dog horse].min_by { |x| x.length }
+end
+
+assert("Enumerable#minmax") do
+ a = %w(albatross dog horse)
+ assert_equal ["albatross", "horse"], a.minmax
+ assert_equal ["dog", "albatross"], a.minmax { |a, b| a.length <=> b.length }
+end
+
+assert("Enumerable#minmax_by") do
+ assert_equal ["dog", "albatross"], %w(albatross dog horse).minmax_by { |x| x.length }
+end
+
+assert("Enumerable#none?") do
+ assert_true %w(ant bear cat).none? { |word| word.length == 5 }
+ assert_false %w(ant bear cat).none? { |word| word.length >= 4 }
+ assert_true [].none?
+ assert_true [nil, false].none?
+ assert_false [nil, true].none?
+end
+
+assert("Enumerable#one?") do
+ assert_true %w(ant bear cat).one? { |word| word.length == 4 }
+ assert_false %w(ant bear cat).one? { |word| word.length > 4 }
+ assert_false %w(ant bear cat).one? { |word| word.length < 4 }
+ assert_false [nil, true, 99].one?
+ assert_true [nil, true, false].one?
+end
+
+assert("Enumerable#each_with_object") do
+ assert_true [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], (1..10).each_with_object([]) { |i, a| a << i*2 }
+ assert_raise(ArgumentError) { (1..10).each_with_object() { |i, a| a << i*2 } }
+end
+
+assert("Enumerable#reverse_each") do
+ r = (1..3)
+ a = []
+ assert_equal (1..3), r.reverse_each { |v| a << v }
+ assert_equal [3, 2, 1], a
+end
+
+assert("Enumerable#cycle") do
+ a = []
+ ["a", "b", "c"].cycle(2) { |v| a << v }
+ assert_equal ["a", "b", "c", "a", "b", "c"], a
+ assert_raise(TypeError) { ["a", "b", "c"].cycle("a") { |v| a << v } }
+
+ empty = Class.new do
+ include Enumerable
+ def each
+ end
+ end
+ assert_nil empty.new.cycle { break :nope }
+end
+
+assert("Enumerable#find_index") do
+ assert_nil (1..10).find_index { |i| i % 5 == 0 and i % 7 == 0 }
+ assert_equal 34, (1..100).find_index { |i| i % 5 == 0 and i % 7 == 0 }
+ assert_equal 49 ,(1..100).find_index(50)
+end
+
+assert("Enumerable#zip") do
+ a = [ 4, 5, 6 ]
+ b = [ 7, 8, 9 ]
+ assert_equal [[4, 7], [5, 8], [6, 9]], a.zip(b)
+ assert_equal [[1, 4, 7], [2, 5, 8], [3, 6, 9]], [1, 2, 3].zip(a, b)
+ assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b)
+ assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8])
+end
+
+assert("Enumerable#to_h") do
+ c = Class.new {
+ include Enumerable
+ def each
+ yield [1,2]
+ yield [3,4]
+ end
+ }
+ h0 = {1=>2, 3=>4}
+ h = c.new.to_h
+ assert_equal Hash, h.class
+ assert_equal h0, h
+ # mruby-enum-ext also provides nil.to_h
+ assert_equal Hash.new, nil.to_h
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake
new file mode 100644
index 00000000..682134c4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake
@@ -0,0 +1,7 @@
+MRuby::Gem::Specification.new('mruby-enum-lazy') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Enumerator::Lazy class'
+ spec.add_dependency('mruby-enumerator', :core => 'mruby-enumerator')
+ spec.add_dependency('mruby-enum-ext', :core => 'mruby-enum-ext')
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb
new file mode 100644
index 00000000..c98681ed
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb
@@ -0,0 +1,163 @@
+module Enumerable
+
+ # = Enumerable#lazy implementation
+ #
+ # Enumerable#lazy returns an instance of Enumerator::Lazy.
+ # You can use it just like as normal Enumerable object,
+ # except these methods act as 'lazy':
+ #
+ # - map collect
+ # - select find_all
+ # - reject
+ # - grep
+ # - drop
+ # - drop_while
+ # - take_while
+ # - flat_map collect_concat
+ # - zip
+ def lazy
+ Enumerator::Lazy.new(self)
+ end
+end
+
+class Enumerator
+ # == Acknowledgements
+ #
+ # Based on https://github.com/yhara/enumerable-lazy
+ # Inspired by https://github.com/antimon2/enumerable_lz
+ # http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja)
+ class Lazy < Enumerator
+ def initialize(obj, &block)
+ super(){|yielder|
+ begin
+ obj.each{|x|
+ if block
+ block.call(yielder, x)
+ else
+ yielder << x
+ end
+ }
+ rescue StopIteration
+ end
+ }
+ end
+
+ def to_enum(meth=:each, *args, &block)
+ unless self.respond_to?(meth)
+ raise NoMethodError, "undefined method #{meth}"
+ end
+ lz = Lazy.new(self, &block)
+ lz.obj = self
+ lz.meth = meth
+ lz.args = args
+ lz
+ end
+ alias enum_for to_enum
+
+ def map(&block)
+ Lazy.new(self){|yielder, val|
+ yielder << block.call(val)
+ }
+ end
+ alias collect map
+
+ def select(&block)
+ Lazy.new(self){|yielder, val|
+ if block.call(val)
+ yielder << val
+ end
+ }
+ end
+ alias find_all select
+
+ def reject(&block)
+ Lazy.new(self){|yielder, val|
+ unless block.call(val)
+ yielder << val
+ end
+ }
+ end
+
+ def grep(pattern)
+ Lazy.new(self){|yielder, val|
+ if pattern === val
+ yielder << val
+ end
+ }
+ end
+
+ def drop(n)
+ dropped = 0
+ Lazy.new(self){|yielder, val|
+ if dropped < n
+ dropped += 1
+ else
+ yielder << val
+ end
+ }
+ end
+
+ def drop_while(&block)
+ dropping = true
+ Lazy.new(self){|yielder, val|
+ if dropping
+ if not block.call(val)
+ yielder << val
+ dropping = false
+ end
+ else
+ yielder << val
+ end
+ }
+ end
+
+ def take(n)
+ if n == 0
+ return Lazy.new(self){raise StopIteration}
+ end
+ taken = 0
+ Lazy.new(self){|yielder, val|
+ yielder << val
+ taken += 1
+ if taken >= n
+ raise StopIteration
+ end
+ }
+ end
+
+ def take_while(&block)
+ Lazy.new(self){|yielder, val|
+ if block.call(val)
+ yielder << val
+ else
+ raise StopIteration
+ end
+ }
+ end
+
+ def flat_map(&block)
+ Lazy.new(self){|yielder, val|
+ ary = block.call(val)
+ # TODO: check ary is an Array
+ ary.each{|x|
+ yielder << x
+ }
+ }
+ end
+ alias collect_concat flat_map
+
+ def zip(*args, &block)
+ enums = [self] + args
+ Lazy.new(self){|yielder, val|
+ ary = enums.map{|e| e.next}
+ if block
+ yielder << block.call(ary)
+ else
+ yielder << ary
+ end
+ }
+ end
+
+ alias force to_a
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb
new file mode 100644
index 00000000..940d070e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb
@@ -0,0 +1,53 @@
+assert("Enumerator::Lazy") do
+ a = [1, 2]
+ assert_equal Enumerator::Lazy, a.lazy.class
+end
+
+assert("Enumerator::Lazy laziness") do
+ a = Object.new
+ def a.each
+ return to_enum :each unless block_given?
+ self.b << 10
+ yield 1
+ self.b << 20
+ yield 2
+ self.b << 30
+ yield 3
+ self.b << 40
+ yield 4
+ self.b << 50
+ yield 5
+ end
+ def a.b(b=nil)
+ @b = b if b
+ @b
+ end
+
+ a.b([])
+ assert_equal [1,2], a.each.lazy.take(2).force
+ assert_equal [10,20], a.b
+
+ a.b([])
+ assert_equal [2,4], a.each.lazy.select{|x|x%2==0}.take(2).force
+ assert_equal [10,20,30,40], a.b
+
+ a.b([])
+ assert_equal [1], a.each.lazy.take_while{|x|x<2}.take(1).force
+ assert_equal [10], a.b
+
+ a.b([])
+ assert_equal [1], a.each.lazy.take_while{|x|x<2}.take(4).force
+ assert_equal [10,20], a.b
+end
+
+assert("Enumrator::Lazy#to_enum") do
+ lazy_enum = (0..Float::INFINITY).lazy.to_enum(:each_slice, 2)
+ assert_kind_of Enumerator::Lazy, lazy_enum
+ assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4)
+end
+
+assert("Enumerator::Lazy#zip with cycle") do
+ e1 = [1, 2, 3].cycle
+ e2 = [:a, :b].cycle
+ assert_equal [[1,:a],[2,:b],[3,:a]], e1.lazy.zip(e2).first(3)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrbgem.rake
new file mode 100644
index 00000000..8757a15e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrbgem.rake
@@ -0,0 +1,7 @@
+MRuby::Gem::Specification.new('mruby-enumerator') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.add_dependency('mruby-fiber', :core => 'mruby-fiber')
+ spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
+ spec.summary = 'Enumerator class'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb
new file mode 100644
index 00000000..1e77af36
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb
@@ -0,0 +1,645 @@
+##
+# enumerator.rb Enumerator class
+# See Copyright Notice in mruby.h
+
+##
+# A class which allows both internal and external iteration.
+#
+# An Enumerator can be created by the following methods.
+# - {Kernel#to_enum}
+# - {Kernel#enum_for}
+# - {Enumerator#initialize Enumerator.new}
+#
+# Most methods have two forms: a block form where the contents
+# are evaluated for each item in the enumeration, and a non-block form
+# which returns a new Enumerator wrapping the iteration.
+#
+# enumerator = %w(one two three).each
+# puts enumerator.class # => Enumerator
+#
+# enumerator.each_with_object("foo") do |item, obj|
+# puts "#{obj}: #{item}"
+# end
+#
+# # foo: one
+# # foo: two
+# # foo: three
+#
+# enum_with_obj = enumerator.each_with_object("foo")
+# puts enum_with_obj.class # => Enumerator
+#
+# enum_with_obj.each do |item, obj|
+# puts "#{obj}: #{item}"
+# end
+#
+# # foo: one
+# # foo: two
+# # foo: three
+#
+# This allows you to chain Enumerators together. For example, you
+# can map a list's elements to strings containing the index
+# and the element as a string via:
+#
+# puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
+# # => ["0:foo", "1:bar", "2:baz"]
+#
+# An Enumerator can also be used as an external iterator.
+# For example, Enumerator#next returns the next value of the iterator
+# or raises StopIteration if the Enumerator is at the end.
+#
+# e = [1,2,3].each # returns an enumerator object.
+# puts e.next # => 1
+# puts e.next # => 2
+# puts e.next # => 3
+# puts e.next # raises StopIteration
+#
+# You can use this to implement an internal iterator as follows:
+#
+# def ext_each(e)
+# while true
+# begin
+# vs = e.next_values
+# rescue StopIteration
+# return $!.result
+# end
+# y = yield(*vs)
+# e.feed y
+# end
+# end
+#
+# o = Object.new
+#
+# def o.each
+# puts yield
+# puts yield(1)
+# puts yield(1, 2)
+# 3
+# end
+#
+# # use o.each as an internal iterator directly.
+# puts o.each {|*x| puts x; [:b, *x] }
+# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
+#
+# # convert o.each to an external iterator for
+# # implementing an internal iterator.
+# puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
+# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3
+#
+class Enumerator
+ include Enumerable
+
+ ##
+ # @overload initialize(size = nil, &block)
+ # @overload initialize(obj, method = :each, *args)
+ #
+ # Creates a new Enumerator object, which can be used as an
+ # Enumerable.
+ #
+ # In the first form, iteration is defined by the given block, in
+ # which a "yielder" object, given as block parameter, can be used to
+ # yield a value by calling the +yield+ method (aliased as +<<+):
+ #
+ # fib = Enumerator.new do |y|
+ # a = b = 1
+ # loop do
+ # y << a
+ # a, b = b, a + b
+ # end
+ # end
+ #
+ # p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
+ #
+ def initialize(obj=nil, meth=:each, *args, &block)
+ if block
+ obj = Generator.new(&block)
+ else
+ raise ArgumentError unless obj
+ end
+ if @obj and !self.respond_to?(meth)
+ raise NoMethodError, "undefined method #{meth}"
+ end
+
+ @obj = obj
+ @meth = meth
+ @args = args.dup
+ @fib = nil
+ @dst = nil
+ @lookahead = nil
+ @feedvalue = nil
+ @stop_exc = false
+ end
+ attr_accessor :obj, :meth, :args, :fib
+ private :obj, :meth, :args, :fib
+
+ def initialize_copy(obj)
+ raise TypeError, "can't copy type #{obj.class}" unless obj.kind_of? Enumerator
+ raise TypeError, "can't copy execution context" if obj.fib
+ @obj = obj.obj
+ @meth = obj.meth
+ @args = obj.args
+ @fib = nil
+ @lookahead = nil
+ @feedvalue = nil
+ self
+ end
+
+ ##
+ # call-seq:
+ # e.with_index(offset = 0) {|(*args), idx| ... }
+ # e.with_index(offset = 0)
+ #
+ # Iterates the given block for each element with an index, which
+ # starts from +offset+. If no block is given, returns a new Enumerator
+ # that includes the index, starting from +offset+
+ #
+ # +offset+:: the starting index to use
+ #
+ def with_index(offset=0, &block)
+ return to_enum :with_index, offset unless block
+
+ offset = if offset.nil?
+ 0
+ elsif offset.respond_to?(:to_int)
+ offset.to_int
+ else
+ raise TypeError, "no implicit conversion of #{offset.class} into Integer"
+ end
+
+ n = offset - 1
+ enumerator_block_call do |*i|
+ n += 1
+ block.call i.__svalue, n
+ end
+ end
+
+ ##
+ # call-seq:
+ # e.each_with_index {|(*args), idx| ... }
+ # e.each_with_index
+ #
+ # Same as Enumerator#with_index(0), i.e. there is no starting offset.
+ #
+ # If no block is given, a new Enumerator is returned that includes the index.
+ #
+ def each_with_index(&block)
+ with_index(0, &block)
+ end
+
+ ##
+ # call-seq:
+ # e.each_with_object(obj) {|(*args), obj| ... }
+ # e.each_with_object(obj)
+ # e.with_object(obj) {|(*args), obj| ... }
+ # e.with_object(obj)
+ #
+ # Iterates the given block for each element with an arbitrary object, +obj+,
+ # and returns +obj+
+ #
+ # If no block is given, returns a new Enumerator.
+ #
+ # @example
+ # to_three = Enumerator.new do |y|
+ # 3.times do |x|
+ # y << x
+ # end
+ # end
+ #
+ # to_three_with_string = to_three.with_object("foo")
+ # to_three_with_string.each do |x,string|
+ # puts "#{string}: #{x}"
+ # end
+ #
+ # # => foo:0
+ # # => foo:1
+ # # => foo:2
+ #
+ def with_object(object, &block)
+ return to_enum(:with_object, object) unless block
+
+ enumerator_block_call do |i|
+ block.call [i,object]
+ end
+ object
+ end
+
+ def inspect
+ return "#<#{self.class}: uninitialized>" unless @obj
+
+ if @args && @args.size > 0
+ args = @args.join(", ")
+ "#<#{self.class}: #{@obj}:#{@meth}(#{args})>"
+ else
+ "#<#{self.class}: #{@obj}:#{@meth}>"
+ end
+ end
+
+ ##
+ # call-seq:
+ # enum.each { |elm| block } -> obj
+ # enum.each -> enum
+ # enum.each(*appending_args) { |elm| block } -> obj
+ # enum.each(*appending_args) -> an_enumerator
+ #
+ # Iterates over the block according to how this Enumerator was constructed.
+ # If no block and no arguments are given, returns self.
+ #
+ # === Examples
+ #
+ # "Hello, world!".scan(/\w+/) #=> ["Hello", "world"]
+ # "Hello, world!".to_enum(:scan, /\w+/).to_a #=> ["Hello", "world"]
+ # "Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"]
+ #
+ # obj = Object.new
+ #
+ # def obj.each_arg(a, b=:b, *rest)
+ # yield a
+ # yield b
+ # yield rest
+ # :method_returned
+ # end
+ #
+ # enum = obj.to_enum :each_arg, :a, :x
+ #
+ # enum.each.to_a #=> [:a, :x, []]
+ # enum.each.equal?(enum) #=> true
+ # enum.each { |elm| elm } #=> :method_returned
+ #
+ # enum.each(:y, :z).to_a #=> [:a, :x, [:y, :z]]
+ # enum.each(:y, :z).equal?(enum) #=> false
+ # enum.each(:y, :z) { |elm| elm } #=> :method_returned
+ #
+ def each(*argv, &block)
+ obj = self
+ if 0 < argv.length
+ obj = self.dup
+ args = obj.args
+ if !args.empty?
+ args = args.dup
+ args.concat argv
+ else
+ args = argv.dup
+ end
+ obj.args = args
+ end
+ return obj unless block
+ enumerator_block_call(&block)
+ end
+
+ def enumerator_block_call(&block)
+ @obj.__send__ @meth, *@args, &block
+ end
+ private :enumerator_block_call
+
+ ##
+ # call-seq:
+ # e.next -> object
+ #
+ # Returns the next object in the enumerator, and move the internal position
+ # forward. When the position reached at the end, StopIteration is raised.
+ #
+ # === Example
+ #
+ # a = [1,2,3]
+ # e = a.to_enum
+ # p e.next #=> 1
+ # p e.next #=> 2
+ # p e.next #=> 3
+ # p e.next #raises StopIteration
+ #
+ # Note that enumeration sequence by +next+ does not affect other non-external
+ # enumeration methods, unless the underlying iteration methods itself has
+ # side-effect
+ #
+ def next
+ next_values.__svalue
+ end
+
+ ##
+ # call-seq:
+ # e.next_values -> array
+ #
+ # Returns the next object as an array in the enumerator, and move the
+ # internal position forward. When the position reached at the end,
+ # StopIteration is raised.
+ #
+ # This method can be used to distinguish <code>yield</code> and <code>yield
+ # nil</code>.
+ #
+ # === Example
+ #
+ # o = Object.new
+ # def o.each
+ # yield
+ # yield 1
+ # yield 1, 2
+ # yield nil
+ # yield [1, 2]
+ # end
+ # e = o.to_enum
+ # p e.next_values
+ # p e.next_values
+ # p e.next_values
+ # p e.next_values
+ # p e.next_values
+ # e = o.to_enum
+ # p e.next
+ # p e.next
+ # p e.next
+ # p e.next
+ # p e.next
+ #
+ # ## yield args next_values next
+ # # yield [] nil
+ # # yield 1 [1] 1
+ # # yield 1, 2 [1, 2] [1, 2]
+ # # yield nil [nil] nil
+ # # yield [1, 2] [[1, 2]] [1, 2]
+ #
+ # Note that +next_values+ does not affect other non-external enumeration
+ # methods unless underlying iteration method itself has side-effect
+ #
+ def next_values
+ if @lookahead
+ vs = @lookahead
+ @lookahead = nil
+ return vs
+ end
+ raise @stop_exc if @stop_exc
+
+ curr = Fiber.current
+
+ if !@fib || !@fib.alive?
+ @dst = curr
+ @fib = Fiber.new do
+ result = each do |*args|
+ feedvalue = nil
+ Fiber.yield args
+ if @feedvalue
+ feedvalue = @feedvalue
+ @feedvalue = nil
+ end
+ feedvalue
+ end
+ @stop_exc = StopIteration.new "iteration reached an end"
+ @stop_exc.result = result
+ Fiber.yield nil
+ end
+ @lookahead = nil
+ end
+
+ vs = @fib.resume curr
+ if @stop_exc
+ @fib = nil
+ @dst = nil
+ @lookahead = nil
+ @feedvalue = nil
+ raise @stop_exc
+ end
+ vs
+ end
+
+ ##
+ # call-seq:
+ # e.peek -> object
+ #
+ # Returns the next object in the enumerator, but doesn't move the internal
+ # position forward. If the position is already at the end, StopIteration
+ # is raised.
+ #
+ # === Example
+ #
+ # a = [1,2,3]
+ # e = a.to_enum
+ # p e.next #=> 1
+ # p e.peek #=> 2
+ # p e.peek #=> 2
+ # p e.peek #=> 2
+ # p e.next #=> 2
+ # p e.next #=> 3
+ # p e.next #raises StopIteration
+ #
+ def peek
+ peek_values.__svalue
+ end
+
+ ##
+ # call-seq:
+ # e.peek_values -> array
+ #
+ # Returns the next object as an array, similar to Enumerator#next_values, but
+ # doesn't move the internal position forward. If the position is already at
+ # the end, StopIteration is raised.
+ #
+ # === Example
+ #
+ # o = Object.new
+ # def o.each
+ # yield
+ # yield 1
+ # yield 1, 2
+ # end
+ # e = o.to_enum
+ # p e.peek_values #=> []
+ # e.next
+ # p e.peek_values #=> [1]
+ # p e.peek_values #=> [1]
+ # e.next
+ # p e.peek_values #=> [1, 2]
+ # e.next
+ # p e.peek_values # raises StopIteration
+ #
+ def peek_values
+ if @lookahead.nil?
+ @lookahead = next_values
+ end
+ @lookahead.dup
+ end
+
+ ##
+ # call-seq:
+ # e.rewind -> e
+ #
+ # Rewinds the enumeration sequence to the beginning.
+ #
+ # If the enclosed object responds to a "rewind" method, it is called.
+ #
+ def rewind
+ @obj.rewind if @obj.respond_to? :rewind
+ @fib = nil
+ @dst = nil
+ @lookahead = nil
+ @feedvalue = nil
+ @stop_exc = false
+ self
+ end
+
+ ##
+ # call-seq:
+ # e.feed obj -> nil
+ #
+ # Sets the value to be returned by the next yield inside +e+.
+ #
+ # If the value is not set, the yield returns nil.
+ #
+ # This value is cleared after being yielded.
+ #
+ # # Array#map passes the array's elements to "yield" and collects the
+ # # results of "yield" as an array.
+ # # Following example shows that "next" returns the passed elements and
+ # # values passed to "feed" are collected as an array which can be
+ # # obtained by StopIteration#result.
+ # e = [1,2,3].map
+ # p e.next #=> 1
+ # e.feed "a"
+ # p e.next #=> 2
+ # e.feed "b"
+ # p e.next #=> 3
+ # e.feed "c"
+ # begin
+ # e.next
+ # rescue StopIteration
+ # p $!.result #=> ["a", "b", "c"]
+ # end
+ #
+ # o = Object.new
+ # def o.each
+ # x = yield # (2) blocks
+ # p x # (5) => "foo"
+ # x = yield # (6) blocks
+ # p x # (8) => nil
+ # x = yield # (9) blocks
+ # p x # not reached w/o another e.next
+ # end
+ #
+ # e = o.to_enum
+ # e.next # (1)
+ # e.feed "foo" # (3)
+ # e.next # (4)
+ # e.next # (7)
+ # # (10)
+ #
+ def feed(value)
+ raise TypeError, "feed value already set" if @feedvalue
+ @feedvalue = value
+ nil
+ end
+
+ # just for internal
+ class Generator
+ include Enumerable
+ def initialize(&block)
+ raise TypeError, "wrong argument type #{self.class} (expected Proc)" unless block.kind_of? Proc
+
+ @proc = block
+ end
+
+ def each(*args, &block)
+ args.unshift Yielder.new(&block)
+ @proc.call(*args)
+ end
+ end
+
+ # just for internal
+ class Yielder
+ def initialize(&block)
+ raise LocalJumpError, "no block given" unless block
+
+ @proc = block
+ end
+
+ def yield(*args)
+ @proc.call(*args)
+ end
+
+ def << *args
+ self.yield(*args)
+ self
+ end
+ end
+end
+
+module Kernel
+ ##
+ # call-seq:
+ # obj.to_enum(method = :each, *args) -> enum
+ # obj.enum_for(method = :each, *args) -> enum
+ # obj.to_enum(method = :each, *args) {|*args| block} -> enum
+ # obj.enum_for(method = :each, *args){|*args| block} -> enum
+ #
+ # Creates a new Enumerator which will enumerate by calling +method+ on
+ # +obj+, passing +args+ if any.
+ #
+ # If a block is given, it will be used to calculate the size of
+ # the enumerator without the need to iterate it (see Enumerator#size).
+ #
+ # === Examples
+ #
+ # str = "xyz"
+ #
+ # enum = str.enum_for(:each_byte)
+ # enum.each { |b| puts b }
+ # # => 120
+ # # => 121
+ # # => 122
+ #
+ # # protect an array from being modified by some_method
+ # a = [1, 2, 3]
+ # some_method(a.to_enum)
+ #
+ # It is typical to call to_enum when defining methods for
+ # a generic Enumerable, in case no block is passed.
+ #
+ # Here is such an example, with parameter passing and a sizing block:
+ #
+ # module Enumerable
+ # # a generic method to repeat the values of any enumerable
+ # def repeat(n)
+ # raise ArgumentError, "#{n} is negative!" if n < 0
+ # unless block_given?
+ # return to_enum(__method__, n) do # __method__ is :repeat here
+ # sz = size # Call size and multiply by n...
+ # sz * n if sz # but return nil if size itself is nil
+ # end
+ # end
+ # each do |*val|
+ # n.times { yield *val }
+ # end
+ # end
+ # end
+ #
+ # %i[hello world].repeat(2) { |w| puts w }
+ # # => Prints 'hello', 'hello', 'world', 'world'
+ # enum = (1..14).repeat(3)
+ # # => returns an Enumerator when called without a block
+ # enum.first(4) # => [1, 1, 1, 2]
+ #
+ def to_enum(meth=:each, *args)
+ Enumerator.new self, meth, *args
+ end
+ alias enum_for to_enum
+end
+
+module Enumerable
+ # use Enumerator to use infinite sequence
+ def zip(*arg)
+ ary = []
+ arg = arg.map{|a|a.each}
+ i = 0
+ self.each do |*val|
+ a = []
+ a.push(val.__svalue)
+ idx = 0
+ while idx < arg.size
+ begin
+ a.push(arg[idx].next)
+ rescue StopIteration
+ a.push(nil)
+ end
+ idx += 1
+ end
+ ary.push(a)
+ i += 1
+ end
+ ary
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/test/enumerator.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/test/enumerator.rb
new file mode 100644
index 00000000..763cd36e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-enumerator/test/enumerator.rb
@@ -0,0 +1,546 @@
+@obj = Object.new
+class << @obj
+ include Enumerable
+ def foo *a
+ a.each { |x| yield x }
+ end
+end
+
+assert 'Enumerator' do
+ assert_equal Class, Enumerator.class
+end
+
+assert 'Enumerator' do
+ assert_equal Object, Enumerator.superclass
+end
+
+assert 'Enumerator.new' do
+ assert_equal [0,1,2], 3.times.map{|i| i}.sort
+ assert_equal [:x,:y,:z], [:x,:y,:z].each.map{|i| i}.sort
+ assert_equal [[:x,1],[:y,2]], {x:1, y:2}.each.map{|i| i}.sort
+ assert_equal [1,2,3], @obj.to_enum(:foo, 1,2,3).to_a
+ assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
+ assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
+ assert_raise(ArgumentError) { Enumerator.new }
+ enum = @obj.to_enum
+ assert_raise(NoMethodError) { enum.each {} }
+
+ # examples
+ fib = Enumerator.new do |y|
+ a = b = 1
+ loop do
+ y << a
+ a, b = b, a + b
+ end
+ end
+ assert_equal fib.take(10), [1,1,2,3,5,8,13,21,34,55]
+end
+
+assert 'Enumerator#initialize_copy' do
+ assert_equal [1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).dup.to_a
+ e = @obj.to_enum :foo, 1, 2, 3
+ assert_nothing_raised { assert_equal(1, e.next) }
+ assert_raise(TypeError) { e.dup }
+
+ e = Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.dup
+ assert_nothing_raised { assert_equal(1, e.next) }
+ assert_raise(TypeError) { e.dup }
+end
+
+assert 'Enumerator#with_index' do
+ assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a)
+ assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
+ a = []
+ @obj.to_enum(:foo, 1, 2, 3).with_index(10).with_index(20) { |*i| a << i }
+ assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a
+end
+
+assert 'Enumerator#with_index nonnum offset' do
+ s = Object.new
+ def s.to_int; 1 end
+ assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
+end
+
+assert 'Enumerator#with_index string offset' do
+ assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
+end
+
+assert 'Enumerator#each_with_index' do
+ assert_equal([[1,0],[2,1],[3,2]], @obj.to_enum(:foo, 1, 2, 3).each_with_index.to_a)
+ a = []
+ @obj.to_enum(:foo, 1, 2, 3).each_with_index {|*i| a << i}
+ assert_equal([[1, 0], [2, 1], [3, 2]], a)
+end
+
+assert 'Enumerator#with_object' do
+ obj = [0, 1]
+ ret = (1..10).each.with_object(obj) {|i, memo|
+ memo[0] += i
+ memo[1] *= i
+ }
+ assert_true(obj.equal?(ret))
+ assert_equal([55, 3628800], ret)
+end
+
+assert 'Enumerator#with_object arguments' do
+ to_three = Enumerator.new do |y|
+ 3.times do |x|
+ y << x
+ end
+ end
+
+ a = []
+ to_three_with_string = to_three.with_object("foo")
+ to_three_with_string.each do |x,string|
+ a << "#{string}:#{x}"
+ end
+ assert_equal ["foo:0","foo:1","foo:2"], a
+end
+
+assert 'Enumerator#inspect' do
+ e = (0..10).each
+ assert_equal("#<Enumerator: 0..10:each>", e.inspect)
+ e = Enumerator.new("FooObject", :foo, 1)
+ assert_equal("#<Enumerator: FooObject:foo(1)>", e.inspect)
+ e = Enumerator.new("FooObject", :foo, 1, 2, 3)
+ assert_equal("#<Enumerator: FooObject:foo(1, 2, 3)>", e.inspect)
+end
+
+assert 'Enumerator#each' do
+ o = Object.new
+ def o.each(ary)
+ ary << 1
+ yield
+ end
+ ary = []
+ e = o.to_enum.each(ary)
+ e.next
+ assert_equal([1], ary)
+end
+
+assert 'Enumerator#each arguments' do
+ obj = Object.new
+
+ def obj.each_arg(a, b=:b, *rest)
+ yield a
+ yield b
+ yield rest
+ :method_returned
+ end
+
+ enum = obj.to_enum :each_arg, :a, :x
+
+ assert_equal [:a, :x, []], enum.each.to_a
+ assert_true enum.each.equal?(enum)
+ assert_equal :method_returned, enum.each { |elm| elm }
+
+ assert_equal [:a, :x, [:y, :z]], enum.each(:y, :z).to_a
+ assert_false enum.each(:y, :z).equal?(enum)
+ assert_equal :method_returned, enum.each(:y, :z) { |elm| elm }
+end
+
+assert 'Enumerator#next' do
+ e = 3.times
+ 3.times { |i|
+ assert_equal i, e.next
+ }
+ assert_raise(StopIteration) { e.next }
+end
+
+assert 'Enumerator#next_values' do
+ o = Object.new
+ def o.each
+ yield
+ yield 1
+ yield 1, 2
+ end
+ e = o.to_enum
+ assert_equal nil, e.next
+ assert_equal 1, e.next
+ assert_equal [1,2], e.next
+ e = o.to_enum
+ assert_equal [], e.next_values
+ assert_equal [1], e.next_values
+ assert_equal [1,2], e.next_values
+end
+
+assert 'Enumerator#peek' do
+ a = [1]
+ e = a.each
+ assert_equal 1, e.peek
+ assert_equal 1, e.peek
+ assert_equal 1, e.next
+ assert_raise(StopIteration) { e.peek }
+ assert_raise(StopIteration) { e.peek }
+end
+
+assert 'Enumerator#peek modify' do
+ o = Object.new
+ def o.each
+ yield 1,2
+ end
+ e = o.to_enum
+ a = e.peek
+ a << 3
+ assert_equal([1,2], e.peek)
+end
+
+assert 'Enumerator#peek_values' do
+ o = Object.new
+ def o.each
+ yield
+ yield 1
+ yield 1, 2
+ end
+ e = o.to_enum
+ assert_equal nil, e.peek
+ assert_equal nil, e.next
+ assert_equal 1, e.peek
+ assert_equal 1, e.next
+ assert_equal [1,2], e.peek
+ assert_equal [1,2], e.next
+ e = o.to_enum
+ assert_equal [], e.peek_values
+ assert_equal [], e.next_values
+ assert_equal [1], e.peek_values
+ assert_equal [1], e.next_values
+ assert_equal [1,2], e.peek_values
+ assert_equal [1,2], e.next_values
+ e = o.to_enum
+ assert_equal [], e.peek_values
+ assert_equal nil, e.next
+ assert_equal [1], e.peek_values
+ assert_equal 1, e.next
+ assert_equal [1,2], e.peek_values
+ assert_equal [1,2], e.next
+ e = o.to_enum
+ assert_equal nil, e.peek
+ assert_equal [], e.next_values
+ assert_equal 1, e.peek
+ assert_equal [1], e.next_values
+ assert_equal [1,2], e.peek
+ assert_equal [1,2], e.next_values
+end
+
+assert 'Enumerator#peek_values modify' do
+ o = Object.new
+ def o.each
+ yield 1,2
+ end
+ e = o.to_enum
+ a = e.peek_values
+ a << 3
+ assert_equal [1,2], e.peek
+end
+
+assert 'Enumerator#feed' do
+ o = Object.new
+ def o.each(ary)
+ ary << yield
+ ary << yield
+ ary << yield
+ end
+ ary = []
+ e = o.to_enum :each, ary
+ e.next
+ e.feed 1
+ e.next
+ e.feed 2
+ e.next
+ e.feed 3
+ assert_raise(StopIteration) { e.next }
+ assert_equal [1,2,3], ary
+end
+
+assert 'Enumerator#feed mixed' do
+ o = Object.new
+ def o.each(ary)
+ ary << yield
+ ary << yield
+ ary << yield
+ end
+ ary = []
+ e = o.to_enum :each, ary
+ e.next
+ e.feed 1
+ e.next
+ e.next
+ e.feed 3
+ assert_raise(StopIteration) { e.next }
+ assert_equal [1,nil,3], ary
+end
+
+assert 'Enumerator#feed twice' do
+ o = Object.new
+ def o.each(ary)
+ ary << yield
+ ary << yield
+ ary << yield
+ end
+ ary = []
+ e = o.to_enum :each, ary
+ e.feed 1
+ assert_raise(TypeError) { e.feed 2 }
+end
+
+assert 'Enumerator#feed before first next' do
+ o = Object.new
+ def o.each(ary)
+ ary << yield
+ ary << yield
+ ary << yield
+ end
+ ary = []
+ e = o.to_enum :each, ary
+ e.feed 1
+ e.next
+ e.next
+ assert_equal [1], ary
+end
+
+assert 'Enumerator#feed yielder' do
+ x = nil
+ e = Enumerator.new {|y| x = y.yield; 10 }
+ e.next
+ e.feed 100
+ assert_raise(StopIteration) { e.next }
+ assert_equal 100, x
+end
+
+assert 'Enumerator#rewind' do
+ e = @obj.to_enum(:foo, 1, 2, 3)
+ assert_equal 1, e.next
+ assert_equal 2, e.next
+ e.rewind
+ assert_equal 1, e.next
+ assert_equal 2, e.next
+ assert_equal 3, e.next
+ assert_raise(StopIteration) { e.next }
+end
+
+assert 'Enumerator#rewind clear feed' do
+ o = Object.new
+ def o.each(ary)
+ ary << yield
+ ary << yield
+ ary << yield
+ end
+ ary = []
+ e = o.to_enum(:each, ary)
+ e.next
+ e.feed 1
+ e.next
+ e.feed 2
+ e.rewind
+ e.next
+ e.next
+ assert_equal([1,nil], ary)
+end
+
+assert 'Enumerator#rewind clear' do
+ o = Object.new
+ def o.each(ary)
+ ary << yield
+ ary << yield
+ ary << yield
+ end
+ ary = []
+ e = o.to_enum :each, ary
+ e.next
+ e.feed 1
+ e.next
+ e.feed 2
+ e.rewind
+ e.next
+ e.next
+ assert_equal [1,nil], ary
+end
+
+assert 'Enumerator::Generator' do
+ # note: Enumerator::Generator is a class just for internal
+ g = Enumerator::Generator.new {|y| y << 1 << 2 << 3; :foo }
+ g2 = g.dup
+ a = []
+ assert_equal(:foo, g.each {|x| a << x })
+ assert_equal([1, 2, 3], a)
+ a = []
+ assert_equal(:foo, g2.each {|x| a << x })
+ assert_equal([1, 2, 3], a)
+end
+
+assert 'Enumerator::Generator args' do
+ g = Enumerator::Generator.new {|y, x| y << 1 << 2 << 3; x }
+ a = []
+ assert_equal(:bar, g.each(:bar) {|x| a << x })
+ assert_equal([1, 2, 3], a)
+end
+
+assert 'Enumerator::Yielder' do
+ # note: Enumerator::Yielder is a class just for internal
+ a = []
+ y = Enumerator::Yielder.new {|x| a << x }
+ assert_equal(y, y << 1 << 2 << 3)
+ assert_equal([1, 2, 3], a)
+
+ a = []
+ y = Enumerator::Yielder.new {|x| a << x }
+ assert_equal([1], y.yield(1))
+ assert_equal([1, 2], y.yield(2))
+ assert_equal([1, 2, 3], y.yield(3))
+
+ assert_raise(LocalJumpError) { Enumerator::Yielder.new }
+end
+
+assert 'next after StopIteration' do
+ a = [1]
+ e = a.each
+ assert_equal(1, e.next)
+ assert_raise(StopIteration) { e.next }
+ assert_raise(StopIteration) { e.next }
+ e.rewind
+ assert_equal(1, e.next)
+ assert_raise(StopIteration) { e.next }
+ assert_raise(StopIteration) { e.next }
+end
+
+assert 'gc' do
+ assert_nothing_raised do
+ 1.times do
+ foo = [1,2,3].to_enum
+ GC.start
+ end
+ GC.start
+ end
+end
+
+assert 'nested iteration' do
+ def (o = Object.new).each
+ yield :ok1
+ yield [:ok2, :x].each.next
+ end
+ e = o.to_enum
+ assert_equal :ok1, e.next
+ assert_equal :ok2, e.next
+ assert_raise(StopIteration) { e.next }
+end
+
+assert 'Kernel#to_enum' do
+ assert_equal Enumerator, [].to_enum.class
+ assert_raise(ArgumentError){ nil.to_enum }
+end
+
+assert 'modifying existing methods' do
+ assert_equal Enumerator, loop.class
+ e = 3.times
+ i = 0
+ loop_ret = loop {
+ assert_equal i, e.next
+ i += 1
+ }
+end
+
+assert 'Integral#times' do
+ a = 3
+ b = a.times
+ c = []
+ b.with_object(c) do |i, obj|
+ obj << i
+ end
+ assert_equal 3, a
+ assert_equal Enumerator, b.class
+ assert_equal [0,1,2], c
+end
+
+assert 'Enumerable#each_with_index' do
+ assert_equal [['a',0],['b',1],['c',2]], ['a','b','c'].each_with_index.to_a
+end
+
+assert 'Enumerable#map' do
+ a = [1,2,3]
+ b = a.map
+ c = b.with_index do |i, index|
+ [i*i, index*index]
+ end
+ assert_equal [1,2,3], a
+ assert_equal [[1,0],[4,1],[9,4]], c
+end
+
+assert 'Enumerable#find_all' do
+ assert_equal [[3,4]], [[1,2],[3,4],[5,6]].find_all.each{ |i| i[1] == 4 }
+end
+
+assert 'Array#each_index' do
+ a = [1,2,3]
+ b = a.each_index
+ c = []
+ b.with_index do |index1,index2|
+ c << [index1+2,index2+5]
+ end
+ assert_equal [1,2,3], a
+ assert_equal [[2,5],[3,6],[4,7]], c
+end
+
+assert 'Array#map!' do
+ a = [1,2,3]
+ b = a.map!
+ b.with_index do |i, index|
+ [i*i, index*index]
+ end
+ assert_equal [[1,0],[4,1],[9,4]], a
+end
+
+assert 'Hash#each' do
+ a = {a:1,b:2}
+ b = a.each
+ c = []
+ b.each do |k,v|
+ c << [k,v]
+ end
+ assert_equal [[:a,1], [:b,2]], c.sort
+end
+
+assert 'Hash#each_key' do
+ assert_equal [:a,:b], {a:1,b:2}.each_key.to_a.sort
+end
+
+assert 'Hash#each_value' do
+ assert_equal [1,2], {a:1,b:2}.each_value.to_a.sort
+end
+
+assert 'Hash#select' do
+ h = {1=>2,3=>4,5=>6}
+ hret = h.select.with_index {|a,b| a[1] == 4}
+ assert_equal({3=>4}, hret)
+ assert_equal({1=>2,3=>4,5=>6}, h)
+end
+
+assert 'Hash#select!' do
+ h = {1=>2,3=>4,5=>6}
+ hret = h.select!.with_index {|a,b| a[1] == 4}
+ assert_equal h, hret
+ assert_equal({3=>4}, h)
+end
+
+assert 'Hash#reject' do
+ h = {1=>2,3=>4,5=>6}
+ hret = h.reject.with_index {|a,b| a[1] == 4}
+ assert_equal({1=>2,5=>6}, hret)
+ assert_equal({1=>2,3=>4,5=>6}, h)
+end
+
+assert 'Hash#reject!' do
+ h = {1=>2,3=>4,5=>6}
+ hret = h.reject!.with_index {|a,b| a[1] == 4}
+ assert_equal h, hret
+ assert_equal({1=>2,5=>6}, h)
+end
+
+assert 'Range#each' do
+ a = (1..5)
+ b = a.each
+ c = []
+ b.each do |i|
+ c << i
+ end
+ assert_equal [1,2,3,4,5], c
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/mrbgem.rake
new file mode 100644
index 00000000..30a4259a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/mrbgem.rake
@@ -0,0 +1,10 @@
+MRuby::Gem::Specification.new('mruby-error') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'extensional error handling'
+
+ if build.cxx_exception_enabled?
+ @objs << build.compile_as_cxx("#{spec.dir}/src/exception.c", "#{spec.build_dir}/src/exception.cxx")
+ @objs.delete_if { |v| v == objfile("#{spec.build_dir}/src/exception") }
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/src/exception.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/src/exception.c
new file mode 100644
index 00000000..170abb69
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/src/exception.c
@@ -0,0 +1,100 @@
+#include <mruby.h>
+#include <mruby/throw.h>
+#include <mruby/error.h>
+
+MRB_API mrb_value
+mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result = mrb_nil_value();
+
+ if (state) { *state = FALSE; }
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, data);
+ mrb->jmp = prev_jmp;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+ result = mrb_obj_value(mrb->exc);
+ mrb->exc = NULL;
+ if (state) { *state = TRUE; }
+ } MRB_END_EXC(&c_jmp);
+
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
+MRB_API mrb_value
+mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, b_data);
+ mrb->jmp = prev_jmp;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+ ensure(mrb, e_data);
+ MRB_THROW(mrb->jmp); /* rethrow catched exceptions */
+ } MRB_END_EXC(&c_jmp);
+
+ ensure(mrb, e_data);
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
+MRB_API mrb_value
+mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t rescue, mrb_value r_data)
+{
+ return mrb_rescue_exceptions(mrb, body, b_data, rescue, r_data, 1, &mrb->eStandardError_class);
+}
+
+MRB_API mrb_value
+mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data,
+ mrb_int len, struct RClass **classes)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result;
+ mrb_bool error_matched = FALSE;
+ mrb_int i;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, b_data);
+ mrb->jmp = prev_jmp;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+
+ for (i = 0; i < len; ++i) {
+ if (mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), classes[i])) {
+ error_matched = TRUE;
+ break;
+ }
+ }
+
+ if (!error_matched) { MRB_THROW(mrb->jmp); }
+
+ mrb->exc = NULL;
+ result = rescue(mrb, r_data);
+ } MRB_END_EXC(&c_jmp);
+
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
+void
+mrb_mruby_error_gem_init(mrb_state *mrb)
+{
+}
+
+void
+mrb_mruby_error_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.c
new file mode 100644
index 00000000..4de0e960
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.c
@@ -0,0 +1,59 @@
+#include <mruby.h>
+#include <mruby/error.h>
+#include <mruby/array.h>
+
+static mrb_value
+protect_cb(mrb_state *mrb, mrb_value b)
+{
+ return mrb_yield_argv(mrb, b, 0, NULL);
+}
+
+static mrb_value
+run_protect(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b;
+ mrb_value ret[2];
+ mrb_bool state;
+ mrb_get_args(mrb, "&", &b);
+ ret[0] = mrb_protect(mrb, protect_cb, b, &state);
+ ret[1] = mrb_bool_value(state);
+ return mrb_ary_new_from_values(mrb, 2, ret);
+}
+
+static mrb_value
+run_ensure(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b, e;
+ mrb_get_args(mrb, "oo", &b, &e);
+ return mrb_ensure(mrb, protect_cb, b, protect_cb, e);
+}
+
+static mrb_value
+run_rescue(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b, r;
+ mrb_get_args(mrb, "oo", &b, &r);
+ return mrb_rescue(mrb, protect_cb, b, protect_cb, r);
+}
+
+static mrb_value
+run_rescue_exceptions(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b, r;
+ struct RClass *cls[1];
+ mrb_get_args(mrb, "oo", &b, &r);
+ cls[0] = E_TYPE_ERROR;
+ return mrb_rescue_exceptions(mrb, protect_cb, b, protect_cb, r, 1, cls);
+}
+
+void
+mrb_mruby_error_gem_test(mrb_state *mrb)
+{
+ struct RClass *cls;
+
+ cls = mrb_define_class(mrb, "ExceptionTest", mrb->object_class);
+ mrb_define_module_function(mrb, cls, "mrb_protect", run_protect, MRB_ARGS_NONE() | MRB_ARGS_BLOCK());
+ mrb_define_module_function(mrb, cls, "mrb_ensure", run_ensure, MRB_ARGS_REQ(2));
+ mrb_define_module_function(mrb, cls, "mrb_rescue", run_rescue, MRB_ARGS_REQ(2));
+ mrb_define_module_function(mrb, cls, "mrb_rescue_exceptions", run_rescue_exceptions, MRB_ARGS_REQ(2));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.rb
new file mode 100644
index 00000000..90846504
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-error/test/exception.rb
@@ -0,0 +1,55 @@
+assert 'mrb_protect' do
+ # no failure in protect returns [result, false]
+ assert_equal ['test', false] do
+ ExceptionTest.mrb_protect { 'test' }
+ end
+ # failure in protect returns [exception, true]
+ result = ExceptionTest.mrb_protect { raise 'test' }
+ assert_kind_of RuntimeError, result[0]
+ assert_true result[1]
+end
+
+assert 'mrb_ensure' do
+ a = false
+ assert_equal 'test' do
+ ExceptionTest.mrb_ensure Proc.new { 'test' }, Proc.new { a = true }
+ end
+ assert_true a
+
+ a = false
+ assert_raise RuntimeError do
+ ExceptionTest.mrb_ensure Proc.new { raise 'test' }, Proc.new { a = true }
+ end
+ assert_true a
+end
+
+assert 'mrb_rescue' do
+ assert_equal 'test' do
+ ExceptionTest.mrb_rescue Proc.new { 'test' }, Proc.new {}
+ end
+
+ class CustomExp < Exception
+ end
+
+ assert_raise CustomExp do
+ ExceptionTest.mrb_rescue Proc.new { raise CustomExp.new 'test' }, Proc.new { 'rescue' }
+ end
+
+ assert_equal 'rescue' do
+ ExceptionTest.mrb_rescue Proc.new { raise 'test' }, Proc.new { 'rescue' }
+ end
+end
+
+assert 'mrb_rescue_exceptions' do
+ assert_equal 'test' do
+ ExceptionTest.mrb_rescue_exceptions Proc.new { 'test' }, Proc.new {}
+ end
+
+ assert_raise RangeError do
+ ExceptionTest.mrb_rescue_exceptions Proc.new { raise RangeError.new 'test' }, Proc.new { 'rescue' }
+ end
+
+ assert_equal 'rescue' do
+ ExceptionTest.mrb_rescue_exceptions Proc.new { raise TypeError.new 'test' }, Proc.new { 'rescue' }
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/mrbgem.rake
new file mode 100644
index 00000000..cb8835b3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/mrbgem.rake
@@ -0,0 +1,7 @@
+MRuby::Gem::Specification.new('mruby-eval') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'standard Kernel#eval method'
+
+ add_dependency 'mruby-compiler', :core => 'mruby-compiler'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/src/eval.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/src/eval.c
new file mode 100644
index 00000000..5c0ea82f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/src/eval.c
@@ -0,0 +1,346 @@
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/irep.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
+#include <mruby/error.h>
+
+mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
+mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
+
+static struct mrb_irep *
+get_closure_irep(mrb_state *mrb, int level)
+{
+ struct mrb_context *c = mrb->c;
+ struct REnv *e = c->ci[-1].proc->env;
+ struct RProc *proc;
+
+ if (level == 0) {
+ proc = c->ci[-1].proc;
+ if (MRB_PROC_CFUNC_P(proc)) {
+ return NULL;
+ }
+ return proc->body.irep;
+ }
+
+ while (--level) {
+ e = (struct REnv*)e->c;
+ if (!e) return NULL;
+ }
+
+ if (!e) return NULL;
+ if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
+ c = e->cxt.c;
+ proc = c->cibase[e->cioff].proc;
+
+ if (!proc || MRB_PROC_CFUNC_P(proc)) {
+ return NULL;
+ }
+ return proc->body.irep;
+}
+
+/* search for irep lev above the bottom */
+static mrb_irep*
+search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
+{
+ int i;
+
+ for (i=0; i<top->rlen; i++) {
+ mrb_irep* tmp = top->reps[i];
+
+ if (tmp == bottom) return top;
+ tmp = search_irep(tmp, bnest-1, lev, bottom);
+ if (tmp) {
+ if (bnest == lev) return top;
+ return tmp;
+ }
+ }
+ return NULL;
+}
+
+static inline mrb_code
+search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
+{
+ mrb_irep *virep;
+ int level;
+ int pos;
+
+ for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
+ if (!virep || virep->lv == NULL) {
+ continue;
+ }
+ for (pos = 0; pos < virep->nlocals - 1; pos++) {
+ if (vsym == virep->lv[pos].name) {
+ return (MKARG_B(pos + 1) | MKARG_C(level + bnest));
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+irep_argc(mrb_irep *irep)
+{
+ mrb_code c;
+
+ c = irep->iseq[0];
+ if (GET_OPCODE(c) == OP_ENTER) {
+ mrb_aspec ax = GETARG_Ax(c);
+ /* extra 1 means a slot for block */
+ return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
+ }
+ return 0;
+}
+
+static mrb_bool
+potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
+{
+ if (v >= nlocals) return FALSE;
+ /* skip arguments */
+ if (v < argc+1) return FALSE;
+ return TRUE;
+}
+
+static void
+patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
+{
+ int i;
+ mrb_code c;
+ int argc = irep_argc(irep);
+
+ for (i = 0; i < irep->ilen; i++) {
+ c = irep->iseq[i];
+ switch(GET_OPCODE(c)){
+ case OP_EPUSH:
+ patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1, top);
+ break;
+
+ case OP_LAMBDA:
+ {
+ int arg_c = GETARG_c(c);
+ if (arg_c & OP_L_CAPTURE) {
+ patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1, top);
+ }
+ }
+ break;
+
+ case OP_SEND:
+ if (GETARG_C(c) != 0) {
+ break;
+ }
+ {
+ mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
+ if (arg != 0) {
+ /* must replace */
+ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
+ }
+ }
+ break;
+
+ case OP_MOVE:
+ /* src part */
+ if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
+ mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
+ if (arg != 0) {
+ /* must replace */
+ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
+ }
+ }
+ /* dst part */
+ if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
+ mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
+ if (arg != 0) {
+ /* must replace */
+ irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg;
+ }
+ }
+ break;
+
+ case OP_GETUPVAR:
+ {
+ int lev = GETARG_C(c)+1;
+ mrb_irep *tmp = search_irep(top, bnest, lev, irep);
+ if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
+ mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
+ if (arg != 0) {
+ /* must replace */
+ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
+ }
+ }
+ }
+ break;
+
+ case OP_SETUPVAR:
+ {
+ int lev = GETARG_C(c)+1;
+ mrb_irep *tmp = search_irep(top, bnest, lev, irep);
+ if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
+ mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
+ if (arg != 0) {
+ /* must replace */
+ irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
+ }
+ }
+ }
+ break;
+
+ case OP_STOP:
+ if (mrb->c->ci->acc >= 0) {
+ irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
+ }
+ break;
+ }
+ }
+}
+
+void mrb_codedump_all(mrb_state*, struct RProc*);
+
+static struct RProc*
+create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line)
+{
+ mrbc_context *cxt;
+ struct mrb_parser_state *p;
+ struct RProc *proc;
+ struct REnv *e;
+ struct mrb_context *c = mrb->c;
+
+ if (!mrb_nil_p(binding)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil.");
+ }
+
+ cxt = mrbc_context_new(mrb);
+ cxt->lineno = line;
+
+ mrbc_filename(mrb, cxt, file ? file : "(eval)");
+ cxt->capture_errors = TRUE;
+ cxt->no_optimize = TRUE;
+
+ p = mrb_parse_nstring(mrb, s, len, cxt);
+
+ /* only occur when memory ran out */
+ if (!p) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state.");
+ }
+
+ if (0 < p->nerr) {
+ /* parse error */
+ mrb_value str;
+
+ if (file) {
+ str = mrb_format(mrb, " file %S line %S: %S",
+ mrb_str_new_cstr(mrb, file),
+ mrb_fixnum_value(p->error_buffer[0].lineno),
+ mrb_str_new_cstr(mrb, p->error_buffer[0].message));
+ }
+ else {
+ str = mrb_format(mrb, " line %S: %S",
+ mrb_fixnum_value(p->error_buffer[0].lineno),
+ mrb_str_new_cstr(mrb, p->error_buffer[0].message));
+ }
+ mrb_parser_free(p);
+ mrbc_context_free(mrb, cxt);
+ mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_SYNTAX_ERROR, str));
+ }
+
+ proc = mrb_generate_code(mrb, p);
+ if (proc == NULL) {
+ /* codegen error */
+ mrb_parser_free(p);
+ mrbc_context_free(mrb, cxt);
+ mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
+ }
+ if (c->ci[-1].proc->target_class) {
+ proc->target_class = c->ci[-1].proc->target_class;
+ }
+ e = c->ci[-1].proc->env;
+ if (!e) e = c->ci[-1].env;
+ e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e);
+ e->cxt.c = c;
+ e->cioff = c->ci - c->cibase;
+ e->stack = c->ci->stackent;
+ MRB_SET_ENV_STACK_LEN(e, c->ci->proc->body.irep->nlocals);
+ c->ci->target_class = proc->target_class;
+ c->ci->env = 0;
+ proc->env = e;
+ patch_irep(mrb, proc->body.irep, 0, proc->body.irep);
+ /* mrb_codedump_all(mrb, proc); */
+
+ mrb_parser_free(p);
+ mrbc_context_free(mrb, cxt);
+
+ return proc;
+}
+
+static mrb_value
+exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
+{
+ if (mrb->c->ci->acc < 0) {
+ mrb_value ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0);
+ if (mrb->exc) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
+ }
+ return ret;
+ }
+ return mrb_exec_irep(mrb, self, proc);
+}
+
+static mrb_value
+f_eval(mrb_state *mrb, mrb_value self)
+{
+ char *s;
+ mrb_int len;
+ mrb_value binding = mrb_nil_value();
+ char *file = NULL;
+ mrb_int line = 1;
+ struct RProc *proc;
+
+ mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line);
+
+ proc = create_proc_from_string(mrb, s, len, binding, file, line);
+ mrb_assert(!MRB_PROC_CFUNC_P(proc));
+ return exec_irep(mrb, self, proc);
+}
+
+static mrb_value
+f_instance_eval(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b;
+ mrb_int argc; mrb_value *argv;
+
+ mrb_get_args(mrb, "*!&", &argv, &argc, &b);
+
+ if (mrb_nil_p(b)) {
+ char *s;
+ mrb_int len;
+ char *file = NULL;
+ mrb_int line = 1;
+ mrb_value cv;
+ struct RProc *proc;
+
+ mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
+ cv = mrb_singleton_class(mrb, self);
+ proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
+ proc->target_class = mrb_class_ptr(cv);
+ mrb->c->ci->env = NULL;
+ mrb_assert(!MRB_PROC_CFUNC_P(proc));
+ return exec_irep(mrb, self, proc);
+ }
+ else {
+ mrb_get_args(mrb, "&", &b);
+ return mrb_obj_instance_eval(mrb, self);
+ }
+}
+
+void
+mrb_mruby_eval_gem_init(mrb_state* mrb)
+{
+ mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
+ mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
+}
+
+void
+mrb_mruby_eval_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/test/eval.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/test/eval.rb
new file mode 100644
index 00000000..66ca1fcd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-eval/test/eval.rb
@@ -0,0 +1,101 @@
+assert('Kernel.eval', '15.3.1.2.3') do
+ assert_equal(10) { Kernel.eval '1 * 10' }
+ assert_equal('aaa') { Kernel.eval "'a' * 3" }
+ assert_equal(10) {
+ a = 10
+ Kernel.eval "a"
+ }
+ assert_equal(20) {
+ a = 10
+ Kernel.eval "a = 20"
+ a
+ }
+ assert_equal(15) {
+ c = 5
+ lambda {
+ a = 10
+ Kernel.eval "c = a + c"
+ }.call
+ c
+ }
+ assert_equal(5) {
+ c = 5
+ lambda {
+ Kernel.eval 'lambda { c }.call'
+ }.call
+ }
+ assert_equal(15) {
+ c = 5
+ lambda {
+ a = 10
+ Kernel.eval 'lambda { c = a + c }.call'
+ }.call
+ c
+ }
+ assert_equal(2) {
+ a = 10
+ Kernel.eval 'def f(a); b=a.send(:+, 1); end'
+ f(1)
+ }
+end
+
+assert('Kernel#eval', '15.3.1.3.12') do
+ assert_equal(10) { eval '1 * 10' }
+end
+
+assert('rest arguments of eval') do
+ assert_raise(ArgumentError) { Kernel.eval('0', 0, 'test', 0) }
+ assert_equal ['test', 'test.rb', 10] do
+ Kernel.eval('[\'test\', __FILE__, __LINE__]', nil, 'test.rb', 10)
+ end
+end
+
+assert 'eval syntax error' do
+ assert_raise(SyntaxError) do
+ eval 'p "test'
+ end
+end
+
+assert('String instance_eval') do
+ obj = Object.new
+ obj.instance_variable_set :@test, 'test'
+ assert_raise(ArgumentError) { obj.instance_eval(0) { } }
+ assert_raise(ArgumentError) { obj.instance_eval('0', 'test', 0, 'test') }
+ assert_equal(['test.rb', 10]) { obj.instance_eval('[__FILE__, __LINE__]', 'test.rb', 10)}
+ assert_equal('test') { obj.instance_eval('@test') }
+ assert_equal('test') { obj.instance_eval { @test } }
+ o = Object.new
+ assert_equal ['', o, o], o.instance_eval("[''].each { |s| break [s, o, self] }")
+end
+
+assert('Kernel.#eval(string) context') do
+ class TestEvalConstScope
+ EVAL_CONST_CLASS = 'class'
+ def const_string
+ eval 'EVAL_CONST_CLASS'
+ end
+ end
+ obj = TestEvalConstScope.new
+ assert_raise(NameError) { eval 'EVAL_CONST_CLASS' }
+ assert_equal('class') { obj.const_string }
+end
+
+assert('Object#instance_eval with begin-rescue-ensure execution order') do
+ class HellRaiser
+ def raise_hell
+ order = [:enter_raise_hell]
+ begin
+ order.push :begin
+ self.instance_eval("raise 'error'")
+ rescue
+ order.push :rescue
+ ensure
+ order.push :ensure
+ end
+ order
+ end
+ end
+
+ hell_raiser = HellRaiser.new
+ assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/mrbgem.rake
new file mode 100644
index 00000000..d193528d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-exit') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Kernel#exit method'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/src/mruby-exit.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/src/mruby-exit.c
new file mode 100644
index 00000000..3e147f80
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-exit/src/mruby-exit.c
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <mruby.h>
+
+static mrb_value
+f_exit(mrb_state *mrb, mrb_value self)
+{
+ mrb_int i = EXIT_SUCCESS;
+
+ mrb_get_args(mrb, "|i", &i);
+ exit(i);
+ /* not reached */
+ return mrb_nil_value();
+}
+
+void
+mrb_mruby_exit_gem_init(mrb_state* mrb)
+{
+ mrb_define_method(mrb, mrb->kernel_module, "exit", f_exit, MRB_ARGS_OPT(1));
+}
+
+void
+mrb_mruby_exit_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake
new file mode 100644
index 00000000..815cd3c4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-fiber') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Fiber class'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c
new file mode 100644
index 00000000..9de175f3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/src/fiber.c
@@ -0,0 +1,420 @@
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+
+#define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o))
+
+#define FIBER_STACK_INIT_SIZE 64
+#define FIBER_CI_INIT_SIZE 8
+#define CI_ACC_RESUMED -3
+
+/*
+ * call-seq:
+ * Fiber.new{...} -> obj
+ *
+ * Creates a fiber, whose execution is suspend until it is explicitly
+ * resumed using <code>Fiber#resume</code> method.
+ * The code running inside the fiber can give up control by calling
+ * <code>Fiber.yield</code> in which case it yields control back to caller
+ * (the caller of the <code>Fiber#resume</code>).
+ *
+ * Upon yielding or termination the Fiber returns the value of the last
+ * executed expression
+ *
+ * For instance:
+ *
+ * fiber = Fiber.new do
+ * Fiber.yield 1
+ * 2
+ * end
+ *
+ * puts fiber.resume
+ * puts fiber.resume
+ * puts fiber.resume
+ *
+ * <em>produces</em>
+ *
+ * 1
+ * 2
+ * resuming dead fiber (FiberError)
+ *
+ * The <code>Fiber#resume</code> method accepts an arbitrary number of
+ * parameters, if it is the first call to <code>resume</code> then they
+ * will be passed as block arguments. Otherwise they will be the return
+ * value of the call to <code>Fiber.yield</code>
+ *
+ * Example:
+ *
+ * fiber = Fiber.new do |first|
+ * second = Fiber.yield first + 2
+ * end
+ *
+ * puts fiber.resume 10
+ * puts fiber.resume 14
+ * puts fiber.resume 18
+ *
+ * <em>produces</em>
+ *
+ * 12
+ * 14
+ * resuming dead fiber (FiberError)
+ *
+ */
+static mrb_value
+fiber_init(mrb_state *mrb, mrb_value self)
+{
+ static const struct mrb_context mrb_context_zero = { 0 };
+ struct RFiber *f = fiber_ptr(self);
+ struct mrb_context *c;
+ struct RProc *p;
+ mrb_callinfo *ci;
+ mrb_value blk;
+ size_t slen;
+
+ mrb_get_args(mrb, "&", &blk);
+
+ if (f->cxt) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice");
+ }
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block");
+ }
+ p = mrb_proc_ptr(blk);
+ if (MRB_PROC_CFUNC_P(p)) {
+ mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method");
+ }
+
+ c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
+ *c = mrb_context_zero;
+ f->cxt = c;
+
+ /* initialize VM stack */
+ slen = FIBER_STACK_INIT_SIZE;
+ if (p->body.irep->nregs > slen) {
+ slen += p->body.irep->nregs;
+ }
+ c->stbase = (mrb_value *)mrb_malloc(mrb, slen*sizeof(mrb_value));
+ c->stend = c->stbase + slen;
+ c->stack = c->stbase;
+
+#ifdef MRB_NAN_BOXING
+ {
+ mrb_value *p = c->stbase;
+ mrb_value *pend = c->stend;
+
+ while (p < pend) {
+ SET_NIL_VALUE(*p);
+ p++;
+ }
+ }
+#else
+ memset(c->stbase, 0, slen * sizeof(mrb_value));
+#endif
+
+ /* copy receiver from a block */
+ c->stack[0] = mrb->c->stack[0];
+
+ /* initialize callinfo stack */
+ c->cibase = (mrb_callinfo *)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo));
+ c->ciend = c->cibase + FIBER_CI_INIT_SIZE;
+ c->ci = c->cibase;
+ c->ci->stackent = c->stack;
+
+ /* adjust return callinfo */
+ ci = c->ci;
+ ci->target_class = p->target_class;
+ ci->proc = p;
+ mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p);
+ ci->pc = p->body.irep->iseq;
+ ci->nregs = p->body.irep->nregs;
+ ci[1] = ci[0];
+ c->ci++; /* push dummy callinfo */
+
+ c->fib = f;
+ c->status = MRB_FIBER_CREATED;
+
+ return self;
+}
+
+static struct mrb_context*
+fiber_check(mrb_state *mrb, mrb_value fib)
+{
+ struct RFiber *f = fiber_ptr(fib);
+
+ mrb_assert(f->tt == MRB_TT_FIBER);
+ if (!f->cxt) {
+ mrb_raise(mrb, E_FIBER_ERROR, "uninitialized Fiber");
+ }
+ return f->cxt;
+}
+
+static mrb_value
+fiber_result(mrb_state *mrb, const mrb_value *a, mrb_int len)
+{
+ if (len == 0) return mrb_nil_value();
+ if (len == 1) return a[0];
+ return mrb_ary_new_from_values(mrb, len, a);
+}
+
+/* mark return from context modifying method */
+#define MARK_CONTEXT_MODIFY(c) (c)->ci->target_class = NULL
+
+static void
+fiber_check_cfunc(mrb_state *mrb, struct mrb_context *c)
+{
+ mrb_callinfo *ci;
+
+ for (ci = c->ci; ci >= c->cibase; ci--) {
+ if (ci->acc < 0) {
+ mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary");
+ }
+ }
+}
+
+static void
+fiber_switch_context(mrb_state *mrb, struct mrb_context *c)
+{
+ if (mrb->c->fib) {
+ mrb_write_barrier(mrb, (struct RBasic*)mrb->c->fib);
+ }
+ c->status = MRB_FIBER_RUNNING;
+ mrb->c = c;
+}
+
+static mrb_value
+fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume, mrb_bool vmexec)
+{
+ struct mrb_context *c = fiber_check(mrb, self);
+ struct mrb_context *old_c = mrb->c;
+ mrb_value value;
+
+ fiber_check_cfunc(mrb, c);
+ if (resume && c->status == MRB_FIBER_TRANSFERRED) {
+ mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
+ }
+ if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) {
+ mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)");
+ }
+ if (c->status == MRB_FIBER_TERMINATED) {
+ mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
+ }
+ mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
+ c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
+ if (c->status == MRB_FIBER_CREATED) {
+ mrb_value *b, *e;
+
+ if (len >= c->stend - c->stack) {
+ mrb_raise(mrb, E_FIBER_ERROR, "too many arguments to fiber");
+ }
+ b = c->stack+1;
+ e = b + len;
+ while (b<e) {
+ *b++ = *a++;
+ }
+ c->cibase->argc = len;
+ value = c->stack[0] = c->ci->proc->env->stack[0];
+ }
+ else {
+ value = fiber_result(mrb, a, len);
+ }
+ fiber_switch_context(mrb, c);
+
+ if (vmexec) {
+ c->vmexec = TRUE;
+ value = mrb_vm_exec(mrb, c->ci[-1].proc, c->ci->pc);
+ mrb->c = old_c;
+ }
+ else {
+ MARK_CONTEXT_MODIFY(c);
+ }
+ return value;
+}
+
+/*
+ * call-seq:
+ * fiber.resume(args, ...) -> obj
+ *
+ * Resumes the fiber from the point at which the last <code>Fiber.yield</code>
+ * was called, or starts running it if it is the first call to
+ * <code>resume</code>. Arguments passed to resume will be the value of
+ * the <code>Fiber.yield</code> expression or will be passed as block
+ * parameters to the fiber's block if this is the first <code>resume</code>.
+ *
+ * Alternatively, when resume is called it evaluates to the arguments passed
+ * to the next <code>Fiber.yield</code> statement inside the fiber's block
+ * or to the block value if it runs to completion without any
+ * <code>Fiber.yield</code>
+ */
+static mrb_value
+fiber_resume(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *a;
+ mrb_int len;
+ mrb_bool vmexec = FALSE;
+
+ mrb_get_args(mrb, "*!", &a, &len);
+ if (mrb->c->ci->acc < 0) {
+ vmexec = TRUE;
+ }
+ return fiber_switch(mrb, self, len, a, TRUE, vmexec);
+}
+
+/* resume thread with given arguments */
+MRB_API mrb_value
+mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a)
+{
+ return fiber_switch(mrb, fib, len, a, TRUE, TRUE);
+}
+
+/*
+ * call-seq:
+ * fiber.alive? -> true or false
+ *
+ * Returns true if the fiber can still be resumed. After finishing
+ * execution of the fiber block this method will always return false.
+ */
+static mrb_value
+fiber_alive_p(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_context *c = fiber_check(mrb, self);
+ return mrb_bool_value(c->status != MRB_FIBER_TERMINATED);
+}
+
+static mrb_value
+fiber_eq(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+ mrb_get_args(mrb, "o", &other);
+
+ if (mrb_type(other) != MRB_TT_FIBER) {
+ return mrb_false_value();
+ }
+ return mrb_bool_value(fiber_ptr(self) == fiber_ptr(other));
+}
+
+/*
+ * call-seq:
+ * fiber.transfer(args, ...) -> obj
+ *
+ * Transfers control to receiver fiber of the method call.
+ * Unlike <code>resume</code> the receiver wouldn't be pushed to call
+ * stack of fibers. Instead it will switch to the call stack of
+ * transferring fiber.
+ * When resuming a fiber that was transferred to another fiber it would
+ * cause double resume error. Though when the fiber is re-transferred
+ * and <code>Fiber.yield</code> is called, the fiber would be resumable.
+ */
+static mrb_value
+fiber_transfer(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_context *c = fiber_check(mrb, self);
+ mrb_value* a;
+ mrb_int len;
+
+ fiber_check_cfunc(mrb, mrb->c);
+ mrb_get_args(mrb, "*!", &a, &len);
+
+ if (c == mrb->root_c) {
+ mrb->c->status = MRB_FIBER_TRANSFERRED;
+ fiber_switch_context(mrb, c);
+ MARK_CONTEXT_MODIFY(c);
+ return fiber_result(mrb, a, len);
+ }
+
+ if (c == mrb->c) {
+ return fiber_result(mrb, a, len);
+ }
+
+ return fiber_switch(mrb, self, len, a, FALSE, FALSE);
+}
+
+/* yield values to the caller fiber */
+/* mrb_fiber_yield() must be called as `return mrb_fiber_yield(...)` */
+MRB_API mrb_value
+mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a)
+{
+ struct mrb_context *c = mrb->c;
+
+ if (!c->prev) {
+ mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber");
+ }
+
+ fiber_check_cfunc(mrb, c);
+ c->prev->status = MRB_FIBER_RUNNING;
+ c->status = MRB_FIBER_SUSPENDED;
+ fiber_switch_context(mrb, c->prev);
+ c->prev = NULL;
+ if (c->vmexec) {
+ c->vmexec = FALSE;
+ mrb->c->ci->acc = CI_ACC_RESUMED;
+ }
+ MARK_CONTEXT_MODIFY(mrb->c);
+ return fiber_result(mrb, a, len);
+}
+
+/*
+ * call-seq:
+ * Fiber.yield(args, ...) -> obj
+ *
+ * Yields control back to the context that resumed the fiber, passing
+ * along any arguments that were passed to it. The fiber will resume
+ * processing at this point when <code>resume</code> is called next.
+ * Any arguments passed to the next <code>resume</code> will be the
+ *
+ * mruby limitation: Fiber resume/yield cannot cross C function boundary.
+ * thus you cannot yield from #initialize which is called by mrb_funcall().
+ */
+static mrb_value
+fiber_yield(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *a;
+ mrb_int len;
+
+ mrb_get_args(mrb, "*!", &a, &len);
+ return mrb_fiber_yield(mrb, len, a);
+}
+
+/*
+ * call-seq:
+ * Fiber.current() -> fiber
+ *
+ * Returns the current fiber. If you are not running in the context of
+ * a fiber this method will return the root fiber.
+ */
+static mrb_value
+fiber_current(mrb_state *mrb, mrb_value self)
+{
+ if (!mrb->c->fib) {
+ struct RFiber *f = (struct RFiber*)mrb_obj_alloc(mrb, MRB_TT_FIBER, mrb_class_ptr(self));
+
+ f->cxt = mrb->c;
+ mrb->c->fib = f;
+ }
+ return mrb_obj_value(mrb->c->fib);
+}
+
+void
+mrb_mruby_fiber_gem_init(mrb_state* mrb)
+{
+ struct RClass *c;
+
+ c = mrb_define_class(mrb, "Fiber", mrb->object_class);
+ MRB_SET_INSTANCE_TT(c, MRB_TT_FIBER);
+
+ mrb_define_method(mrb, c, "initialize", fiber_init, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "resume", fiber_resume, MRB_ARGS_ANY());
+ mrb_define_method(mrb, c, "transfer", fiber_transfer, MRB_ARGS_ANY());
+ mrb_define_method(mrb, c, "alive?", fiber_alive_p, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "==", fiber_eq, MRB_ARGS_REQ(1));
+
+ mrb_define_class_method(mrb, c, "yield", fiber_yield, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, c, "current", fiber_current, MRB_ARGS_NONE());
+
+ mrb_define_class(mrb, "FiberError", mrb->eStandardError_class);
+}
+
+void
+mrb_mruby_fiber_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb
new file mode 100644
index 00000000..d063a0a6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-fiber/test/fiber.rb
@@ -0,0 +1,208 @@
+assert('Fiber.new') do
+ f = Fiber.new{}
+ assert_kind_of Fiber, f
+end
+
+assert('Fiber#resume') do
+ f = Fiber.new{|x| x }
+ assert_equal 2, f.resume(2)
+end
+
+assert('Fiber#transfer') do
+ f2 = nil
+ f1 = Fiber.new do |v|
+ Fiber.yield v
+ f2.transfer
+ end
+ f2 = Fiber.new do
+ f1.transfer(1)
+ f1.transfer(1)
+ Fiber.yield 2
+ end
+ assert_equal 1, f2.resume
+ assert_raise(FiberError) { f2.resume }
+ assert_equal 2, f2.transfer
+ assert_raise(FiberError) { f1.resume }
+ f1.transfer
+ f2.resume
+ assert_false f1.alive?
+ assert_false f2.alive?
+end
+
+assert('Fiber#alive?') do
+ f = Fiber.new{ Fiber.yield }
+ f.resume
+ assert_true f.alive?
+ f.resume
+ assert_false f.alive?
+end
+
+assert('Fiber#==') do
+ root = Fiber.current
+ assert_equal root, root
+ assert_equal root, Fiber.current
+ assert_false root != Fiber.current
+ f = Fiber.new {
+ assert_false root == Fiber.current
+ }
+ f.resume
+ assert_false f == root
+ assert_true f != root
+end
+
+assert('Fiber.yield') do
+ f = Fiber.new{|x| Fiber.yield x }
+ assert_equal 3, f.resume(3)
+ assert_true f.alive?
+end
+
+assert('FiberError') do
+ assert_equal StandardError, FiberError.superclass
+end
+
+assert('Fiber iteration') do
+ f1 = Fiber.new{
+ [1,2,3].each{|x| Fiber.yield(x)}
+ }
+ f2 = Fiber.new{
+ [9,8,7].each{|x| Fiber.yield(x)}
+ }
+ a = []
+ 3.times {
+ a << f1.resume
+ a << f2.resume
+ }
+ assert_equal [1,9,2,8,3,7], a
+end
+
+assert('Fiber with splat in the block argument list') {
+ Fiber.new{|*x|x}.resume(1) == [1]
+}
+
+assert('Fiber raises on resume when dead') do
+ assert_raise(FiberError) do
+ f = Fiber.new{}
+ f.resume
+ assert_false f.alive?
+ f.resume
+ end
+end
+
+assert('Yield raises when called on root fiber') do
+ assert_raise(FiberError) { Fiber.yield }
+end
+
+assert('Double resume of Fiber') do
+ f1 = Fiber.new {}
+ f2 = Fiber.new {
+ f1.resume
+ assert_raise(FiberError) { f2.resume }
+ Fiber.yield 0
+ }
+ assert_equal 0, f2.resume
+ f2.resume
+ assert_false f1.alive?
+ assert_false f2.alive?
+end
+
+assert('Recursive resume of Fiber') do
+ f1, f2 = nil, nil
+ f1 = Fiber.new { assert_raise(FiberError) { f2.resume } }
+ f2 = Fiber.new {
+ f1.resume
+ Fiber.yield 0
+ }
+ f3 = Fiber.new {
+ f2.resume
+ }
+ assert_equal 0, f3.resume
+ f2.resume
+ assert_false f1.alive?
+ assert_false f2.alive?
+ assert_false f3.alive?
+end
+
+assert('Root fiber resume') do
+ root = Fiber.current
+ assert_raise(FiberError) { root.resume }
+ f = Fiber.new {
+ assert_raise(FiberError) { root.resume }
+ }
+ f.resume
+ assert_false f.alive?
+end
+
+assert('Fiber without block') do
+ assert_raise(ArgumentError) { Fiber.new }
+end
+
+
+assert('Transfer to self.') do
+ result = []
+ f = Fiber.new { result << :start; f.transfer; result << :end }
+ f.transfer
+ assert_equal [:start, :end], result
+
+ result = []
+ f = Fiber.new { result << :start; f.transfer; result << :end }
+ f.resume
+ assert_equal [:start, :end], result
+end
+
+assert('Resume transferred fiber') do
+ f = Fiber.new {
+ assert_raise(FiberError) { f.resume }
+ }
+ f.transfer
+end
+
+assert('Root fiber transfer.') do
+ result = nil
+ root = Fiber.current
+ f = Fiber.new {
+ result = :ok
+ root.transfer
+ }
+ f.resume
+ assert_true f.alive?
+ assert_equal :ok, result
+end
+
+assert('Break nested fiber with root fiber transfer') do
+ root = Fiber.current
+
+ result = nil
+ f2 = nil
+ f1 = Fiber.new {
+ Fiber.yield f2.resume
+ result = :f1
+ }
+ f2 = Fiber.new {
+ result = :to_root
+ root.transfer :from_f2
+ result = :f2
+ }
+ assert_equal :from_f2, f1.resume
+ assert_equal :to_root, result
+ assert_equal :f2, f2.transfer
+ assert_equal :f2, result
+ assert_false f2.alive?
+ assert_equal :f1, f1.resume
+ assert_equal :f1, result
+ assert_false f1.alive?
+end
+
+assert('CRuby Fiber#transfer test.') do
+ ary = []
+ f2 = nil
+ f1 = Fiber.new{
+ ary << f2.transfer(:foo)
+ :ok
+ }
+ f2 = Fiber.new{
+ ary << f1.transfer(:baz)
+ :ng
+ }
+ assert_equal :ok, f1.transfer
+ assert_equal [:baz], ary
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrbgem.rake
new file mode 100644
index 00000000..103410ab
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrbgem.rake
@@ -0,0 +1,8 @@
+MRuby::Gem::Specification.new('mruby-hash-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Hash class extension'
+ spec.add_dependency 'mruby-enum-ext', core: 'mruby-enum-ext'
+ spec.add_dependency 'mruby-array-ext', core: 'mruby-array-ext'
+ spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb
new file mode 100644
index 00000000..73d1fbe6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb
@@ -0,0 +1,477 @@
+class Hash
+
+ # ISO does not define Hash#each_pair, so each_pair is defined in gem.
+ alias each_pair each
+
+ ##
+ # call-seq:
+ # Hash[ key, value, ... ] -> new_hash
+ # Hash[ [ [key, value], ... ] ] -> new_hash
+ # Hash[ object ] -> new_hash
+ #
+ # Creates a new hash populated with the given objects.
+ #
+ # Similar to the literal `{ _key_ => _value_, ... }`. In the first
+ # form, keys and values occur in pairs, so there must be an even number of
+ # arguments.
+ #
+ # The second and third form take a single argument which is either an array
+ # of key-value pairs or an object convertible to a hash.
+ #
+ # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
+ # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
+ # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
+ #
+
+ def self.[](*object)
+ length = object.length
+ if length == 1
+ o = object[0]
+ if o.respond_to?(:to_hash)
+ h = self.new
+ object[0].to_hash.each { |k, v| h[k] = v }
+ return h
+ elsif o.respond_to?(:to_a)
+ h = self.new
+ o.to_a.each do |i|
+ raise ArgumentError, "wrong element type #{i.class} (expected array)" unless i.respond_to?(:to_a)
+ k, v = nil
+ case i.size
+ when 2
+ k = i[0]
+ v = i[1]
+ when 1
+ k = i[0]
+ else
+ raise ArgumentError, "invalid number of elements (#{i.size} for 1..2)"
+ end
+ h[k] = v
+ end
+ return h
+ end
+ end
+ unless length % 2 == 0
+ raise ArgumentError, 'odd number of arguments for Hash'
+ end
+ h = self.new
+ 0.step(length - 2, 2) do |i|
+ h[object[i]] = object[i + 1]
+ end
+ h
+ end
+
+ ##
+ # call-seq:
+ # Hash.try_convert(obj) -> hash or nil
+ #
+ # Try to convert <i>obj</i> into a hash, using to_hash method.
+ # Returns converted hash or nil if <i>obj</i> cannot be converted
+ # for any reason.
+ #
+ # Hash.try_convert({1=>2}) # => {1=>2}
+ # Hash.try_convert("1=>2") # => nil
+ #
+ def self.try_convert(obj)
+ if obj.respond_to?(:to_hash)
+ obj.to_hash
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
+ # hsh.merge!(other_hash) -> hsh
+ # hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh
+ #
+ # Adds the contents of _other_hash_ to _hsh_. If no block is specified,
+ # entries with duplicate keys are overwritten with the values from
+ # _other_hash_, otherwise the value of each duplicate key is determined by
+ # calling the block with the key, its value in _hsh_ and its value in
+ # _other_hash_.
+ #
+ # h1 = { "a" => 100, "b" => 200 }
+ # h2 = { "b" => 254, "c" => 300 }
+ # h1.merge!(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
+ #
+ # h1 = { "a" => 100, "b" => 200 }
+ # h2 = { "b" => 254, "c" => 300 }
+ # h1.merge!(h2) { |key, v1, v2| v1 }
+ # #=> {"a"=>100, "b"=>200, "c"=>300}
+ #
+
+ def merge!(other, &block)
+ raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
+ if block
+ other.each_key{|k|
+ self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
+ }
+ else
+ other.each_key{|k| self[k] = other[k]}
+ end
+ self
+ end
+
+ alias update merge!
+
+ ##
+ # call-seq:
+ # hsh.compact -> new_hsh
+ #
+ # Returns a new hash with the nil values/key pairs removed
+ #
+ # h = { a: 1, b: false, c: nil }
+ # h.compact #=> { a: 1, b: false }
+ # h #=> { a: 1, b: false, c: nil }
+ #
+ def compact
+ result = self.dup
+ result.compact!
+ result
+ end
+
+ ##
+ # call-seq:
+ # hsh.fetch(key [, default] ) -> obj
+ # hsh.fetch(key) {| key | block } -> obj
+ #
+ # Returns a value from the hash for the given key. If the key can't be
+ # found, there are several options: With no other arguments, it will
+ # raise an <code>KeyError</code> exception; if <i>default</i> is
+ # given, then that will be returned; if the optional code block is
+ # specified, then that will be run and its result returned.
+ #
+ # h = { "a" => 100, "b" => 200 }
+ # h.fetch("a") #=> 100
+ # h.fetch("z", "go fish") #=> "go fish"
+ # h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
+ #
+ # The following example shows that an exception is raised if the key
+ # is not found and a default value is not supplied.
+ #
+ # h = { "a" => 100, "b" => 200 }
+ # h.fetch("z")
+ #
+ # <em>produces:</em>
+ #
+ # prog.rb:2:in 'fetch': key not found (KeyError)
+ # from prog.rb:2
+ #
+
+ def fetch(key, none=NONE, &block)
+ unless self.key?(key)
+ if block
+ block.call(key)
+ elsif none != NONE
+ none
+ else
+ raise KeyError, "Key not found: #{key}"
+ end
+ else
+ self[key]
+ end
+ end
+
+ ##
+ # call-seq:
+ # hsh.delete_if {| key, value | block } -> hsh
+ # hsh.delete_if -> an_enumerator
+ #
+ # Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
+ # evaluates to <code>true</code>.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300 }
+ # h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}
+ #
+
+ def delete_if(&block)
+ return to_enum :delete_if unless block
+
+ self.each do |k, v|
+ self.delete(k) if block.call(k, v)
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # hash.flatten -> an_array
+ # hash.flatten(level) -> an_array
+ #
+ # Returns a new array that is a one-dimensional flattening of this
+ # hash. That is, for every key or value that is an array, extract
+ # its elements into the new array. Unlike Array#flatten, this
+ # method does not flatten recursively by default. The optional
+ # <i>level</i> argument determines the level of recursion to flatten.
+ #
+ # a = {1=> "one", 2 => [2,"two"], 3 => "three"}
+ # a.flatten # => [1, "one", 2, [2, "two"], 3, "three"]
+ # a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
+ #
+
+ def flatten(level=1)
+ self.to_a.flatten(level)
+ end
+
+ ##
+ # call-seq:
+ # hsh.invert -> new_hash
+ #
+ # Returns a new hash created by using <i>hsh</i>'s values as keys, and
+ # the keys as values.
+ #
+ # h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
+ # h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
+ #
+
+ def invert
+ h = self.class.new
+ self.each {|k, v| h[v] = k }
+ h
+ end
+
+ ##
+ # call-seq:
+ # hsh.keep_if {| key, value | block } -> hsh
+ # hsh.keep_if -> an_enumerator
+ #
+ # Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
+ # evaluates to false.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+
+ def keep_if(&block)
+ return to_enum :keep_if unless block
+
+ keys = []
+ self.each do |k, v|
+ unless block.call([k, v])
+ self.delete(k)
+ end
+ end
+ self
+ end
+
+ ##
+ # call-seq:
+ # hsh.key(value) -> key
+ #
+ # Returns the key of an occurrence of a given value. If the value is
+ # not found, returns <code>nil</code>.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
+ # h.key(200) #=> "b"
+ # h.key(300) #=> "c"
+ # h.key(999) #=> nil
+ #
+
+ def key(val)
+ self.each do |k, v|
+ return k if v == val
+ end
+ nil
+ end
+
+ ##
+ # call-seq:
+ # hsh.to_h -> hsh or new_hash
+ #
+ # Returns +self+. If called on a subclass of Hash, converts
+ # the receiver to a Hash object.
+ #
+ def to_h
+ self
+ end
+
+ ##
+ # call-seq:
+ # hash < other -> true or false
+ #
+ # Returns <code>true</code> if <i>hash</i> is subset of
+ # <i>other</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 < h2 #=> true
+ # h2 < h1 #=> false
+ # h1 < h1 #=> false
+ #
+ def <(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size < hash.size and all? {|key, val|
+ hash.key?(key) and hash[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hash <= other -> true or false
+ #
+ # Returns <code>true</code> if <i>hash</i> is subset of
+ # <i>other</i> or equals to <i>other</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 <= h2 #=> true
+ # h2 <= h1 #=> false
+ # h1 <= h1 #=> true
+ #
+ def <=(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size <= hash.size and all? {|key, val|
+ hash.key?(key) and hash[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hash > other -> true or false
+ #
+ # Returns <code>true</code> if <i>other</i> is subset of
+ # <i>hash</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 > h2 #=> false
+ # h2 > h1 #=> true
+ # h1 > h1 #=> false
+ #
+ def >(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size > hash.size and hash.all? {|key, val|
+ key?(key) and self[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hash >= other -> true or false
+ #
+ # Returns <code>true</code> if <i>other</i> is subset of
+ # <i>hash</i> or equals to <i>hash</i>.
+ #
+ # h1 = {a:1, b:2}
+ # h2 = {a:1, b:2, c:3}
+ # h1 >= h2 #=> false
+ # h2 >= h1 #=> true
+ # h1 >= h1 #=> true
+ #
+ def >=(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ raise TypeError, "can't convert #{hash.class} to Hash"
+ end
+ size >= hash.size and hash.all? {|key, val|
+ key?(key) and self[key] == val
+ }
+ end
+
+ ##
+ # call-seq:
+ # hsh.dig(key,...) -> object
+ #
+ # Extracts the nested value specified by the sequence of <i>key</i>
+ # objects by calling +dig+ at each step, returning +nil+ if any
+ # intermediate step is +nil+.
+ #
+ def dig(idx,*args)
+ n = self[idx]
+ if args.size > 0
+ n&.dig(*args)
+ else
+ n
+ end
+ end
+
+ ##
+ # call-seq:
+ # hsh.transform_keys {|key| block } -> new_hash
+ # hsh.transform_keys -> an_enumerator
+ #
+ # Returns a new hash, with the keys computed from running the block
+ # once for each key in the hash, and the values unchanged.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ def transform_keys(&block)
+ return to_enum :transform_keys unless block
+ hash = {}
+ self.keys.each do |k|
+ new_key = block.call(k)
+ hash[new_key] = self[k]
+ end
+ hash
+ end
+ ##
+ # call-seq:
+ # hsh.transform_keys! {|key| block } -> hsh
+ # hsh.transform_keys! -> an_enumerator
+ #
+ # Invokes the given block once for each key in <i>hsh</i>, replacing it
+ # with the new key returned by the block, and then returns <i>hsh</i>.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ def transform_keys!(&block)
+ return to_enum :transform_keys! unless block
+ self.keys.each do |k|
+ value = self[k]
+ new_key = block.call(k)
+ self.__delete(k)
+ self[new_key] = value
+ end
+ self
+ end
+ ##
+ # call-seq:
+ # hsh.transform_values {|value| block } -> new_hash
+ # hsh.transform_values -> an_enumerator
+ #
+ # Returns a new hash with the results of running the block once for
+ # every value.
+ # This method does not change the keys.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ def transform_values(&b)
+ return to_enum :transform_values unless block_given?
+ hash = {}
+ self.keys.each do |k|
+ hash[k] = yield(self[k])
+ end
+ hash
+ end
+ ##
+ # call-seq:
+ # hsh.transform_values! {|key| block } -> hsh
+ # hsh.transform_values! -> an_enumerator
+ #
+ # Invokes the given block once for each value in the hash, replacing
+ # with the new value returned by the block, and then returns <i>hsh</i>.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ def transform_values!(&b)
+ return to_enum :transform_values! unless block_given?
+ self.keys.each do |k|
+ self[k] = yield(self[k])
+ end
+ self
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c
new file mode 100644
index 00000000..952f2eb6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c
@@ -0,0 +1,88 @@
+/*
+** hash.c - Hash class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/hash.h>
+
+/*
+ * call-seq:
+ * hsh.values_at(key, ...) -> array
+ *
+ * Return an array containing the values associated with the given keys.
+ * Also see <code>Hash.select</code>.
+ *
+ * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
+ * h.values_at("cow", "cat") #=> ["bovine", "feline"]
+ */
+
+static mrb_value
+hash_values_at(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value *argv, result;
+ mrb_int argc, i;
+ int ai;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ result = mrb_ary_new_capa(mrb, argc);
+ ai = mrb_gc_arena_save(mrb);
+ for (i = 0; i < argc; i++) {
+ mrb_ary_push(mrb, result, mrb_hash_get(mrb, hash, argv[i]));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ return result;
+}
+
+/*
+ * call-seq:
+ * hsh.compact! -> hsh
+ *
+ * Removes all nil values from the hash. Returns the hash.
+ *
+ * h = { a: 1, b: false, c: nil }
+ * h.compact! #=> { a: 1, b: false }
+ */
+static mrb_value
+hash_compact_bang(mrb_state *mrb, mrb_value hash)
+{
+ khiter_t k;
+ khash_t(ht) *h = RHASH_TBL(hash);
+ mrb_int n = -1;
+
+ if (!h) return mrb_nil_value();
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ mrb_value val = kh_value(h, k).v;
+ khiter_t k2;
+
+ if (mrb_nil_p(val)) {
+ kh_del(ht, mrb, h, k);
+ n = kh_value(h, k).n;
+ for (k2 = kh_begin(h); k2 != kh_end(h); k2++) {
+ if (!kh_exist(h, k2)) continue;
+ if (kh_value(h, k2).n > n) kh_value(h, k2).n--;
+ }
+ }
+ }
+ }
+ if (n < 0) return mrb_nil_value();
+ return hash;
+}
+
+void
+mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
+{
+ struct RClass *h;
+
+ h = mrb->hash_class;
+ mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY());
+ mrb_define_method(mrb, h, "compact!", hash_compact_bang, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_hash_ext_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/test/hash.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/test/hash.rb
new file mode 100644
index 00000000..ca4e346f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-hash-ext/test/hash.rb
@@ -0,0 +1,294 @@
+##
+# Hash(Ext) Test
+
+assert('Hash.[] Hash') do
+ a = Hash['a_key' => 'a_value']
+
+ assert_equal({'a_key' => 'a_value'}, a)
+end
+
+assert('Hash.[] [ [ ["b_key", "b_value" ] ] ]') do
+ a = Hash[ [ ['b_key', 'b_value'] ] ]
+
+ assert_equal({'b_key' => 'b_value'}, a)
+
+ a = Hash[ [ ] ]
+
+ assert_equal({}, a)
+
+ assert_raise(ArgumentError) do
+ Hash[ [ ['b_key', 'b_value', 'b_over'] ] ]
+ end
+
+ assert_raise(ArgumentError) do
+ Hash[ [ [] ] ]
+ end
+end
+
+assert('Hash.[] "c_key", "c_value"') do
+ a = Hash['c_key', 'c_value', 'd_key', 1]
+
+ assert_equal({'c_key' => 'c_value', 'd_key' => 1}, a)
+
+ a = Hash[]
+
+ assert_equal({}, a)
+
+ assert_raise(ArgumentError) do
+ Hash['d_key']
+ end
+end
+
+assert('Hash.[] for sub class') do
+ sub_hash_class = Class.new(Hash)
+ sub_hash = sub_hash_class[]
+ assert_equal(sub_hash_class, sub_hash.class)
+end
+
+assert('Hash.try_convert') do
+ assert_nil Hash.try_convert(nil)
+ assert_nil Hash.try_convert("{1=>2}")
+ assert_equal({1=>2}, Hash.try_convert({1=>2}))
+end
+
+assert('Hash#merge!') do
+ a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
+ b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }
+
+ result_1 = a.merge! b
+
+ a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
+ result_2 = a.merge!(b) do |key, original, new|
+ original
+ end
+
+ assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'XXX',
+ 'xyz_key' => 'xyz_value' }, result_1)
+ assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'cba_value',
+ 'xyz_key' => 'xyz_value' }, result_2)
+
+ assert_raise(TypeError) do
+ { 'abc_key' => 'abc_value' }.merge! "a"
+ end
+end
+
+assert('Hash#values_at') do
+ h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
+ assert_equal ["bovine", "feline"], h.values_at("cow", "cat")
+
+ keys = []
+ (0...1000).each { |v| keys.push "#{v}" }
+ h = Hash.new { |hash,k| hash[k] = k }
+ assert_equal keys, h.values_at(*keys)
+end
+
+assert('Hash#compact') do
+ h = { "cat" => "feline", "dog" => nil, "cow" => false }
+
+ assert_equal({ "cat" => "feline", "cow" => false }, h.compact)
+ assert_equal({ "cat" => "feline", "dog" => nil, "cow" => false }, h)
+end
+
+assert('Hash#compact!') do
+ h = { "cat" => "feline", "dog" => nil, "cow" => false }
+
+ h.compact!
+ assert_equal({ "cat" => "feline", "cow" => false }, h)
+end
+
+assert('Hash#fetch') do
+ h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
+ assert_equal "feline", h.fetch("cat")
+ assert_equal "mickey", h.fetch("mouse", "mickey")
+ assert_equal "minny", h.fetch("mouse"){"minny"}
+ assert_equal "mouse", h.fetch("mouse"){|k| k}
+ assert_raise(KeyError) do
+ h.fetch("gnu")
+ end
+end
+
+assert("Hash#delete_if") do
+ base = { 1 => 'one', 2 => false, true => 'true', 'cat' => 99 }
+ h1 = { 1 => 'one', 2 => false, true => 'true' }
+ h2 = { 2 => false, 'cat' => 99 }
+ h3 = { 2 => false }
+
+ h = base.dup
+ assert_equal(h, h.delete_if { false })
+ assert_equal({}, h.delete_if { true })
+
+ h = base.dup
+ assert_equal(h1, h.delete_if {|k,v| k.instance_of?(String) })
+ assert_equal(h1, h)
+
+ h = base.dup
+ assert_equal(h2, h.delete_if {|k,v| v.instance_of?(String) })
+ assert_equal(h2, h)
+
+ h = base.dup
+ assert_equal(h3, h.delete_if {|k,v| v })
+ assert_equal(h3, h)
+
+ h = base.dup
+ n = 0
+ h.delete_if {|*a|
+ n += 1
+ assert_equal(2, a.size)
+ assert_equal(base[a[0]], a[1])
+ h.shift
+ true
+ }
+ assert_equal(base.size, n)
+end
+
+assert("Hash#flatten") do
+ a = {1=> "one", 2 => [2,"two"], 3 => [3, ["three"]]}
+ assert_equal [1, "one", 2, [2, "two"], 3, [3, ["three"]]], a.flatten
+ assert_equal [[1, "one"], [2, [2, "two"]], [3, [3, ["three"]]]], a.flatten(0)
+ assert_equal [1, "one", 2, [2, "two"], 3, [3, ["three"]]], a.flatten(1)
+ assert_equal [1, "one", 2, 2, "two", 3, 3, ["three"]], a.flatten(2)
+ assert_equal [1, "one", 2, 2, "two", 3, 3, "three"], a.flatten(3)
+end
+
+assert("Hash#invert") do
+ h = { 1 => 'one', 2 => 'two', 3 => 'three',
+ true => 'true', nil => 'nil' }.invert
+ assert_equal 1, h['one']
+ assert_equal true, h['true']
+ assert_equal nil, h['nil']
+
+ h = { 'a' => 1, 'b' => 2, 'c' => 1 }.invert
+ assert_equal(2, h.length)
+ assert_include(%w[a c], h[1])
+ assert_equal('b', h[2])
+end
+
+assert("Hash#invert with sub class") do
+ sub_hash_class = Class.new(Hash)
+ sub_hash = sub_hash_class.new
+ assert_equal(sub_hash_class, sub_hash.invert.class)
+end
+
+assert("Hash#keep_if") do
+ h = { 1 => 2, 3 => 4, 5 => 6 }
+ assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
+ h = { 1 => 2, 3 => 4, 5 => 6 }
+ assert_equal({ 1 => 2, 3=> 4, 5 =>6} , h.keep_if { true })
+end
+
+assert("Hash#key") do
+ h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300, nil => 'nil', 'nil' => nil }
+ assert_equal "b", h.key(200)
+ assert_equal "c", h.key(300)
+ assert_nil h.key(999)
+ assert_nil h.key('nil')
+ assert_equal 'nil', h.key(nil)
+end
+
+assert("Hash#to_h") do
+ h = { "a" => 100, "b" => 200 }
+ assert_equal Hash, h.to_h.class
+ assert_equal h, h.to_h
+end
+
+assert('Hash#<') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_false(h1 < h1)
+ assert_true(h1 < h2)
+ assert_false(h2 < h1)
+ assert_false(h2 < h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_false(h1 < h1)
+ assert_false(h1 < h2)
+ assert_false(h2 < h1)
+ assert_false(h2 < h2)
+end
+
+assert('Hash#<=') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_true(h1 <= h1)
+ assert_true(h1 <= h2)
+ assert_false(h2 <= h1)
+ assert_true(h2 <= h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_true(h1 <= h1)
+ assert_false(h1 <= h2)
+ assert_false(h2 <= h1)
+ assert_true(h2 <= h2)
+end
+
+assert('Hash#>=') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_true(h1 >= h1)
+ assert_false(h1 >= h2)
+ assert_true(h2 >= h1)
+ assert_true(h2 >= h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_true(h1 >= h1)
+ assert_false(h1 >= h2)
+ assert_false(h2 >= h1)
+ assert_true(h2 >= h2)
+end
+
+assert('Hash#>') do
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
+
+ assert_false(h1 > h1)
+ assert_false(h1 > h2)
+ assert_true(h2 > h1)
+ assert_false(h2 > h2)
+
+ h1 = {a:1}
+ h2 = {a:2}
+
+ assert_false(h1 > h1)
+ assert_false(h1 > h2)
+ assert_false(h2 > h1)
+ assert_false(h2 > h2)
+end
+
+assert("Hash#dig") do
+ h = {a:{b:{c:1}}}
+ assert_equal(1, h.dig(:a, :b, :c))
+ assert_nil(h.dig(:d))
+end
+
+assert("Hash#transform_keys") do
+ h = {"1" => 100, "2" => 200}
+ assert_equal(h.transform_keys{|k| k+"!"},
+ {"1!" => 100, "2!" => 200})
+ assert_equal(h.transform_keys{|k|k.to_i},
+ {1 => 100, 2 => 200})
+ assert_equal(h.transform_keys.with_index{|k, i| "#{k}.#{i}"},
+ {"1.0" => 100, "2.1" => 200})
+ assert_equal(h.transform_keys!{|k|k.to_i}, h)
+ assert_equal(h, {1 => 100, 2 => 200})
+end
+
+assert("Hash#transform_values") do
+ h = {a: 1, b: 2, c: 3}
+ assert_equal(h.transform_values{|v| v * v + 1},
+ {a: 2, b: 5, c: 10})
+ assert_equal(h.transform_values{|v|v.to_s},
+ {a: "1", b: "2", c: "3"})
+ assert_equal(h.transform_values.with_index{|v, i| "#{v}.#{i}"},
+ {a: "1.0", b: "2.1", c: "3.2"})
+ assert_equal(h.transform_values!{|v|v.to_s}, h)
+ assert_equal(h, {a: "1", b: "2", c: "3"})
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/mrbgem.rake
new file mode 100644
index 00000000..91ad9f44
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-inline-struct') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'inline structure'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.c
new file mode 100644
index 00000000..0baaab61
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.c
@@ -0,0 +1,83 @@
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/string.h>
+#include <mruby/istruct.h>
+
+static mrb_value
+istruct_test_initialize(mrb_state *mrb, mrb_value self)
+{
+ char *string = (char*)mrb_istruct_ptr(self);
+ mrb_int size = mrb_istruct_size();
+ mrb_value object;
+ mrb_get_args(mrb, "o", &object);
+
+ if (mrb_float_p(object))
+ {
+ snprintf(string, size, "float(%.3f)", mrb_float(object));
+ }
+ else if (mrb_fixnum_p(object))
+ {
+ snprintf(string, size, "fixnum(%" MRB_PRId ")", mrb_fixnum(object));
+ }
+ else if (mrb_string_p(object))
+ {
+ snprintf(string, size, "string(%s)", mrb_string_value_cstr(mrb, &object));
+ }
+
+ string[size - 1] = 0; // force NULL at the end
+ return self;
+}
+
+static mrb_value
+istruct_test_to_s(mrb_state *mrb, mrb_value self)
+{
+ return mrb_str_new_cstr(mrb, (const char*)mrb_istruct_ptr(self));
+}
+
+static mrb_value
+istruct_test_length(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(mrb_istruct_size());
+}
+
+static mrb_value
+istruct_test_test_receive(mrb_state *mrb, mrb_value self)
+{
+ mrb_value object;
+ mrb_get_args(mrb, "o", &object);
+ if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
+ {
+ mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
+ }
+ return mrb_bool_value(((char*)mrb_istruct_ptr(object))[0] == 's');
+}
+
+static mrb_value
+istruct_test_test_receive_direct(mrb_state *mrb, mrb_value self)
+{
+ char *ptr;
+ mrb_get_args(mrb, "I", &ptr);
+ return mrb_bool_value(ptr[0] == 's');
+}
+
+static mrb_value
+istruct_test_mutate(mrb_state *mrb, mrb_value self)
+{
+ char *ptr = (char*)mrb_istruct_ptr(self);
+ memcpy(ptr, "mutate", 6);
+ return mrb_nil_value();
+}
+
+void mrb_mruby_inline_struct_gem_test(mrb_state *mrb)
+{
+ struct RClass *cls;
+
+ cls = mrb_define_class(mrb, "InlineStructTest", mrb->object_class);
+ MRB_SET_INSTANCE_TT(cls, MRB_TT_ISTRUCT);
+ mrb_define_method(mrb, cls, "initialize", istruct_test_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, cls, "to_s", istruct_test_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, cls, "mutate", istruct_test_mutate, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, cls, "length", istruct_test_length, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, cls, "test_receive", istruct_test_test_receive, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, cls, "test_receive_direct", istruct_test_test_receive_direct, MRB_ARGS_REQ(1));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.rb
new file mode 100644
index 00000000..49585923
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-inline-struct/test/inline.rb
@@ -0,0 +1,151 @@
+##
+# InlineStruct Test
+
+class InlineStructTest
+ def extra_method
+ :ok
+ end
+
+ def test_ivar_set
+ @var = :ivar
+ end
+
+ def test_ivar_get
+ @vat
+ end
+end
+
+assert('InlineStructTest#dup') do
+ obj = InlineStructTest.new(1)
+ assert_equal obj.to_s, 'fixnum(1)'
+ assert_equal obj.dup.to_s, 'fixnum(1)'
+end
+
+assert('InlineStructTest#clone') do
+ obj = InlineStructTest.new(1)
+ assert_equal obj.to_s, 'fixnum(1)'
+ assert_equal obj.clone.to_s, 'fixnum(1)'
+end
+
+assert('InlineStruct#object_id') do
+ obj1 = InlineStructTest.new(1)
+ obj2 = InlineStructTest.new(1)
+ assert_not_equal obj1, obj2
+ assert_not_equal obj1.object_id, obj2.object_id
+ assert_not_equal obj1.object_id, obj1.dup.object_id
+ assert_not_equal obj1.object_id, obj1.clone.object_id
+end
+
+assert('InlineStructTest#mutate (dup)') do
+ obj1 = InlineStructTest.new("foo")
+ assert_equal obj1.to_s, "string(foo)"
+ obj2 = obj1.dup
+ assert_equal obj2.to_s, "string(foo)"
+ obj1.mutate
+ assert_equal obj1.to_s, "mutate(foo)"
+ assert_equal obj2.to_s, "string(foo)"
+end
+
+assert('InlineStructTest#mutate (clone)') do
+ obj1 = InlineStructTest.new("foo")
+ assert_equal obj1.to_s, "string(foo)"
+ obj2 = obj1.clone
+ assert_equal obj2.to_s, "string(foo)"
+ obj1.mutate
+ assert_equal obj1.to_s, "mutate(foo)"
+ assert_equal obj2.to_s, "string(foo)"
+end
+
+assert('InlineStructTest#test_receive(string)') do
+ assert_equal InlineStructTest.test_receive(InlineStructTest.new('a')), true
+end
+
+assert('InlineStructTest#test_receive(float)') do
+ assert_equal InlineStructTest.test_receive(InlineStructTest.new(1.25)), false
+end
+
+assert('InlineStructTest#test_receive(invalid object)') do
+ assert_raise(TypeError) do
+ InlineStructTest.test_receive([])
+ end
+end
+
+assert('InlineStructTest#test_receive(string)') do
+ assert_equal InlineStructTest.test_receive_direct(InlineStructTest.new('a')), true
+end
+
+assert('InlineStructTest#test_receive(float)') do
+ assert_equal InlineStructTest.test_receive_direct(InlineStructTest.new(1.25)), false
+end
+
+assert('InlineStructTest#test_receive(invalid object)') do
+ assert_raise(TypeError) do
+ InlineStructTest.test_receive_direct([])
+ end
+end
+
+assert('InlineStructTest#extra_method') do
+ assert_equal InlineStructTest.new(1).extra_method, :ok
+end
+
+assert('InlineStructTest instance variable') do
+ obj = InlineStructTest.new(1)
+ assert_raise(ArgumentError) do
+ obj.test_ivar_set
+ end
+ assert_equal obj.test_ivar_get, nil
+end
+
+# 64-bit mode
+if InlineStructTest.length == 24
+ assert('InlineStructTest length [64 bit]') do
+ assert_equal InlineStructTest.length, 3 * 8
+ end
+
+ assert('InlineStructTest w/float [64 bit]') do
+ obj = InlineStructTest.new(1.25)
+ assert_equal obj.to_s, "float(1.250)"
+ end
+
+ assert('InlineStructTest w/fixnum [64 bit]') do
+ obj = InlineStructTest.new(42)
+ assert_equal obj.to_s, "fixnum(42)"
+ end
+
+ assert('InlineStructTest w/string [64 bit]') do
+ obj = InlineStructTest.new("hello")
+ assert_equal obj.to_s, "string(hello)"
+ end
+
+ assert('InlineStructTest w/long string [64 bit]') do
+ obj = InlineStructTest.new("this won't fit in 3 * 8 bytes available for the structure")
+ assert_equal obj.to_s, "string(this won't fit i"
+ end
+end
+
+# 32-bit mode
+if InlineStructTest.length == 12
+ assert('InlineStructTest length [32 bit]') do
+ assert_equal InlineStructTest.length, 3 * 4
+ end
+
+ assert('InlineStructTest w/float [32 bit]') do
+ obj = InlineStructTest.new(1.25)
+ assert_equal obj.to_s, "float(1.250"
+ end
+
+ assert('InlineStructTest w/fixnum [32 bit]') do
+ obj = InlineStructTest.new(42)
+ assert_equal obj.to_s, "fixnum(42)"
+ end
+
+ assert('InlineStructTest w/string [32 bit]') do
+ obj = InlineStructTest.new("hello")
+ assert_equal obj.to_s, "string(hell"
+ end
+
+ assert('InlineStructTest w/long string [32 bit]') do
+ obj = InlineStructTest.new("this won't fit in 3 * 4 bytes available for the structure")
+ assert_equal obj.to_s, "string(this"
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake
new file mode 100644
index 00000000..fcb3a83b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-kernel-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Kernel module extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/src/kernel.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/src/kernel.c
new file mode 100644
index 00000000..7e6fa28b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/src/kernel.c
@@ -0,0 +1,243 @@
+#include <mruby.h>
+#include <mruby/error.h>
+#include <mruby/array.h>
+#include <mruby/hash.h>
+#include <mruby/range.h>
+
+static mrb_value
+mrb_f_caller(mrb_state *mrb, mrb_value self)
+{
+ mrb_value bt, v, length;
+ mrb_int bt_len, argc, lev, n;
+
+ bt = mrb_get_backtrace(mrb);
+ bt_len = RARRAY_LEN(bt);
+ argc = mrb_get_args(mrb, "|oo", &v, &length);
+
+ switch (argc) {
+ case 0:
+ lev = 1;
+ n = bt_len - lev;
+ break;
+ case 1:
+ if (mrb_type(v) == MRB_TT_RANGE) {
+ mrb_int beg, len;
+ if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len, TRUE) == 1) {
+ lev = beg;
+ n = len;
+ }
+ else {
+ return mrb_nil_value();
+ }
+ }
+ else {
+ v = mrb_to_int(mrb, v);
+ lev = mrb_fixnum(v);
+ if (lev < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v);
+ }
+ n = bt_len - lev;
+ }
+ break;
+ case 2:
+ lev = mrb_fixnum(mrb_to_int(mrb, v));
+ n = mrb_fixnum(mrb_to_int(mrb, length));
+ if (lev < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v);
+ }
+ if (n < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%S)", length);
+ }
+ break;
+ default:
+ lev = n = 0;
+ break;
+ }
+
+ if (n == 0) {
+ return mrb_ary_new(mrb);
+ }
+
+ return mrb_funcall(mrb, bt, "[]", 2, mrb_fixnum_value(lev), mrb_fixnum_value(n));
+}
+
+/*
+ * call-seq:
+ * __method__ -> symbol
+ *
+ * Returns the name at the definition of the current method as a
+ * Symbol.
+ * If called outside of a method, it returns <code>nil</code>.
+ *
+ */
+static mrb_value
+mrb_f_method(mrb_state *mrb, mrb_value self)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+ ci--;
+ if (ci->mid)
+ return mrb_symbol_value(ci->mid);
+ else
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * Integer(arg,base=0) -> integer
+ *
+ * Converts <i>arg</i> to a <code>Fixnum</code>.
+ * Numeric types are converted directly (with floating point numbers
+ * being truncated). <i>base</i> (0, or between 2 and 36) is a base for
+ * integer string representation. If <i>arg</i> is a <code>String</code>,
+ * when <i>base</i> is omitted or equals to zero, radix indicators
+ * (<code>0</code>, <code>0b</code>, and <code>0x</code>) are honored.
+ * In any case, strings should be strictly conformed to numeric
+ * representation. This behavior is different from that of
+ * <code>String#to_i</code>. Non string values will be converted using
+ * <code>to_int</code>, and <code>to_i</code>. Passing <code>nil</code>
+ * raises a TypeError.
+ *
+ * Integer(123.999) #=> 123
+ * Integer("0x1a") #=> 26
+ * Integer(Time.new) #=> 1204973019
+ * Integer("0930", 10) #=> 930
+ * Integer("111", 2) #=> 7
+ * Integer(nil) #=> TypeError
+ */
+static mrb_value
+mrb_f_integer(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+ mrb_int base = 0;
+
+ mrb_get_args(mrb, "o|i", &arg, &base);
+ return mrb_convert_to_integer(mrb, arg, base);
+}
+
+/*
+ * call-seq:
+ * Float(arg) -> float
+ *
+ * Returns <i>arg</i> converted to a float. Numeric types are converted
+ * directly, the rest are converted using <i>arg</i>.to_f.
+ *
+ * Float(1) #=> 1.0
+ * Float(123.456) #=> 123.456
+ * Float("123.456") #=> 123.456
+ * Float(nil) #=> TypeError
+ */
+static mrb_value
+mrb_f_float(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ return mrb_Float(mrb, arg);
+}
+
+/*
+ * call-seq:
+ * String(arg) -> string
+ *
+ * Returns <i>arg</i> as an <code>String</code>.
+ *
+ * First tries to call its <code>to_str</code> method, then its to_s method.
+ *
+ * String(self) #=> "main"
+ * String(self.class) #=> "Object"
+ * String(123456) #=> "123456"
+ */
+static mrb_value
+mrb_f_string(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg, tmp;
+
+ mrb_get_args(mrb, "o", &arg);
+ tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_str");
+ if (mrb_nil_p(tmp)) {
+ tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s");
+ }
+ return tmp;
+}
+
+/*
+ * call-seq:
+ * Array(arg) -> array
+ *
+ * Returns +arg+ as an Array.
+ *
+ * First tries to call Array#to_ary on +arg+, then Array#to_a.
+ *
+ * Array(1..5) #=> [1, 2, 3, 4, 5]
+ *
+ */
+static mrb_value
+mrb_f_array(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg, tmp;
+
+ mrb_get_args(mrb, "o", &arg);
+ tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_ary");
+ if (mrb_nil_p(tmp)) {
+ tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a");
+ }
+ if (mrb_nil_p(tmp)) {
+ return mrb_ary_new_from_values(mrb, 1, &arg);
+ }
+
+ return tmp;
+}
+
+/*
+ * call-seq:
+ * Hash(arg) -> hash
+ *
+ * Converts <i>arg</i> to a <code>Hash</code> by calling
+ * <i>arg</i><code>.to_hash</code>. Returns an empty <code>Hash</code> when
+ * <i>arg</i> is <tt>nil</tt> or <tt>[]</tt>.
+ *
+ * Hash([]) #=> {}
+ * Hash(nil) #=> {}
+ * Hash(key: :value) #=> {:key => :value}
+ * Hash([1, 2, 3]) #=> TypeError
+ *
+ */
+static mrb_value
+mrb_f_hash(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg, tmp;
+
+ mrb_get_args(mrb, "o", &arg);
+ if (mrb_nil_p(arg)) {
+ return mrb_hash_new(mrb);
+ }
+ tmp = mrb_check_convert_type(mrb, arg, MRB_TT_HASH, "Hash", "to_hash");
+ if (mrb_nil_p(tmp)) {
+ if (mrb_array_p(arg) && RARRAY_LEN(arg) == 0) {
+ return mrb_hash_new(mrb);
+ }
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into Hash",
+ mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, arg)));
+ }
+ return tmp;
+}
+
+void
+mrb_mruby_kernel_ext_gem_init(mrb_state *mrb)
+{
+ struct RClass *krn = mrb->kernel_module;
+
+ mrb_define_module_function(mrb, krn, "fail", mrb_f_raise, MRB_ARGS_OPT(2));
+ mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_OPT(2));
+ mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
+ mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY());
+ mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, krn, "String", mrb_f_string, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, krn, "Array", mrb_f_array, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, krn, "Hash", mrb_f_hash, MRB_ARGS_REQ(1));
+}
+
+void
+mrb_mruby_kernel_ext_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb
new file mode 100644
index 00000000..89cedaf2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb
@@ -0,0 +1,86 @@
+assert('Kernel.fail, Kernel#fail') do
+ assert_raise(RuntimeError) { fail }
+ assert_raise(RuntimeError) { Kernel.fail }
+end
+
+assert('Kernel.caller, Kernel#caller') do
+ skip "backtrace isn't available" if caller(0).empty?
+
+ caller_lineno = __LINE__ + 3
+ c = Class.new do
+ def foo(*args)
+ caller(*args)
+ end
+
+ def bar(*args)
+ foo(*args)
+ end
+
+ def baz(*args)
+ bar(*args)
+ end
+ end
+ assert_equal "kernel.rb:#{caller_lineno}:in foo", c.new.baz(0)[0][-19..-1]
+ assert_equal "bar", c.new.baz[0][-3..-1]
+ assert_equal "foo", c.new.baz(0)[0][-3..-1]
+ assert_equal "bar", c.new.baz(1)[0][-3..-1]
+ assert_equal "baz", c.new.baz(2)[0][-3..-1]
+ assert_equal ["foo", "bar"], c.new.baz(0, 2).map { |i| i[-3..-1] }
+ assert_equal ["bar", "baz"], c.new.baz(1..2).map { |i| i[-3..-1] }
+ assert_nil c.new.baz(10..20)
+ assert_raise(ArgumentError) { c.new.baz(-1) }
+ assert_raise(ArgumentError) { c.new.baz(-1, 1) }
+ assert_raise(ArgumentError) { c.new.baz(1, -1) }
+ assert_raise(TypeError) { c.new.baz(nil) }
+end
+
+assert('Kernel#__method__') do
+ assert_equal(:m, Class.new {def m; __method__; end}.new.m)
+ assert_equal(:m, Class.new {define_method(:m) {__method__}}.new.m)
+ c = Class.new do
+ [:m1, :m2].each do |m|
+ define_method(m) do
+ __method__
+ end
+ end
+ end
+ assert_equal(:m1, c.new.m1)
+ assert_equal(:m2, c.new.m2)
+end
+
+assert('Kernel#Integer') do
+ assert_equal(123, Integer(123.999))
+ assert_equal(26, Integer("0x1a"))
+ assert_equal(930, Integer("0930", 10))
+ assert_equal(7, Integer("111", 2))
+ assert_equal(0, Integer("0"))
+ assert_equal(0, Integer("00000"))
+ assert_raise(TypeError) { Integer(nil) }
+end
+
+assert('Kernel#Float') do
+ assert_equal(1.0, Float(1))
+ assert_equal(123.456, Float(123.456))
+ assert_equal(123.456, Float("123.456"))
+ assert_raise(TypeError) { Float(nil) }
+end
+
+assert('Kernel#String') do
+ assert_equal("main", String(self))
+ assert_equal("Object", String(self.class))
+ assert_equal("123456", String(123456))
+end
+
+assert('Kernel#Array') do
+ assert_equal([1], Kernel.Array(1))
+ assert_equal([1, 2, 3, 4, 5], Kernel.Array([1, 2, 3, 4, 5]))
+ assert_equal([1, 2, 3, 4, 5], Kernel.Array(1..5))
+ assert_equal([[:a, 1], [:b, 2], [:c, 3]], Kernel.Array({a:1, b:2, c:3}))
+end
+
+assert('Kernel#Hash') do
+ assert_equal({}, Hash([]))
+ assert_equal({}, Hash(nil))
+ assert_equal({:key => :value}, Hash(key: :value))
+ assert_raise(TypeError) { Hash([1, 2, 3]) }
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/mrbgem.rake
new file mode 100644
index 00000000..66eb5c8d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-math') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'standard Math module'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/src/math.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/src/math.c
new file mode 100644
index 00000000..7302b92d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/src/math.c
@@ -0,0 +1,783 @@
+/*
+** math.c - Math module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/array.h>
+
+#include <math.h>
+
+static void
+domain_error(mrb_state *mrb, const char *func)
+{
+ struct RClass *math = mrb_module_get(mrb, "Math");
+ struct RClass *domainerror = mrb_class_get_under(mrb, math, "DomainError");
+ mrb_value str = mrb_str_new_cstr(mrb, func);
+ mrb_raisef(mrb, domainerror, "Numerical argument is out of domain - %S", str);
+}
+
+/* math functions not provided by Microsoft Visual C++ 2012 or older */
+#if defined _MSC_VER && _MSC_VER <= 1700
+
+#include <float.h>
+
+#define MATH_TOLERANCE 1E-12
+
+double
+asinh(double x)
+{
+ double xa, ya, y;
+
+ /* Basic formula loses precision for x < 0, but asinh is an odd function */
+ xa = fabs(x);
+ if (xa > 3.16227E+18) {
+ /* Prevent x*x from overflowing; basic formula reduces to log(2*x) */
+ ya = log(xa) + 0.69314718055994530942;
+ }
+ else {
+ /* Basic formula for asinh */
+ ya = log(xa + sqrt(xa*xa + 1.0));
+ }
+
+ y = _copysign(ya, x);
+ return y;
+}
+
+double
+acosh(double x)
+{
+ double y;
+
+ if (x > 3.16227E+18) {
+ /* Prevent x*x from overflowing; basic formula reduces to log(2*x) */
+ y = log(x) + 0.69314718055994530942;
+ }
+ else {
+ /* Basic formula for acosh */
+ y = log(x + sqrt(x*x - 1.0));
+ }
+
+ return y;
+}
+
+double
+atanh(double x)
+{
+ double y;
+
+ if (fabs(x) < 1E-2) {
+ /* The sums 1+x and 1-x lose precision for small x. Use the polynomial
+ instead. */
+ double x2 = x * x;
+ y = x*(1.0 + x2*(1.0/3.0 + x2*(1.0/5.0 + x2*(1.0/7.0))));
+ }
+ else {
+ /* Basic formula for atanh */
+ y = 0.5 * (log(1.0+x) - log(1.0-x));
+ }
+
+ return y;
+}
+
+double
+cbrt(double x)
+{
+ double xa, ya, y;
+
+ /* pow(x, y) is undefined for x < 0 and y not an integer, but cbrt is an
+ odd function */
+ xa = fabs(x);
+ ya = pow(xa, 1.0/3.0);
+ y = _copysign(ya, x);
+ return y;
+}
+
+/* Declaration of complementary Error function */
+double
+erfc(double x);
+
+/*
+** Implementations of error functions
+** credits to http://www.digitalmars.com/archives/cplusplus/3634.html
+*/
+
+/* Implementation of Error function */
+double
+erf(double x)
+{
+ static const double two_sqrtpi = 1.128379167095512574;
+ double sum = x;
+ double term = x;
+ double xsqr = x*x;
+ int j= 1;
+ if (fabs(x) > 2.2) {
+ return 1.0 - erfc(x);
+ }
+ do {
+ term *= xsqr/j;
+ sum -= term/(2*j+1);
+ ++j;
+ term *= xsqr/j;
+ sum += term/(2*j+1);
+ ++j;
+ } while (fabs(term/sum) > MATH_TOLERANCE);
+ return two_sqrtpi*sum;
+}
+
+/* Implementation of complementary Error function */
+double
+erfc(double x)
+{
+ static const double one_sqrtpi= 0.564189583547756287;
+ double a = 1;
+ double b = x;
+ double c = x;
+ double d = x*x+0.5;
+ double q1;
+ double q2 = b/d;
+ double n = 1.0;
+ double t;
+ if (fabs(x) < 2.2) {
+ return 1.0 - erf(x);
+ }
+ if (x < 0.0) { /*signbit(x)*/
+ return 2.0 - erfc(-x);
+ }
+ do {
+ t = a*n+b*x;
+ a = b;
+ b = t;
+ t = c*n+d*x;
+ c = d;
+ d = t;
+ n += 0.5;
+ q1 = q2;
+ q2 = b/d;
+ } while (fabs(q1-q2)/q2 > MATH_TOLERANCE);
+ return one_sqrtpi*exp(-x*x)*q2;
+}
+
+#endif
+
+#if (defined _MSC_VER && _MSC_VER < 1800) || defined __ANDROID__ || (defined __FreeBSD__ && __FreeBSD_version < 803000)
+
+double
+log2(double x)
+{
+ return log10(x)/log10(2.0);
+}
+
+#endif
+
+/*
+ TRIGONOMETRIC FUNCTIONS
+*/
+
+/*
+ * call-seq:
+ * Math.sin(x) -> float
+ *
+ * Computes the sine of <i>x</i> (expressed in radians). Returns
+ * -1..1.
+ */
+static mrb_value
+math_sin(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = sin(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.cos(x) -> float
+ *
+ * Computes the cosine of <i>x</i> (expressed in radians). Returns
+ * -1..1.
+ */
+static mrb_value
+math_cos(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = cos(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.tan(x) -> float
+ *
+ * Returns the tangent of <i>x</i> (expressed in radians).
+ */
+static mrb_value
+math_tan(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = tan(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ INVERSE TRIGONOMETRIC FUNCTIONS
+*/
+
+/*
+ * call-seq:
+ * Math.asin(x) -> float
+ *
+ * Computes the arc sine of <i>x</i>.
+ * @return computed value between `-(PI/2)` and `(PI/2)`.
+ */
+static mrb_value
+math_asin(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < -1.0 || x > 1.0) {
+ domain_error(mrb, "asin");
+ }
+ x = asin(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.acos(x) -> float
+ *
+ * Computes the arc cosine of <i>x</i>. Returns 0..PI.
+ */
+static mrb_value
+math_acos(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < -1.0 || x > 1.0) {
+ domain_error(mrb, "acos");
+ }
+ x = acos(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.atan(x) -> float
+ *
+ * Computes the arc tangent of <i>x</i>. Returns `-(PI/2) .. (PI/2)`.
+ */
+static mrb_value
+math_atan(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = atan(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.atan2(y, x) -> float
+ *
+ * Computes the arc tangent given <i>y</i> and <i>x</i>. Returns
+ * -PI..PI.
+ *
+ * Math.atan2(-0.0, -1.0) #=> -3.141592653589793
+ * Math.atan2(-1.0, -1.0) #=> -2.356194490192345
+ * Math.atan2(-1.0, 0.0) #=> -1.5707963267948966
+ * Math.atan2(-1.0, 1.0) #=> -0.7853981633974483
+ * Math.atan2(-0.0, 1.0) #=> -0.0
+ * Math.atan2(0.0, 1.0) #=> 0.0
+ * Math.atan2(1.0, 1.0) #=> 0.7853981633974483
+ * Math.atan2(1.0, 0.0) #=> 1.5707963267948966
+ * Math.atan2(1.0, -1.0) #=> 2.356194490192345
+ * Math.atan2(0.0, -1.0) #=> 3.141592653589793
+ *
+ */
+static mrb_value
+math_atan2(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x, y;
+
+ mrb_get_args(mrb, "ff", &x, &y);
+ x = atan2(x, y);
+
+ return mrb_float_value(mrb, x);
+}
+
+
+
+/*
+ HYPERBOLIC TRIG FUNCTIONS
+*/
+/*
+ * call-seq:
+ * Math.sinh(x) -> float
+ *
+ * Computes the hyperbolic sine of <i>x</i> (expressed in
+ * radians).
+ */
+static mrb_value
+math_sinh(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = sinh(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.cosh(x) -> float
+ *
+ * Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
+ */
+static mrb_value
+math_cosh(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = cosh(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.tanh() -> float
+ *
+ * Computes the hyperbolic tangent of <i>x</i> (expressed in
+ * radians).
+ */
+static mrb_value
+math_tanh(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = tanh(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+
+/*
+ INVERSE HYPERBOLIC TRIG FUNCTIONS
+*/
+
+/*
+ * call-seq:
+ * Math.asinh(x) -> float
+ *
+ * Computes the inverse hyperbolic sine of <i>x</i>.
+ */
+static mrb_value
+math_asinh(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+
+ x = asinh(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.acosh(x) -> float
+ *
+ * Computes the inverse hyperbolic cosine of <i>x</i>.
+ */
+static mrb_value
+math_acosh(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < 1.0) {
+ domain_error(mrb, "acosh");
+ }
+ x = acosh(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.atanh(x) -> float
+ *
+ * Computes the inverse hyperbolic tangent of <i>x</i>.
+ */
+static mrb_value
+math_atanh(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < -1.0 || x > 1.0) {
+ domain_error(mrb, "atanh");
+ }
+ x = atanh(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ EXPONENTIALS AND LOGARITHMS
+*/
+
+/*
+ * call-seq:
+ * Math.exp(x) -> float
+ *
+ * Returns e**x.
+ *
+ * Math.exp(0) #=> 1.0
+ * Math.exp(1) #=> 2.718281828459045
+ * Math.exp(1.5) #=> 4.4816890703380645
+ *
+ */
+static mrb_value
+math_exp(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = exp(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.log(numeric) -> float
+ * Math.log(num,base) -> float
+ *
+ * Returns the natural logarithm of <i>numeric</i>.
+ * If additional second argument is given, it will be the base
+ * of logarithm.
+ *
+ * Math.log(1) #=> 0.0
+ * Math.log(Math::E) #=> 1.0
+ * Math.log(Math::E**3) #=> 3.0
+ * Math.log(12,3) #=> 2.2618595071429146
+ *
+ */
+static mrb_value
+math_log(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x, base;
+ int argc;
+
+ argc = mrb_get_args(mrb, "f|f", &x, &base);
+ if (x < 0.0) {
+ domain_error(mrb, "log");
+ }
+ x = log(x);
+ if (argc == 2) {
+ if (base < 0.0) {
+ domain_error(mrb, "log");
+ }
+ x /= log(base);
+ }
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.log2(numeric) -> float
+ *
+ * Returns the base 2 logarithm of <i>numeric</i>.
+ *
+ * Math.log2(1) #=> 0.0
+ * Math.log2(2) #=> 1.0
+ * Math.log2(32768) #=> 15.0
+ * Math.log2(65536) #=> 16.0
+ *
+ */
+static mrb_value
+math_log2(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < 0.0) {
+ domain_error(mrb, "log2");
+ }
+ x = log2(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.log10(numeric) -> float
+ *
+ * Returns the base 10 logarithm of <i>numeric</i>.
+ *
+ * Math.log10(1) #=> 0.0
+ * Math.log10(10) #=> 1.0
+ * Math.log10(10**100) #=> 100.0
+ *
+ */
+static mrb_value
+math_log10(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < 0.0) {
+ domain_error(mrb, "log10");
+ }
+ x = log10(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.sqrt(numeric) -> float
+ *
+ * Returns the square root of <i>numeric</i>.
+ *
+ */
+static mrb_value
+math_sqrt(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ if (x < 0.0) {
+ domain_error(mrb, "sqrt");
+ }
+ x = sqrt(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+
+/*
+ * call-seq:
+ * Math.cbrt(numeric) -> float
+ *
+ * Returns the cube root of <i>numeric</i>.
+ *
+ * -9.upto(9) {|x|
+ * p [x, Math.cbrt(x), Math.cbrt(x)**3]
+ * }
+ * #=>
+ * [-9, -2.0800838230519, -9.0]
+ * [-8, -2.0, -8.0]
+ * [-7, -1.91293118277239, -7.0]
+ * [-6, -1.81712059283214, -6.0]
+ * [-5, -1.7099759466767, -5.0]
+ * [-4, -1.5874010519682, -4.0]
+ * [-3, -1.44224957030741, -3.0]
+ * [-2, -1.25992104989487, -2.0]
+ * [-1, -1.0, -1.0]
+ * [0, 0.0, 0.0]
+ * [1, 1.0, 1.0]
+ * [2, 1.25992104989487, 2.0]
+ * [3, 1.44224957030741, 3.0]
+ * [4, 1.5874010519682, 4.0]
+ * [5, 1.7099759466767, 5.0]
+ * [6, 1.81712059283214, 6.0]
+ * [7, 1.91293118277239, 7.0]
+ * [8, 2.0, 8.0]
+ * [9, 2.0800838230519, 9.0]
+ *
+ */
+static mrb_value
+math_cbrt(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = cbrt(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+
+/*
+ * call-seq:
+ * Math.frexp(numeric) -> [ fraction, exponent ]
+ *
+ * Returns a two-element array containing the normalized fraction (a
+ * <code>Float</code>) and exponent (a <code>Fixnum</code>) of
+ * <i>numeric</i>.
+ *
+ * fraction, exponent = Math.frexp(1234) #=> [0.6025390625, 11]
+ * fraction * 2**exponent #=> 1234.0
+ */
+static mrb_value
+math_frexp(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+ int exp;
+
+ mrb_get_args(mrb, "f", &x);
+ x = frexp(x, &exp);
+
+ return mrb_assoc_new(mrb, mrb_float_value(mrb, x), mrb_fixnum_value(exp));
+}
+
+/*
+ * call-seq:
+ * Math.ldexp(flt, int) -> float
+ *
+ * Returns the value of <i>flt</i>*(2**<i>int</i>).
+ *
+ * fraction, exponent = Math.frexp(1234)
+ * Math.ldexp(fraction, exponent) #=> 1234.0
+ */
+static mrb_value
+math_ldexp(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+ mrb_int i;
+
+ mrb_get_args(mrb, "fi", &x, &i);
+ x = ldexp(x, i);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.hypot(x, y) -> float
+ *
+ * Returns sqrt(x**2 + y**2), the hypotenuse of a right-angled triangle
+ * with sides <i>x</i> and <i>y</i>.
+ *
+ * Math.hypot(3, 4) #=> 5.0
+ */
+static mrb_value
+math_hypot(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x, y;
+
+ mrb_get_args(mrb, "ff", &x, &y);
+ x = hypot(x, y);
+
+ return mrb_float_value(mrb, x);
+}
+
+/*
+ * call-seq:
+ * Math.erf(x) -> float
+ *
+ * Calculates the error function of x.
+ */
+static mrb_value
+math_erf(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = erf(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+
+/*
+ * call-seq:
+ * Math.erfc(x) -> float
+ *
+ * Calculates the complementary error function of x.
+ */
+static mrb_value
+math_erfc(mrb_state *mrb, mrb_value obj)
+{
+ mrb_float x;
+
+ mrb_get_args(mrb, "f", &x);
+ x = erfc(x);
+
+ return mrb_float_value(mrb, x);
+}
+
+/* ------------------------------------------------------------------------*/
+void
+mrb_mruby_math_gem_init(mrb_state* mrb)
+{
+ struct RClass *mrb_math;
+ mrb_math = mrb_define_module(mrb, "Math");
+
+ mrb_define_class_under(mrb, mrb_math, "DomainError", mrb->eStandardError_class);
+
+#ifdef M_PI
+ mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(mrb, M_PI));
+#else
+ mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(mrb, atan(1.0)*4.0));
+#endif
+
+#ifdef M_E
+ mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, M_E));
+#else
+ mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, exp(1.0)));
+#endif
+
+#ifdef MRB_USE_FLOAT
+ mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-5));
+#else
+ mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-12));
+#endif
+
+ mrb_define_module_function(mrb, mrb_math, "sin", math_sin, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "cos", math_cos, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "tan", math_tan, MRB_ARGS_REQ(1));
+
+ mrb_define_module_function(mrb, mrb_math, "asin", math_asin, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "acos", math_acos, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "atan", math_atan, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "atan2", math_atan2, MRB_ARGS_REQ(2));
+
+ mrb_define_module_function(mrb, mrb_math, "sinh", math_sinh, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "cosh", math_cosh, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "tanh", math_tanh, MRB_ARGS_REQ(1));
+
+ mrb_define_module_function(mrb, mrb_math, "asinh", math_asinh, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "acosh", math_acosh, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "atanh", math_atanh, MRB_ARGS_REQ(1));
+
+ mrb_define_module_function(mrb, mrb_math, "exp", math_exp, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "log", math_log, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
+ mrb_define_module_function(mrb, mrb_math, "log2", math_log2, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "log10", math_log10, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "sqrt", math_sqrt, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "cbrt", math_cbrt, MRB_ARGS_REQ(1));
+
+ mrb_define_module_function(mrb, mrb_math, "frexp", math_frexp, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "ldexp", math_ldexp, MRB_ARGS_REQ(2));
+
+ mrb_define_module_function(mrb, mrb_math, "hypot", math_hypot, MRB_ARGS_REQ(2));
+
+ mrb_define_module_function(mrb, mrb_math, "erf", math_erf, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, mrb_math, "erfc", math_erfc, MRB_ARGS_REQ(1));
+}
+
+void
+mrb_mruby_math_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/test/math.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/test/math.rb
new file mode 100644
index 00000000..e9ea07cc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-math/test/math.rb
@@ -0,0 +1,152 @@
+##
+# Math Test
+
+##
+# Performs fuzzy check for equality on methods returning floats
+# on the basis of the Math::TOLERANCE constant.
+def check_float(a, b)
+ tolerance = Math::TOLERANCE
+ a = a.to_f
+ b = b.to_f
+ if a.finite? and b.finite?
+ (a-b).abs < tolerance
+ else
+ true
+ end
+end
+
+assert('Math.sin 0') do
+ check_float(Math.sin(0), 0)
+end
+
+assert('Math.sin PI/2') do
+ check_float(Math.sin(Math::PI / 2), 1)
+end
+
+assert('Math.cos 0') do
+ check_float(Math.cos(0), 1)
+end
+
+assert('Math.cos PI/2') do
+ check_float(Math.cos(Math::PI / 2), 0)
+end
+
+assert('Math.tan 0') do
+ check_float(Math.tan(0), 0)
+end
+
+assert('Math.tan PI/4') do
+ check_float(Math.tan(Math::PI / 4), 1)
+end
+
+assert('Fundamental trig identities') do
+ result = true
+ N = 13
+ N.times do |i|
+ a = Math::PI / N * i
+ ca = Math::PI / 2 - a
+ s = Math.sin(a)
+ c = Math.cos(a)
+ t = Math.tan(a)
+ result &= check_float(s, Math.cos(ca))
+ result &= check_float(t, 1 / Math.tan(ca))
+ result &= check_float(s ** 2 + c ** 2, 1)
+ result &= check_float(t ** 2 + 1, (1/c) ** 2)
+ result &= check_float((1/t) ** 2 + 1, (1/s) ** 2)
+ end
+ result
+end
+
+assert('Math.erf 0') do
+ check_float(Math.erf(0), 0)
+end
+
+assert('Math.exp 0') do
+ check_float(Math.exp(0), 1.0)
+end
+
+assert('Math.exp 1') do
+ check_float(Math.exp(1), 2.718281828459045)
+end
+
+assert('Math.exp 1.5') do
+ check_float(Math.exp(1.5), 4.4816890703380645)
+end
+
+assert('Math.log 1') do
+ check_float(Math.log(1), 0)
+end
+
+assert('Math.log E') do
+ check_float(Math.log(Math::E), 1.0)
+end
+
+assert('Math.log E**3') do
+ check_float(Math.log(Math::E**3), 3.0)
+end
+
+assert('Math.log2 1') do
+ check_float(Math.log2(1), 0.0)
+end
+
+assert('Math.log2 2') do
+ check_float(Math.log2(2), 1.0)
+end
+
+assert('Math.log10 1') do
+ check_float(Math.log10(1), 0.0)
+end
+
+assert('Math.log10 10') do
+ check_float(Math.log10(10), 1.0)
+end
+
+assert('Math.log10 10**100') do
+ check_float(Math.log10(10**100), 100.0)
+end
+
+assert('Math.sqrt') do
+ num = [0.0, 1.0, 2.0, 3.0, 4.0]
+ sqr = [0, 1, 4, 9, 16]
+ result = true
+ sqr.each_with_index do |v,i|
+ result &= check_float(Math.sqrt(v), num[i])
+ end
+ result
+end
+
+assert('Math.cbrt') do
+ num = [-2.0, -1.0, 0.0, 1.0, 2.0]
+ cub = [-8, -1, 0, 1, 8]
+ result = true
+ cub.each_with_index do |v,i|
+ result &= check_float(Math.cbrt(v), num[i])
+ end
+ result
+end
+
+assert('Math.hypot') do
+ check_float(Math.hypot(3, 4), 5.0)
+end
+
+assert('Math.frexp 1234') do
+ n = 1234
+ fraction, exponent = Math.frexp(n)
+ check_float(Math.ldexp(fraction, exponent), n)
+end
+
+assert('Math.erf 1') do
+ check_float(Math.erf(1), 0.842700792949715)
+end
+
+assert('Math.erfc 1') do
+ check_float(Math.erfc(1), 0.157299207050285)
+end
+
+assert('Math.erf -1') do
+ check_float(Math.erf(-1), -0.8427007929497148)
+end
+
+assert('Math.erfc -1') do
+ check_float(Math.erfc(-1), 1.8427007929497148)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake
new file mode 100644
index 00000000..6db7e589
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-numeric-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Numeric class extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb
new file mode 100644
index 00000000..0bf3c6ab
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb
@@ -0,0 +1,17 @@
+module Integral
+ def div(other)
+ self.divmod(other)[0]
+ end
+
+ def zero?
+ self == 0
+ end
+
+ def nonzero?
+ if self == 0
+ nil
+ else
+ self
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c
new file mode 100644
index 00000000..f71236a3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c
@@ -0,0 +1,30 @@
+#include <limits.h>
+#include <mruby.h>
+
+static mrb_value
+mrb_int_chr(mrb_state *mrb, mrb_value x)
+{
+ mrb_int chr;
+ char c;
+
+ chr = mrb_fixnum(x);
+ if (chr >= (1 << CHAR_BIT)) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", x);
+ }
+ c = (char)chr;
+
+ return mrb_str_new(mrb, &c, 1);
+}
+
+void
+mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass *i = mrb_class_get(mrb, "Integer");
+
+ mrb_define_method(mrb, i, "chr", mrb_int_chr, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_numeric_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb
new file mode 100644
index 00000000..8bead248
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb
@@ -0,0 +1,28 @@
+##
+# Numeric(Ext) Test
+
+assert('Integer#chr') do
+ assert_equal("A", 65.chr)
+ assert_equal("B", 0x42.chr)
+
+ # multibyte encoding (not support yet)
+ assert_raise(RangeError) { 256.chr }
+end
+
+assert('Integer#div') do
+ assert_equal 52, 365.div(7)
+end
+
+assert('Float#div') do
+ assert_float 52, 365.2425.div(7)
+end
+
+assert('Integer#zero?') do
+ assert_equal true, 0.zero?
+ assert_equal false, 1.zero?
+end
+
+assert('Integer#nonzero?') do
+ assert_equal nil, 0.nonzero?
+ assert_equal 1000, 1000.nonzero?
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrbgem.rake
new file mode 100644
index 00000000..6d14b4a5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-object-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Object class extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrblib/object.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrblib/object.rb
new file mode 100644
index 00000000..581156cb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/mrblib/object.rb
@@ -0,0 +1,19 @@
+class Object
+ ##
+ # call-seq:
+ # obj.tap{|x|...} -> obj
+ #
+ # Yields <code>x</code> to the block, and then returns <code>x</code>.
+ # The primary purpose of this method is to "tap into" a method chain,
+ # in order to perform operations on intermediate results within the chain.
+ #
+ # (1..10) .tap {|x| puts "original: #{x.inspect}"}
+ # .to_a .tap {|x| puts "array: #{x.inspect}"}
+ # .select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"}
+ # .map { |x| x*x } .tap {|x| puts "squares: #{x.inspect}"}
+ #
+ def tap
+ yield self
+ self
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/src/object.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/src/object.c
new file mode 100644
index 00000000..35a07b58
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/src/object.c
@@ -0,0 +1,106 @@
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+
+/*
+ * call-seq:
+ * nil.to_a -> []
+ *
+ * Always returns an empty array.
+ */
+
+static mrb_value
+nil_to_a(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_ary_new(mrb);
+}
+
+/*
+ * call-seq:
+ * nil.to_f -> 0.0
+ *
+ * Always returns zero.
+ */
+
+static mrb_value
+nil_to_f(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_float_value(mrb, 0.0);
+}
+
+/*
+ * call-seq:
+ * nil.to_i -> 0
+ *
+ * Always returns zero.
+ */
+
+static mrb_value
+nil_to_i(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_fixnum_value(0);
+}
+
+/*
+ * call-seq:
+ * obj.instance_exec(arg...) {|var...| block } -> obj
+ *
+ * Executes the given block within the context of the receiver
+ * (_obj_). In order to set the context, the variable +self+ is set
+ * to _obj_ while the code is executing, giving the code access to
+ * _obj_'s instance variables. Arguments are passed as block parameters.
+ *
+ * class KlassWithSecret
+ * def initialize
+ * @secret = 99
+ * end
+ * end
+ * k = KlassWithSecret.new
+ * k.instance_exec(5) {|x| @secret+x } #=> 104
+ */
+
+static mrb_value
+mrb_obj_instance_exec(mrb_state *mrb, mrb_value self)
+{
+ const mrb_value *argv;
+ mrb_int argc;
+ mrb_value blk;
+ struct RClass *c;
+
+ mrb_get_args(mrb, "*&", &argv, &argc, &blk);
+
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+
+ switch (mrb_type(self)) {
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ c = NULL;
+ break;
+ default:
+ c = mrb_class_ptr(mrb_singleton_class(mrb, self));
+ break;
+ }
+ mrb->c->ci->target_class = c;
+ return mrb_yield_cont(mrb, blk, self, argc, argv);
+}
+
+void
+mrb_mruby_object_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass * n = mrb->nil_class;
+
+ mrb_define_method(mrb, n, "to_a", nil_to_a, MRB_ARGS_NONE());
+ mrb_define_method(mrb, n, "to_f", nil_to_f, MRB_ARGS_NONE());
+ mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, mrb->kernel_module, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
+}
+
+void
+mrb_mruby_object_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/nil.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/nil.rb
new file mode 100644
index 00000000..5cd1cf4e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/nil.rb
@@ -0,0 +1,11 @@
+assert('NilClass#to_a') do
+ assert_equal [], nil.to_a
+end
+
+assert('NilClass#to_f') do
+ assert_equal 0.0, nil.to_f
+end
+
+assert('NilClass#to_i') do
+ assert_equal 0, nil.to_i
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/object.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/object.rb
new file mode 100644
index 00000000..f0742f8c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-object-ext/test/object.rb
@@ -0,0 +1,53 @@
+assert('Object#instance_exec') do
+ class KlassWithSecret
+ def initialize
+ @secret = 99
+ end
+ end
+ k = KlassWithSecret.new
+ assert_equal 104, k.instance_exec(5) {|x| @secret+x }
+end
+
+assert('Object#tap') do
+ ret = []
+ (1..10) .tap {|x| ret << "original: #{x.inspect}"}
+ .to_a .tap {|x| ret << "array: #{x.inspect}"}
+ .select {|x| x%2==0} .tap {|x| ret << "evens: #{x.inspect}"}
+ .map { |x| x*x } .tap {|x| ret << "squares: #{x.inspect}"}
+
+ assert_equal [
+ "original: 1..10",
+ "array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]",
+ "evens: [2, 4, 6, 8, 10]",
+ "squares: [4, 16, 36, 64, 100]"
+ ], ret
+ assert_equal(:tap_ok, Class.new {def m; tap{return :tap_ok}; end}.new.m)
+end
+
+assert('instance_exec on primitives with class and module definition') do
+ begin
+ class A
+ 1.instance_exec do
+ class B
+ end
+ end
+ end
+
+ assert_kind_of Class, A::B
+ ensure
+ Object.remove_const :A
+ end
+
+ begin
+ class A
+ 1.instance_exec do
+ module B
+ end
+ end
+ end
+
+ assert_kind_of Module, A::B
+ ensure
+ Object.remove_const :A
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/mrbgem.rake
new file mode 100644
index 00000000..fa35136a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-objectspace') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'ObjectSpace class'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c
new file mode 100644
index 00000000..3887091d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c
@@ -0,0 +1,187 @@
+#include <mruby.h>
+#include <mruby/gc.h>
+#include <mruby/hash.h>
+#include <mruby/class.h>
+
+struct os_count_struct {
+ mrb_int total;
+ mrb_int freed;
+ mrb_int counts[MRB_TT_MAXDEFINE+1];
+};
+
+static int
+os_count_object_type(mrb_state *mrb, struct RBasic *obj, void *data)
+{
+ struct os_count_struct *obj_count;
+ obj_count = (struct os_count_struct*)data;
+
+ obj_count->total++;
+
+ if (mrb_object_dead_p(mrb, obj)) {
+ obj_count->freed++;
+ }
+ else {
+ obj_count->counts[obj->tt]++;
+ }
+ return MRB_EACH_OBJ_OK;
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.count_objects([result_hash]) -> hash
+ *
+ * Counts objects for each type.
+ *
+ * It returns a hash, such as:
+ * {
+ * :TOTAL=>10000,
+ * :FREE=>3011,
+ * :T_OBJECT=>6,
+ * :T_CLASS=>404,
+ * # ...
+ * }
+ *
+ * If the optional argument +result_hash+ is given,
+ * it is overwritten and returned. This is intended to avoid probe effect.
+ *
+ */
+
+static mrb_value
+os_count_objects(mrb_state *mrb, mrb_value self)
+{
+ struct os_count_struct obj_count = { 0 };
+ mrb_int i;
+ mrb_value hash;
+
+ if (mrb_get_args(mrb, "|H", &hash) == 0) {
+ hash = mrb_hash_new(mrb);
+ }
+
+ if (!mrb_test(mrb_hash_empty_p(mrb, hash))) {
+ mrb_hash_clear(mrb, hash);
+ }
+
+ mrb_objspace_each_objects(mrb, os_count_object_type, &obj_count);
+
+ mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "TOTAL")), mrb_fixnum_value(obj_count.total));
+ mrb_hash_set(mrb, hash, mrb_symbol_value(mrb_intern_lit(mrb, "FREE")), mrb_fixnum_value(obj_count.freed));
+
+ for (i = MRB_TT_FALSE; i < MRB_TT_MAXDEFINE; i++) {
+ mrb_value type;
+ switch (i) {
+#define COUNT_TYPE(t) case (MRB_T ## t): type = mrb_symbol_value(mrb_intern_lit(mrb, #t)); break;
+ COUNT_TYPE(T_FALSE);
+ COUNT_TYPE(T_FREE);
+ COUNT_TYPE(T_TRUE);
+ COUNT_TYPE(T_FIXNUM);
+ COUNT_TYPE(T_SYMBOL);
+ COUNT_TYPE(T_UNDEF);
+ COUNT_TYPE(T_FLOAT);
+ COUNT_TYPE(T_CPTR);
+ COUNT_TYPE(T_OBJECT);
+ COUNT_TYPE(T_CLASS);
+ COUNT_TYPE(T_MODULE);
+ COUNT_TYPE(T_ICLASS);
+ COUNT_TYPE(T_SCLASS);
+ COUNT_TYPE(T_PROC);
+ COUNT_TYPE(T_ARRAY);
+ COUNT_TYPE(T_HASH);
+ COUNT_TYPE(T_STRING);
+ COUNT_TYPE(T_RANGE);
+ COUNT_TYPE(T_EXCEPTION);
+ COUNT_TYPE(T_FILE);
+ COUNT_TYPE(T_ENV);
+ COUNT_TYPE(T_DATA);
+ COUNT_TYPE(T_FIBER);
+#undef COUNT_TYPE
+ default:
+ type = mrb_fixnum_value(i); break;
+ }
+ if (obj_count.counts[i])
+ mrb_hash_set(mrb, hash, type, mrb_fixnum_value(obj_count.counts[i]));
+ }
+
+ return hash;
+}
+
+struct os_each_object_data {
+ mrb_value block;
+ struct RClass *target_module;
+ mrb_int count;
+};
+
+static int
+os_each_object_cb(mrb_state *mrb, struct RBasic *obj, void *ud)
+{
+ struct os_each_object_data *d = (struct os_each_object_data*)ud;
+
+ /* filter dead objects */
+ if (mrb_object_dead_p(mrb, obj)) {
+ return MRB_EACH_OBJ_OK;
+ }
+
+ /* filter internal objects */
+ switch (obj->tt) {
+ case MRB_TT_ENV:
+ case MRB_TT_ICLASS:
+ return MRB_EACH_OBJ_OK;
+ default:
+ break;
+ }
+
+ /* filter half baked (or internal) objects */
+ if (!obj->c) return MRB_EACH_OBJ_OK;
+
+ /* filter class kind if target module defined */
+ if (d->target_module && !mrb_obj_is_kind_of(mrb, mrb_obj_value(obj), d->target_module)) {
+ return MRB_EACH_OBJ_OK;
+ }
+
+ mrb_yield(mrb, d->block, mrb_obj_value(obj));
+ ++d->count;
+ return MRB_EACH_OBJ_OK;
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.each_object([module]) {|obj| ... } -> fixnum
+ *
+ * Calls the block once for each object in this Ruby process.
+ * Returns the number of objects found.
+ * If the optional argument +module+ is given,
+ * calls the block for only those classes or modules
+ * that match (or are a subclass of) +module+.
+ *
+ * If no block is given, ArgumentError is raised.
+ *
+ */
+
+static mrb_value
+os_each_object(mrb_state *mrb, mrb_value self)
+{
+ mrb_value cls = mrb_nil_value();
+ struct os_each_object_data d;
+ mrb_get_args(mrb, "&|C", &d.block, &cls);
+
+ if (mrb_nil_p(d.block)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Expected block in ObjectSpace.each_object.");
+ }
+
+ d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls);
+ d.count = 0;
+ mrb_objspace_each_objects(mrb, os_each_object_cb, &d);
+ return mrb_fixnum_value(d.count);
+}
+
+void
+mrb_mruby_objectspace_gem_init(mrb_state *mrb)
+{
+ struct RClass *os = mrb_define_module(mrb, "ObjectSpace");
+ mrb_define_class_method(mrb, os, "count_objects", os_count_objects, MRB_ARGS_OPT(1));
+ mrb_define_class_method(mrb, os, "each_object", os_each_object, MRB_ARGS_OPT(1));
+}
+
+void
+mrb_mruby_objectspace_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/test/objectspace.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/test/objectspace.rb
new file mode 100644
index 00000000..4731d53b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-objectspace/test/objectspace.rb
@@ -0,0 +1,60 @@
+assert('ObjectSpace.count_objects') do
+ h = {}
+ f = Fiber.new {} if Object.const_defined? :Fiber
+ ObjectSpace.count_objects(h)
+ assert_kind_of(Hash, h)
+ assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) })
+ assert_true(h.values.all? {|x| x.is_a?(Integer) })
+
+ assert_true(h.has_key?(:TOTAL))
+ assert_true(h.has_key?(:FREE))
+ assert_true(h.has_key?(:T_FIBER)) if Object.const_defined? :Fiber
+
+ assert_equal(h[:TOTAL] * 2, h.values.reduce(:+))
+
+ h = ObjectSpace.count_objects
+ assert_kind_of(Hash, h)
+ assert_true(h.keys.all? {|x| x.is_a?(Symbol) || x.is_a?(Integer) })
+ assert_true(h.values.all? {|x| x.is_a?(Integer) })
+
+ assert_raise(TypeError) { ObjectSpace.count_objects(1) }
+
+ h0 = {:T_FOO=>1000}
+ h = ObjectSpace.count_objects(h0)
+ assert_false(h0.has_key?(:T_FOO))
+
+ GC.start
+ h_after = {}
+ h_before = ObjectSpace.count_objects
+
+ objs = []
+ 1000.times do
+ objs << {}
+ end
+ objs = nil
+ ObjectSpace.count_objects(h)
+ GC.start
+ ObjectSpace.count_objects(h_after)
+
+ assert_equal(h[:T_HASH], h_before[:T_HASH] + 1000)
+ assert_equal(h_after[:T_HASH], h_before[:T_HASH])
+end
+
+assert('ObjectSpace.each_object') do
+ objs = []
+ objs_count = ObjectSpace.each_object { |obj|
+ objs << obj
+ }
+ assert_equal objs.length, objs_count
+
+ arys = []
+ arys_count = ObjectSpace.each_object(Array) { |obj|
+ arys << obj
+ }
+ assert_equal arys.length, arys_count
+ assert_true arys.length < objs.length
+end
+
+assert 'Check class pointer of ObjectSpace.each_object.' do
+ ObjectSpace.each_object { |obj| !obj }
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrbgem.rake
new file mode 100644
index 00000000..2ea6e312
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-print') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'standard print/puts/p'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrblib/print.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrblib/print.rb
new file mode 100644
index 00000000..38a10661
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/mrblib/print.rb
@@ -0,0 +1,64 @@
+##
+# Kernel
+#
+# ISO 15.3.1
+module Kernel
+ ##
+ # Invoke method +print+ on STDOUT and passing +*args+
+ #
+ # ISO 15.3.1.2.10
+ def print(*args)
+ i = 0
+ len = args.size
+ while i < len
+ __printstr__ args[i].to_s
+ i += 1
+ end
+ end
+
+ ##
+ # Invoke method +puts+ on STDOUT and passing +*args*+
+ #
+ # ISO 15.3.1.2.11
+ def puts(*args)
+ i = 0
+ len = args.size
+ while i < len
+ s = args[i].to_s
+ __printstr__ s
+ __printstr__ "\n" if (s[-1] != "\n")
+ i += 1
+ end
+ __printstr__ "\n" if len == 0
+ nil
+ end
+
+ ##
+ # Print human readable object description
+ #
+ # ISO 15.3.1.3.34
+ def p(*args)
+ i = 0
+ len = args.size
+ while i < len
+ __printstr__ args[i].inspect
+ __printstr__ "\n"
+ i += 1
+ end
+ args[0]
+ end
+
+ unless Kernel.respond_to?(:sprintf)
+ def printf(*args)
+ raise NotImplementedError.new('printf not available')
+ end
+ def sprintf(*args)
+ raise NotImplementedError.new('sprintf not available')
+ end
+ else
+ def printf(*args)
+ __printstr__(sprintf(*args))
+ nil
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/src/print.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/src/print.c
new file mode 100644
index 00000000..d0c522d2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-print/src/print.c
@@ -0,0 +1,64 @@
+#include <mruby.h>
+#include <mruby/string.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#if defined(_WIN32)
+# include <windows.h>
+# include <io.h>
+#ifdef _MSC_VER
+# define isatty(x) _isatty(x)
+# define fileno(x) _fileno(x)
+#endif
+#endif
+
+static void
+printstr(mrb_state *mrb, mrb_value obj)
+{
+ if (mrb_string_p(obj)) {
+#if defined(_WIN32)
+ if (isatty(fileno(stdout))) {
+ DWORD written;
+ int mlen = RSTRING_LEN(obj);
+ char* utf8 = RSTRING_PTR(obj);
+ int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0);
+ wchar_t* utf16 = (wchar_t*)mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t));
+ if (utf16 == NULL) return;
+ if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) {
+ utf16[wlen] = 0;
+ WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE),
+ utf16, wlen, &written, NULL);
+ }
+ mrb_free(mrb, utf16);
+ } else
+#endif
+ fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
+ fflush(stdout);
+ }
+}
+
+/* 15.3.1.2.9 */
+/* 15.3.1.3.34 */
+mrb_value
+mrb_printstr(mrb_state *mrb, mrb_value self)
+{
+ mrb_value argv;
+
+ mrb_get_args(mrb, "o", &argv);
+ printstr(mrb, argv);
+
+ return argv;
+}
+
+void
+mrb_mruby_print_gem_init(mrb_state* mrb)
+{
+ struct RClass *krn;
+ krn = mrb->kernel_module;
+ mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, MRB_ARGS_REQ(1));
+}
+
+void
+mrb_mruby_print_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrbgem.rake
new file mode 100644
index 00000000..e4d15a14
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-proc-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Proc class extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb
new file mode 100644
index 00000000..b7166393
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb
@@ -0,0 +1,42 @@
+class Proc
+
+ def ===(*args)
+ call(*args)
+ end
+
+ def yield(*args)
+ call(*args)
+ end
+
+ def to_proc
+ self
+ end
+
+ def curry(arity=self.arity)
+ type = :proc
+ abs = lambda {|a| a < 0 ? -a - 1 : a}
+ arity = abs[arity]
+ if lambda?
+ type = :lambda
+ self_arity = self.arity
+ if (self_arity >= 0 && arity != self_arity) ||
+ (self_arity < 0 && abs[self_arity] > arity)
+ raise ArgumentError, "wrong number of arguments (#{arity} for #{abs[self_arity]})"
+ end
+ end
+
+ pproc = self
+ make_curry = proc do |given_args=[]|
+ send(type) do |*args|
+ new_args = given_args + args
+ if new_args.size >= arity
+ pproc[*new_args]
+ else
+ make_curry[new_args]
+ end
+ end
+ end
+ make_curry.call
+ end
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/src/proc.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/src/proc.c
new file mode 100644
index 00000000..b13606f5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/src/proc.c
@@ -0,0 +1,173 @@
+#include <mruby.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/debug.h>
+
+static mrb_value
+mrb_proc_lambda(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *p = mrb_proc_ptr(self);
+ return mrb_bool_value(MRB_PROC_STRICT_P(p));
+}
+
+static mrb_value
+mrb_proc_source_location(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *p = mrb_proc_ptr(self);
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ return mrb_nil_value();
+ }
+ else {
+ mrb_irep *irep = p->body.irep;
+ int32_t line;
+ const char *filename;
+
+ filename = mrb_debug_get_filename(irep, 0);
+ line = mrb_debug_get_line(irep, 0);
+
+ return (!filename && line == -1)? mrb_nil_value()
+ : mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, filename), mrb_fixnum_value(line));
+ }
+}
+
+static mrb_value
+mrb_proc_inspect(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *p = mrb_proc_ptr(self);
+ mrb_value str = mrb_str_new_lit(mrb, "#<Proc:");
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));
+
+ if (!MRB_PROC_CFUNC_P(p)) {
+ mrb_irep *irep = p->body.irep;
+ const char *filename;
+ int32_t line;
+ mrb_str_cat_lit(mrb, str, "@");
+
+ filename = mrb_debug_get_filename(irep, 0);
+ mrb_str_cat_cstr(mrb, str, filename ? filename : "-");
+ mrb_str_cat_lit(mrb, str, ":");
+
+ line = mrb_debug_get_line(irep, 0);
+ if (line != -1) {
+ str = mrb_format(mrb, "%S:%S", str, mrb_fixnum_value(line));
+ }
+ else {
+ mrb_str_cat_lit(mrb, str, "-");
+ }
+ }
+
+ if (MRB_PROC_STRICT_P(p)) {
+ mrb_str_cat_lit(mrb, str, " (lambda)");
+ }
+
+ mrb_str_cat_lit(mrb, str, ">");
+ return str;
+}
+
+static mrb_value
+mrb_kernel_proc(mrb_state *mrb, mrb_value self)
+{
+ mrb_value blk;
+
+ mrb_get_args(mrb, "&", &blk);
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
+ }
+
+ return blk;
+}
+
+/*
+ * call-seq:
+ * prc.parameters -> array
+ *
+ * Returns the parameter information of this proc.
+ *
+ * prc = lambda{|x, y=42, *other|}
+ * prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
+ */
+
+static mrb_value
+mrb_proc_parameters(mrb_state *mrb, mrb_value self)
+{
+ struct parameters_type {
+ int size;
+ const char *name;
+ } *p, parameters_list [] = {
+ {0, "req"},
+ {0, "opt"},
+ {0, "rest"},
+ {0, "req"},
+ {0, "block"},
+ {0, NULL}
+ };
+ const struct RProc *proc = mrb_proc_ptr(self);
+ const struct mrb_irep *irep = proc->body.irep;
+ mrb_aspec aspec;
+ mrb_value sname, parameters;
+ int i, j;
+
+ if (MRB_PROC_CFUNC_P(proc)) {
+ // TODO cfunc aspec is not implemented yet
+ return mrb_ary_new(mrb);
+ }
+ if (!irep) {
+ return mrb_ary_new(mrb);
+ }
+ if (!irep->lv) {
+ return mrb_ary_new(mrb);
+ }
+ if (GET_OPCODE(*irep->iseq) != OP_ENTER) {
+ return mrb_ary_new(mrb);
+ }
+
+ if (!MRB_PROC_STRICT_P(proc)) {
+ parameters_list[0].name = "opt";
+ parameters_list[3].name = "opt";
+ }
+
+ aspec = GETARG_Ax(*irep->iseq);
+ parameters_list[0].size = MRB_ASPEC_REQ(aspec);
+ parameters_list[1].size = MRB_ASPEC_OPT(aspec);
+ parameters_list[2].size = MRB_ASPEC_REST(aspec);
+ parameters_list[3].size = MRB_ASPEC_POST(aspec);
+ parameters_list[4].size = MRB_ASPEC_BLOCK(aspec);
+
+ parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
+
+ for (i = 0, p = parameters_list; p->name; p++) {
+ if (p->size <= 0) continue;
+ sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name));
+ for (j = 0; j < p->size; i++, j++) {
+ mrb_value a = mrb_ary_new(mrb);
+ mrb_ary_push(mrb, a, sname);
+ if (irep->lv[i].name) {
+ mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i].name));
+ }
+ mrb_ary_push(mrb, parameters, a);
+ }
+ }
+ return parameters;
+}
+
+void
+mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass *p = mrb->proc_class;
+ mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda, MRB_ARGS_NONE());
+ mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE());
+ mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE());
+ mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE());
+ mrb_define_method(mrb, p, "parameters", mrb_proc_parameters, MRB_ARGS_NONE());
+
+ mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
+ mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_proc_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.c
new file mode 100644
index 00000000..a77b68e9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.c
@@ -0,0 +1,56 @@
+#include <mruby.h>
+#include <mruby/proc.h>
+#include <mruby/class.h>
+
+static mrb_value
+return_func_name(mrb_state *mrb, mrb_value self)
+{
+ return mrb_cfunc_env_get(mrb, 0);
+}
+
+static mrb_value
+proc_new_cfunc_with_env(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym n;
+ mrb_value n_val;
+ mrb_get_args(mrb, "n", &n);
+ n_val = mrb_symbol_value(n);
+ mrb_define_method_raw(mrb, mrb_class_ptr(self), n,
+ mrb_proc_new_cfunc_with_env(mrb, return_func_name, 1, &n_val));
+ return self;
+}
+
+static mrb_value
+return_env(mrb_state *mrb, mrb_value self)
+{
+ mrb_int idx;
+ mrb_get_args(mrb, "i", &idx);
+ return mrb_cfunc_env_get(mrb, idx);
+}
+
+static mrb_value
+cfunc_env_get(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym n;
+ mrb_value *argv; mrb_int argc;
+ mrb_get_args(mrb, "na", &n, &argv, &argc);
+ mrb_define_method_raw(mrb, mrb_class_ptr(self), n,
+ mrb_proc_new_cfunc_with_env(mrb, return_env, argc, argv));
+ return self;
+}
+
+static mrb_value
+cfunc_without_env(mrb_state *mrb, mrb_value self)
+{
+ return mrb_cfunc_env_get(mrb, 0);
+}
+
+void mrb_mruby_proc_ext_gem_test(mrb_state *mrb)
+{
+ struct RClass *cls;
+
+ cls = mrb_define_class(mrb, "ProcExtTest", mrb->object_class);
+ mrb_define_module_function(mrb, cls, "mrb_proc_new_cfunc_with_env", proc_new_cfunc_with_env, MRB_ARGS_REQ(1));
+ mrb_define_module_function(mrb, cls, "mrb_cfunc_env_get", cfunc_env_get, MRB_ARGS_REQ(2));
+ mrb_define_module_function(mrb, cls, "cfunc_without_env", cfunc_without_env, MRB_ARGS_NONE());
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.rb
new file mode 100644
index 00000000..037d8d12
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-proc-ext/test/proc.rb
@@ -0,0 +1,96 @@
+##
+# Proc(Ext) Test
+
+assert('Proc#source_location') do
+ loc = Proc.new {}.source_location
+ next true if loc.nil?
+ assert_equal loc[0][-7, 7], 'proc.rb'
+ assert_equal loc[1], 5
+end
+
+assert('Proc#inspect') do
+ ins = Proc.new{}.inspect
+ assert_kind_of String, ins
+end
+
+assert('Proc#lambda?') do
+ assert_true lambda{}.lambda?
+ assert_true !Proc.new{}.lambda?
+end
+
+assert('Proc#===') do
+ proc = Proc.new {|a| a * 2}
+ assert_equal 20, (proc === 10)
+end
+
+assert('Proc#yield') do
+ proc = Proc.new {|a| a * 2}
+ assert_equal 20, proc.yield(10)
+end
+
+assert('Proc#curry') do
+ b = proc {|x, y, z| (x||0) + (y||0) + (z||0) }
+ assert_equal 6, b.curry[1][2][3]
+ assert_equal 6, b.curry[1, 2][3, 4]
+ assert_equal 6, b.curry(5)[1][2][3][4][5]
+ assert_equal 6, b.curry(5)[1, 2][3, 4][5]
+ assert_equal 1, b.curry(1)[1]
+
+ b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }
+ assert_equal 6, b.curry[1][2][3]
+ assert_raise(ArgumentError) { b.curry[1, 2][3, 4] }
+ assert_raise(ArgumentError) { b.curry(5) }
+ assert_raise(ArgumentError) { b.curry(1) }
+
+ assert_false(proc{}.curry.lambda?)
+ assert_true(lambda{}.curry.lambda?)
+end
+
+assert('Proc#parameters') do
+ assert_equal([], Proc.new {}.parameters)
+ assert_equal([], Proc.new {||}.parameters)
+ assert_equal([[:opt, :a]], Proc.new {|a|}.parameters)
+ assert_equal([[:req, :a]], lambda {|a|}.parameters)
+ assert_equal([[:opt, :a]], lambda {|a=nil|}.parameters)
+ assert_equal([[:req, :a]], ->(a){}.parameters)
+ assert_equal([[:rest]], lambda { |*| }.parameters)
+ assert_equal([[:rest, :a]], Proc.new {|*a|}.parameters)
+ assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], Proc.new {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters)
+ assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters)
+end
+
+assert('Proc#to_proc') do
+ proc = Proc.new {}
+ assert_equal proc, proc.to_proc
+end
+
+assert('Kernel#proc') do
+ assert_true !proc{|a|}.lambda?
+
+ assert_raise LocalJumpError do
+ proc{ break }.call
+ end
+end
+
+assert('mrb_proc_new_cfunc_with_env') do
+ ProcExtTest.mrb_proc_new_cfunc_with_env(:test)
+ ProcExtTest.mrb_proc_new_cfunc_with_env(:mruby)
+
+ t = ProcExtTest.new
+
+ assert_equal :test, t.test
+ assert_equal :mruby, t.mruby
+end
+
+assert('mrb_cfunc_env_get') do
+ ProcExtTest.mrb_cfunc_env_get :get_int, [0, 1, 2]
+
+ t = ProcExtTest.new
+
+ assert_raise(TypeError) { t.cfunc_without_env }
+
+ assert_raise(IndexError) { t.get_int(-1) }
+ assert_raise(IndexError) { t.get_int(3) }
+
+ assert_equal 1, t.get_int(1)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/mrbgem.rake
new file mode 100644
index 00000000..3a3fd2bd
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-random') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Random class'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.c
new file mode 100644
index 00000000..405bd5c2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.c
@@ -0,0 +1,224 @@
+/*
+** mt19937ar.c - MT Random functions
+**
+** Copyright (C) 1997 - 2016, Makoto Matsumoto and Takuji Nishimura,
+** All rights reserved.
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+**
+** Any feedback is very welcome.
+** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+** email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+**
+** This version is modified by mruby developers. If you see any problem,
+** contact us first at https://github.com/mruby/mruby/issues
+*/
+
+#include <mruby.h>
+#include "mt19937ar.h"
+
+/* Period parameters */
+/* #define N 624 */
+#define M 397
+#define MATRIX_A 0x9908b0dfUL /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+#if 0 /* dead_code */
+static unsigned long mt[N]; /* the array for the state vector */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+#endif /* dead_code */
+
+void mrb_random_init_genrand(mt_state *t, unsigned long s)
+{
+ t->mt[0]= s & 0xffffffffUL;
+ for (t->mti=1; t->mti<N; t->mti++) {
+ t->mt[t->mti] = (1812433253UL * (t->mt[t->mti-1] ^ (t->mt[t->mti-1] >> 30)) + t->mti);
+ t->mt[t->mti] &= 0xffffffffUL;
+ }
+}
+
+unsigned long mrb_random_genrand_int32(mt_state *t)
+{
+ unsigned long y;
+ static const unsigned long mag01[2]={0x0UL, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ if (t->mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (t->mti == N+1) /* if init_genrand() has not been called, */
+ mrb_random_init_genrand(t, 5489UL); /* a default initial seed is used */
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (t->mt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK);
+ t->mt[kk] = t->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ for (;kk<N-1;kk++) {
+ y = (t->mt[kk]&UPPER_MASK)|(t->mt[kk+1]&LOWER_MASK);
+ t->mt[kk] = t->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ y = (t->mt[N-1]&UPPER_MASK)|(t->mt[0]&LOWER_MASK);
+ t->mt[N-1] = t->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+ t->mti = 0;
+ }
+
+ y = t->mt[t->mti++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ t->gen.int_ = y;
+
+ return y;
+}
+
+double mrb_random_genrand_real1(mt_state *t)
+{
+ mrb_random_genrand_int32(t);
+ t->gen.double_ = t->gen.int_*(1.0/4294967295.0);
+ return t->gen.double_;
+ /* divided by 2^32-1 */
+}
+
+#if 0 /* dead_code */
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s)
+{
+ mt[0]= s & 0xffffffffUL;
+ for (mti=1; mti<N; mti++) {
+ mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
+ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+ /* In the previous versions, MSBs of the seed affect */
+ /* only MSBs of the array mt[]. */
+ /* 2002/01/09 modified by Makoto Matsumoto */
+ mt[mti] &= 0xffffffffUL;
+ /* for >32 bit machines */
+ }
+}
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[], int key_length)
+{
+ int i, j, k;
+ init_genrand(19650218UL);
+ i=1; j=0;
+ k = (N>key_length ? N : key_length);
+ for (; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ + init_key[j] + j; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++; j++;
+ if (i>=N) { mt[0] = mt[N-1]; i=1; }
+ if (j>=key_length) j=0;
+ }
+ for (k=N-1; k; k--) {
+ mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+ - i; /* non linear */
+ mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+ i++;
+ if (i>=N) { mt[0] = mt[N-1]; i=1; }
+ }
+
+ mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void)
+{
+ unsigned long y;
+ static const unsigned long mag01[2]={0x0UL, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ if (mti >= N) { /* generate N words at one time */
+ int kk;
+
+ if (mti == N+1) /* if init_genrand() has not been called, */
+ init_genrand(5489UL); /* a default initial seed is used */
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ for (;kk<N-1;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+ mti = 0;
+ }
+
+ y = mt[mti++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void)
+{
+ return (long)(genrand_int32()>>1);
+}
+
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void)
+{
+ return genrand_int32()*(1.0/4294967295.0);
+ /* divided by 2^32-1 */
+}
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void)
+{
+ return genrand_int32()*(1.0/4294967296.0);
+ /* divided by 2^32 */
+}
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void)
+{
+ return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
+ /* divided by 2^32 */
+}
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void)
+{
+ unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
+ return(a*67108864.0+b)*(1.0/9007199254740992.0);
+}
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
+#endif /* dead_code */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.h
new file mode 100644
index 00000000..7d382320
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/mt19937ar.h
@@ -0,0 +1,80 @@
+/*
+** mt19937ar.h - MT Random functions
+**
+** Copyright (C) 1997 - 2016, Makoto Matsumoto and Takuji Nishimura,
+** All rights reserved.
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
+**
+** Any feedback is very welcome.
+** http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+** email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+**
+** This version is modified by mruby developers. If you see any problem,
+** contact us first at https://github.com/mruby/mruby/issues
+*/
+
+#define N 624
+
+typedef struct {
+ unsigned long mt[N];
+ int mti;
+ union {
+ unsigned long int_;
+ double double_;
+ } gen;
+
+ mrb_int seed;
+ mrb_bool has_seed : 1;
+} mt_state;
+
+void mrb_random_init_genrand(mt_state *, unsigned long);
+unsigned long mrb_random_genrand_int32(mt_state *);
+double mrb_random_genrand_real1(mt_state *t);
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s);
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[], int key_length);
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void);
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void);
+
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void);
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void);
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void);
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void);
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c
new file mode 100644
index 00000000..b865244c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.c
@@ -0,0 +1,349 @@
+/*
+** random.c - Random module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/variable.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/array.h>
+#include "mt19937ar.h"
+
+#include <time.h>
+
+static char const MT_STATE_KEY[] = "$mrb_i_mt_state";
+
+static const struct mrb_data_type mt_state_type = {
+ MT_STATE_KEY, mrb_free,
+};
+
+static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self);
+static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self);
+
+static void
+mt_srand(mt_state *t, unsigned long seed)
+{
+ mrb_random_init_genrand(t, seed);
+}
+
+static unsigned long
+mt_rand(mt_state *t)
+{
+ return mrb_random_genrand_int32(t);
+}
+
+static double
+mt_rand_real(mt_state *t)
+{
+ return mrb_random_genrand_real1(t);
+}
+
+static mrb_value
+mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed)
+{
+ if (mrb_nil_p(seed)) {
+ seed = mrb_fixnum_value((mrb_int)(time(NULL) + mt_rand(t)));
+ if (mrb_fixnum(seed) < 0) {
+ seed = mrb_fixnum_value(0 - mrb_fixnum(seed));
+ }
+ }
+
+ mt_srand(t, (unsigned) mrb_fixnum(seed));
+
+ return seed;
+}
+
+static mrb_value
+mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max)
+{
+ mrb_value value;
+
+ if (mrb_fixnum(max) == 0) {
+ value = mrb_float_value(mrb, mt_rand_real(t));
+ }
+ else {
+ value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max));
+ }
+
+ return value;
+}
+
+static mrb_value
+get_opt(mrb_state* mrb)
+{
+ mrb_value arg;
+
+ arg = mrb_nil_value();
+ mrb_get_args(mrb, "|o", &arg);
+
+ if (!mrb_nil_p(arg)) {
+ arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int");
+ if (mrb_nil_p(arg)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type");
+ }
+ if (mrb_fixnum(arg) < 0) {
+ arg = mrb_fixnum_value(0 - mrb_fixnum(arg));
+ }
+ }
+ return arg;
+}
+
+static mrb_value
+get_random(mrb_state *mrb) {
+ return mrb_const_get(mrb,
+ mrb_obj_value(mrb_class_get(mrb, "Random")),
+ mrb_intern_lit(mrb, "DEFAULT"));
+}
+
+static mt_state *
+get_random_state(mrb_state *mrb)
+{
+ mrb_value random_val = get_random(mrb);
+ return DATA_GET_PTR(mrb, random_val, &mt_state_type, mt_state);
+}
+
+static mrb_value
+mrb_random_g_rand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value random = get_random(mrb);
+ return mrb_random_rand(mrb, random);
+}
+
+static mrb_value
+mrb_random_g_srand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value random = get_random(mrb);
+ return mrb_random_srand(mrb, random);
+}
+
+static mrb_value
+mrb_random_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value seed;
+ mt_state *t;
+
+ seed = get_opt(mrb);
+
+ /* avoid memory leaks */
+ t = (mt_state*)DATA_PTR(self);
+ if (t) {
+ mrb_free(mrb, t);
+ }
+ mrb_data_init(self, NULL, &mt_state_type);
+
+ t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state));
+ t->mti = N + 1;
+
+ seed = mrb_random_mt_srand(mrb, t, seed);
+ if (mrb_nil_p(seed)) {
+ t->has_seed = FALSE;
+ }
+ else {
+ mrb_assert(mrb_fixnum_p(seed));
+ t->has_seed = TRUE;
+ t->seed = mrb_fixnum(seed);
+ }
+
+ mrb_data_init(self, t, &mt_state_type);
+
+ return self;
+}
+
+static void
+mrb_random_rand_seed(mrb_state *mrb, mt_state *t)
+{
+ if (!t->has_seed) {
+ mrb_random_mt_srand(mrb, t, mrb_nil_value());
+ }
+}
+
+static mrb_value
+mrb_random_rand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value max;
+ mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);
+
+ max = get_opt(mrb);
+ mrb_random_rand_seed(mrb, t);
+ return mrb_random_mt_rand(mrb, t, max);
+}
+
+static mrb_value
+mrb_random_srand(mrb_state *mrb, mrb_value self)
+{
+ mrb_value seed;
+ mrb_value old_seed;
+ mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);
+
+ seed = get_opt(mrb);
+ seed = mrb_random_mt_srand(mrb, t, seed);
+ old_seed = t->has_seed? mrb_fixnum_value(t->seed) : mrb_nil_value();
+ if (mrb_nil_p(seed)) {
+ t->has_seed = FALSE;
+ }
+ else {
+ mrb_assert(mrb_fixnum_p(seed));
+ t->has_seed = TRUE;
+ t->seed = mrb_fixnum(seed);
+ }
+
+ return old_seed;
+}
+
+/*
+ * call-seq:
+ * ary.shuffle! -> ary
+ *
+ * Shuffles elements in self in place.
+ */
+
+static mrb_value
+mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int i;
+ mt_state *random = NULL;
+
+ if (RARRAY_LEN(ary) > 1) {
+ mrb_get_args(mrb, "|d", &random, &mt_state_type);
+
+ if (random == NULL) {
+ random = get_random_state(mrb);
+ }
+ mrb_random_rand_seed(mrb, random);
+
+ mrb_ary_modify(mrb, mrb_ary_ptr(ary));
+
+ for (i = RARRAY_LEN(ary) - 1; i > 0; i--) {
+ mrb_int j;
+ mrb_value *ptr = RARRAY_PTR(ary);
+ mrb_value tmp;
+
+
+ j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary))));
+
+ tmp = ptr[i];
+ ptr[i] = ptr[j];
+ ptr[j] = tmp;
+ }
+ }
+
+ return ary;
+}
+
+/*
+ * call-seq:
+ * ary.shuffle -> new_ary
+ *
+ * Returns a new array with elements of self shuffled.
+ */
+
+static mrb_value
+mrb_ary_shuffle(mrb_state *mrb, mrb_value ary)
+{
+ mrb_value new_ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary));
+ mrb_ary_shuffle_bang(mrb, new_ary);
+
+ return new_ary;
+}
+
+/*
+ * call-seq:
+ * ary.sample -> obj
+ * ary.sample(n) -> new_ary
+ *
+ * Choose a random element or +n+ random elements from the array.
+ *
+ * The elements are chosen by using random and unique indices into the array
+ * in order to ensure that an element doesn't repeat itself unless the array
+ * already contained duplicate elements.
+ *
+ * If the array is empty the first form returns +nil+ and the second form
+ * returns an empty array.
+ */
+
+static mrb_value
+mrb_ary_sample(mrb_state *mrb, mrb_value ary)
+{
+ mrb_int n = 0;
+ mrb_bool given;
+ mt_state *random = NULL;
+ mrb_int len;
+
+ mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type);
+ if (random == NULL) {
+ random = get_random_state(mrb);
+ }
+ mrb_random_rand_seed(mrb, random);
+ mt_rand(random);
+ len = RARRAY_LEN(ary);
+ if (!given) { /* pick one element */
+ switch (len) {
+ case 0:
+ return mrb_nil_value();
+ case 1:
+ return RARRAY_PTR(ary)[0];
+ default:
+ return RARRAY_PTR(ary)[mt_rand(random) % len];
+ }
+ }
+ else {
+ mrb_value result;
+ mrb_int i, j;
+
+ if (n < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "negative sample number");
+ if (n > len) n = len;
+ result = mrb_ary_new_capa(mrb, n);
+ for (i=0; i<n; i++) {
+ mrb_int r;
+
+ for (;;) {
+ retry:
+ r = mt_rand(random) % len;
+
+ for (j=0; j<i; j++) {
+ if (mrb_fixnum(RARRAY_PTR(result)[j]) == r) {
+ goto retry; /* retry if duplicate */
+ }
+ }
+ break;
+ }
+ mrb_ary_push(mrb, result, mrb_fixnum_value(r));
+ }
+ for (i=0; i<n; i++) {
+ mrb_ary_set(mrb, result, i, RARRAY_PTR(ary)[mrb_fixnum(RARRAY_PTR(result)[i])]);
+ }
+ return result;
+ }
+}
+
+
+void mrb_mruby_random_gem_init(mrb_state *mrb)
+{
+ struct RClass *random;
+ struct RClass *array = mrb->array_class;
+
+ mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
+
+ random = mrb_define_class(mrb, "Random", mrb->object_class);
+ MRB_SET_INSTANCE_TT(random, MRB_TT_DATA);
+ mrb_define_class_method(mrb, random, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
+ mrb_define_class_method(mrb, random, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
+
+ mrb_define_method(mrb, random, "initialize", mrb_random_init, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, random, "rand", mrb_random_rand, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, random, "srand", mrb_random_srand, MRB_ARGS_OPT(1));
+
+ mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, array, "shuffle!", mrb_ary_shuffle_bang, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, array, "sample", mrb_ary_sample, MRB_ARGS_OPT(2));
+
+ mrb_const_set(mrb, mrb_obj_value(random), mrb_intern_lit(mrb, "DEFAULT"),
+ mrb_obj_new(mrb, random, 0, NULL));
+}
+
+void mrb_mruby_random_gem_final(mrb_state *mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.h
new file mode 100644
index 00000000..a4785ae5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/src/random.h
@@ -0,0 +1,12 @@
+/*
+** random.h - Random module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRUBY_RANDOM_H
+#define MRUBY_RANDOM_H
+
+void mrb_mruby_random_gem_init(mrb_state *mrb);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/test/random.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/test/random.rb
new file mode 100644
index 00000000..1c59be3a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-random/test/random.rb
@@ -0,0 +1,88 @@
+##
+# Random Test
+
+assert("Random#srand") do
+ r1 = Random.new(123)
+ r2 = Random.new(123)
+ r1.rand == r2.rand
+end
+
+assert("Kernel::srand") do
+ srand(234)
+ r1 = rand
+ srand(234)
+ r2 = rand
+ r1 == r2
+end
+
+assert("Random::srand") do
+ Random.srand(345)
+ r1 = rand
+ srand(345)
+ r2 = Random.rand
+ r1 == r2
+end
+
+assert("fixnum") do
+ rand(3).class == Fixnum
+end
+
+assert("float") do
+ rand.class == Float
+end
+
+assert("Array#shuffle") do
+ ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ shuffled = ary.shuffle
+
+ ary == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and shuffled != ary and 10.times { |x| ary.include? x }
+end
+
+assert('Array#shuffle!') do
+ ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ ary.shuffle!
+
+ ary != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary.include? x }
+end
+
+assert("Array#shuffle(random)") do
+ assert_raise(TypeError) do
+ # this will cause an exception due to the wrong argument
+ [1, 2].shuffle "Not a Random instance"
+ end
+
+ # verify that the same seed causes the same results
+ ary1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ shuffle1 = ary1.shuffle Random.new 345
+ ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ shuffle2 = ary2.shuffle Random.new 345
+
+ ary1 != shuffle1 and 10.times { |x| shuffle1.include? x } and shuffle1 == shuffle2
+end
+
+assert('Array#shuffle!(random)') do
+ assert_raise(TypeError) do
+ # this will cause an exception due to the wrong argument
+ [1, 2].shuffle! "Not a Random instance"
+ end
+
+ # verify that the same seed causes the same results
+ ary1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ ary1.shuffle! Random.new 345
+ ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ ary2.shuffle! Random.new 345
+
+ ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2
+end
+
+assert('Array#sample checks input length after reading arguments') do
+ $ary = [1, 2, 3]
+ class ArrayChange
+ def to_i
+ $ary << 4
+ 4
+ end
+ end
+
+ assert_equal [1, 2, 3, 4], $ary.sample(ArrayChange.new).sort
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrbgem.rake
new file mode 100644
index 00000000..e6fa7df5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-range-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Range class extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrblib/range.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrblib/range.rb
new file mode 100644
index 00000000..e5d1fb07
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/mrblib/range.rb
@@ -0,0 +1,31 @@
+class Range
+ ##
+ # call-seq:
+ # rng.first -> obj
+ # rng.first(n) -> an_array
+ #
+ # Returns the first object in the range, or an array of the first +n+
+ # elements.
+ #
+ # (10..20).first #=> 10
+ # (10..20).first(3) #=> [10, 11, 12]
+ #
+ def first(*args)
+ return self.begin if args.empty?
+
+ raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1)" unless args.length == 1
+ nv = args[0]
+ raise TypeError, "no implicit conversion from nil to integer" if nv.nil?
+ raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless nv.respond_to?(:to_int)
+ n = nv.to_int
+ raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless n.kind_of?(Integer)
+ raise ArgumentError, "negative array size (or size too big)" unless 0 <= n
+ ary = []
+ each do |i|
+ break if n <= 0
+ ary.push(i)
+ n -= 1
+ end
+ ary
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/src/range.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/src/range.c
new file mode 100644
index 00000000..aca71cc0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/src/range.c
@@ -0,0 +1,176 @@
+#include <mruby.h>
+#include <mruby/range.h>
+#include <math.h>
+
+static mrb_bool
+r_le(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ if (mrb_fixnum_p(r)) {
+ mrb_int c = mrb_fixnum(r);
+ if (c == 0 || c == -1) return TRUE;
+ }
+
+ return FALSE;
+}
+
+static mrb_bool
+r_lt(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ return mrb_fixnum_p(r) && mrb_fixnum(r) == -1;
+}
+
+/*
+ * call-seq:
+ * rng.cover?(obj) -> true or false
+ *
+ * Returns <code>true</code> if +obj+ is between the begin and end of
+ * the range.
+ *
+ * This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
+ * and <code>begin <= obj < end</code> when #exclude_end? is +true+.
+ *
+ * ("a".."z").cover?("c") #=> true
+ * ("a".."z").cover?("5") #=> false
+ * ("a".."z").cover?("cc") #=> true
+ */
+static mrb_value
+mrb_range_cover(mrb_state *mrb, mrb_value range)
+{
+ mrb_value val;
+ struct RRange *r = mrb_range_ptr(mrb, range);
+ mrb_value beg, end;
+
+ mrb_get_args(mrb, "o", &val);
+
+ beg = r->edges->beg;
+ end = r->edges->end;
+
+ if (r_le(mrb, beg, val)) {
+ if (r->excl) {
+ if (r_lt(mrb, val, end))
+ return mrb_true_value();
+ }
+ else {
+ if (r_le(mrb, val, end))
+ return mrb_true_value();
+ }
+ }
+
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * rng.last -> obj
+ * rng.last(n) -> an_array
+ *
+ * Returns the last object in the range,
+ * or an array of the last +n+ elements.
+ *
+ * Note that with no arguments +last+ will return the object that defines
+ * the end of the range even if #exclude_end? is +true+.
+ *
+ * (10..20).last #=> 20
+ * (10...20).last #=> 20
+ * (10..20).last(3) #=> [18, 19, 20]
+ * (10...20).last(3) #=> [17, 18, 19]
+ */
+static mrb_value
+mrb_range_last(mrb_state *mrb, mrb_value range)
+{
+ mrb_value num;
+ mrb_value array;
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ if (mrb_get_args(mrb, "|o", &num) == 0) {
+ return r->edges->end;
+ }
+
+ array = mrb_funcall(mrb, range, "to_a", 0);
+ return mrb_funcall(mrb, array, "last", 1, mrb_to_int(mrb, num));
+}
+
+/*
+ * call-seq:
+ * rng.size -> num
+ *
+ * Returns the number of elements in the range. Both the begin and the end of
+ * the Range must be Numeric, otherwise nil is returned.
+ *
+ * (10..20).size #=> 11
+ * ('a'..'z').size #=> nil
+ */
+
+static mrb_value
+mrb_range_size(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_ptr(mrb, range);
+ mrb_value beg, end;
+ mrb_float beg_f, end_f;
+ mrb_bool num_p = TRUE;
+ mrb_bool excl;
+
+ beg = r->edges->beg;
+ end = r->edges->end;
+ excl = r->excl;
+ if (mrb_fixnum_p(beg)) {
+ beg_f = (mrb_float)mrb_fixnum(beg);
+ }
+ else if (mrb_float_p(beg)) {
+ beg_f = mrb_float(beg);
+ }
+ else {
+ num_p = FALSE;
+ }
+ if (mrb_fixnum_p(end)) {
+ end_f = (mrb_float)mrb_fixnum(end);
+ }
+ else if (mrb_float_p(end)) {
+ end_f = mrb_float(end);
+ }
+ else {
+ num_p = FALSE;
+ }
+ if (num_p) {
+ mrb_float n = end_f - beg_f;
+ mrb_float err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * MRB_FLOAT_EPSILON;
+
+ if (err>0.5) err=0.5;
+ if (excl) {
+ if (n<=0) return mrb_fixnum_value(0);
+ if (n<1)
+ n = 0;
+ else
+ n = floor(n - err);
+ }
+ else {
+ if (n<0) return mrb_fixnum_value(0);
+ n = floor(n + err);
+ }
+ if (isinf(n+1))
+ return mrb_float_value(mrb, INFINITY);
+ return mrb_fixnum_value((mrb_int)n+1);
+ }
+ return mrb_nil_value();
+}
+
+void
+mrb_mruby_range_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass * s = mrb_class_get(mrb, "Range");
+
+ mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, s, "last", mrb_range_last, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, s, "size", mrb_range_size, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_range_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/test/range.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/test/range.rb
new file mode 100644
index 00000000..efcbdabe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-range-ext/test/range.rb
@@ -0,0 +1,32 @@
+##
+# Range(Ext) Test
+
+assert('Range#cover?') do
+ assert_true ("a".."z").cover?("c")
+ assert_true !("a".."z").cover?("5")
+ assert_true ("a".."z").cover?("cc")
+end
+
+assert('Range#first') do
+ assert_equal 10, (10..20).first
+ assert_equal [10, 11, 12], (10..20).first(3)
+ assert_equal [0, 1, 2], (0..Float::INFINITY).first(3)
+end
+
+assert('Range#last') do
+ assert_equal 20, (10..20).last
+ assert_equal 20, (10...20).last
+ assert_equal [18, 19, 20], (10..20).last(3)
+ assert_equal [17, 18, 19], (10...20).last(3)
+end
+
+assert('Range#size') do
+ assert_equal 42, (1..42).size
+ assert_equal 41, (1...42).size
+ assert_equal 6, (1...6.3).size
+ assert_equal 5, (1...6.0).size
+ assert_equal 5, (1.1...6).size
+ assert_equal 15, (1.0..15.9).size
+ assert_equal Float::INFINITY, (0..Float::INFINITY).size
+ assert_nil ('a'..'z').size
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrbgem.rake
new file mode 100644
index 00000000..bc897243
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-sprintf') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'standard Kernel#sprintf method'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrblib/string.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrblib/string.rb
new file mode 100644
index 00000000..d7e55536
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/mrblib/string.rb
@@ -0,0 +1,9 @@
+class String
+ def %(args)
+ if args.is_a? Array
+ sprintf(self, *args)
+ else
+ sprintf(self, args)
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/kernel.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/kernel.c
new file mode 100644
index 00000000..946b43a8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/kernel.c
@@ -0,0 +1,30 @@
+/*
+** kernel.c - Kernel module suppliment
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+
+mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */
+
+void
+mrb_mruby_sprintf_gem_init(mrb_state* mrb)
+{
+ struct RClass *krn;
+
+ if (mrb->kernel_module == NULL) {
+ mrb->kernel_module = mrb_define_module(mrb, "Kernel"); /* Might be PARANOID. */
+ }
+ krn = mrb->kernel_module;
+
+ mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_ANY());
+ mrb_define_method(mrb, krn, "format", mrb_f_sprintf, MRB_ARGS_ANY());
+}
+
+void
+mrb_mruby_sprintf_gem_final(mrb_state* mrb)
+{
+ /* nothing to do. */
+}
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/sprintf.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/sprintf.c
new file mode 100644
index 00000000..d2069924
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/src/sprintf.c
@@ -0,0 +1,1113 @@
+/*
+** sprintf.c - Kernel.#sprintf
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <mruby/string.h>
+#include <mruby/hash.h>
+#include <mruby/numeric.h>
+#include <math.h>
+#include <ctype.h>
+
+#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
+#define BITSPERDIG MRB_INT_BIT
+#define EXTENDSIGN(n, l) (((~0U << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0U << (n)))
+
+mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value);
+static void fmt_setup(char*,size_t,int,int,mrb_int,mrb_int);
+
+static char*
+remove_sign_bits(char *str, int base)
+{
+ char *t;
+
+ t = str;
+ if (base == 16) {
+ while (*t == 'f') {
+ t++;
+ }
+ }
+ else if (base == 8) {
+ *t |= EXTENDSIGN(3, strlen(t));
+ while (*t == '7') {
+ t++;
+ }
+ }
+ else if (base == 2) {
+ while (*t == '1') {
+ t++;
+ }
+ }
+
+ return t;
+}
+
+static char
+sign_bits(int base, const char *p)
+{
+ char c;
+
+ switch (base) {
+ case 16:
+ if (*p == 'X') c = 'F';
+ else c = 'f';
+ break;
+ case 8:
+ c = '7'; break;
+ case 2:
+ c = '1'; break;
+ default:
+ c = '.'; break;
+ }
+ return c;
+}
+
+static mrb_value
+mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
+{
+ char buf[66], *b = buf + sizeof buf;
+ mrb_int num = mrb_fixnum(x);
+ uint64_t val = (uint64_t)num;
+ char d;
+
+ if (base != 2) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
+ }
+ if (val == 0) {
+ return mrb_str_new_lit(mrb, "0");
+ }
+ *--b = '\0';
+ do {
+ *--b = mrb_digitmap[(int)(val % base)];
+ } while (val /= base);
+
+ if (num < 0) {
+ b = remove_sign_bits(b, base);
+ switch (base) {
+ case 16: d = 'f'; break;
+ case 8: d = '7'; break;
+ case 2: d = '1'; break;
+ default: d = 0; break;
+ }
+
+ if (d && *b != d) {
+ *--b = d;
+ }
+ }
+
+ return mrb_str_new_cstr(mrb, b);
+}
+
+#define FNONE 0
+#define FSHARP 1
+#define FMINUS 2
+#define FPLUS 4
+#define FZERO 8
+#define FSPACE 16
+#define FWIDTH 32
+#define FPREC 64
+#define FPREC0 128
+
+#define CHECK(l) do {\
+/* int cr = ENC_CODERANGE(result);*/\
+ while ((l) >= bsiz - blen) {\
+ bsiz*=2;\
+ if (bsiz < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "too big specifier"); \
+ }\
+ mrb_str_resize(mrb, result, bsiz);\
+/* ENC_CODERANGE_SET(result, cr);*/\
+ buf = RSTRING_PTR(result);\
+} while (0)
+
+#define PUSH(s, l) do { \
+ CHECK(l);\
+ memcpy(&buf[blen], s, l);\
+ blen += (mrb_int)(l);\
+} while (0)
+
+#define FILL(c, l) do { \
+ CHECK(l);\
+ memset(&buf[blen], c, l);\
+ blen += (l);\
+} while (0)
+
+static void
+check_next_arg(mrb_state *mrb, int posarg, int nextarg)
+{
+ switch (posarg) {
+ case -1:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with numbered", mrb_fixnum_value(nextarg));
+ break;
+ case -2:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with named", mrb_fixnum_value(nextarg));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+check_pos_arg(mrb_state *mrb, int posarg, int n)
+{
+ if (posarg > 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)",
+ mrb_fixnum_value(n), mrb_fixnum_value(posarg));
+ }
+ if (posarg == -2) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n));
+ }
+ if (n < 1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %S$", mrb_fixnum_value(n));
+ }
+}
+
+static void
+check_name_arg(mrb_state *mrb, int posarg, const char *name, int len)
+{
+ if (posarg > 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after unnumbered(%S)",
+ mrb_str_new(mrb, (name), (len)), mrb_fixnum_value(posarg));
+ }
+ if (posarg == -1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after numbered", mrb_str_new(mrb, (name), (len)));
+ }
+}
+
+#define GETNEXTARG() (\
+ check_next_arg(mrb, posarg, nextarg),\
+ (posarg = nextarg++, GETNTHARG(posarg)))
+
+#define GETARG() (!mrb_undef_p(nextvalue) ? nextvalue : GETNEXTARG())
+
+#define GETPOSARG(n) (\
+ check_pos_arg(mrb, posarg, n),\
+ (posarg = -1, GETNTHARG(n)))
+
+#define GETNTHARG(nth) \
+ ((nth >= argc) ? (mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments"), mrb_undef_value()) : argv[nth])
+
+#define GETNAMEARG(id, name, len) (\
+ check_name_arg(mrb, posarg, name, len),\
+ (posarg = -2, mrb_hash_fetch(mrb, get_hash(mrb, &hash, argc, argv), id, mrb_undef_value())))
+
+#define GETNUM(n, val) \
+ for (; p < end && ISDIGIT(*p); p++) {\
+ int next_n = 10 * n + (*p - '0'); \
+ if (next_n / 10 != n) {\
+ mrb_raise(mrb, E_ARGUMENT_ERROR, #val " too big"); \
+ } \
+ n = next_n; \
+ } \
+ if (p >= end) { \
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "malformed format string - %*[0-9]"); \
+ }
+
+#define GETASTER(num) do { \
+ mrb_value tmp_v; \
+ t = p++; \
+ n = 0; \
+ GETNUM(n, val); \
+ if (*p == '$') { \
+ tmp_v = GETPOSARG(n); \
+ } \
+ else { \
+ tmp_v = GETNEXTARG(); \
+ p = t; \
+ } \
+ num = mrb_int(mrb, tmp_v); \
+} while (0)
+
+static mrb_value
+get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
+{
+ mrb_value tmp;
+
+ if (!mrb_undef_p(*hash)) return *hash;
+ if (argc != 2) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
+ }
+ tmp = mrb_check_convert_type(mrb, argv[1], MRB_TT_HASH, "Hash", "to_hash");
+ if (mrb_nil_p(tmp)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
+ }
+ return (*hash = tmp);
+}
+
+/*
+ * call-seq:
+ * format(format_string [, arguments...] ) -> string
+ * sprintf(format_string [, arguments...] ) -> string
+ *
+ * Returns the string resulting from applying <i>format_string</i> to
+ * any additional arguments. Within the format string, any characters
+ * other than format sequences are copied to the result.
+ *
+ * The syntax of a format sequence is follows.
+ *
+ * %[flags][width][.precision]type
+ *
+ * A format
+ * sequence consists of a percent sign, followed by optional flags,
+ * width, and precision indicators, then terminated with a field type
+ * character. The field type controls how the corresponding
+ * <code>sprintf</code> argument is to be interpreted, while the flags
+ * modify that interpretation.
+ *
+ * The field type characters are:
+ *
+ * Field | Integer Format
+ * ------+--------------------------------------------------------------
+ * b | Convert argument as a binary number.
+ * | Negative numbers will be displayed as a two's complement
+ * | prefixed with '..1'.
+ * B | Equivalent to 'b', but uses an uppercase 0B for prefix
+ * | in the alternative format by #.
+ * d | Convert argument as a decimal number.
+ * i | Identical to 'd'.
+ * o | Convert argument as an octal number.
+ * | Negative numbers will be displayed as a two's complement
+ * | prefixed with '..7'.
+ * u | Identical to 'd'.
+ * x | Convert argument as a hexadecimal number.
+ * | Negative numbers will be displayed as a two's complement
+ * | prefixed with '..f' (representing an infinite string of
+ * | leading 'ff's).
+ * X | Equivalent to 'x', but uses uppercase letters.
+ *
+ * Field | Float Format
+ * ------+--------------------------------------------------------------
+ * e | Convert floating point argument into exponential notation
+ * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
+ * | The precision specifies the number of digits after the decimal
+ * | point (defaulting to six).
+ * E | Equivalent to 'e', but uses an uppercase E to indicate
+ * | the exponent.
+ * f | Convert floating point argument as [-]ddd.dddddd,
+ * | where the precision specifies the number of digits after
+ * | the decimal point.
+ * g | Convert a floating point number using exponential form
+ * | if the exponent is less than -4 or greater than or
+ * | equal to the precision, or in dd.dddd form otherwise.
+ * | The precision specifies the number of significant digits.
+ * G | Equivalent to 'g', but use an uppercase 'E' in exponent form.
+ * a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
+ * | which is consisted from optional sign, "0x", fraction part
+ * | as hexadecimal, "p", and exponential part as decimal.
+ * A | Equivalent to 'a', but use uppercase 'X' and 'P'.
+ *
+ * Field | Other Format
+ * ------+--------------------------------------------------------------
+ * c | Argument is the numeric code for a single character or
+ * | a single character string itself.
+ * p | The valuing of argument.inspect.
+ * s | Argument is a string to be substituted. If the format
+ * | sequence contains a precision, at most that many characters
+ * | will be copied.
+ * % | A percent sign itself will be displayed. No argument taken.
+ *
+ * The flags modifies the behavior of the formats.
+ * The flag characters are:
+ *
+ * Flag | Applies to | Meaning
+ * ---------+---------------+-----------------------------------------
+ * space | bBdiouxX | Leave a space at the start of
+ * | aAeEfgG | non-negative numbers.
+ * | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use
+ * | | a minus sign with absolute value for
+ * | | negative values.
+ * ---------+---------------+-----------------------------------------
+ * (digit)$ | all | Specifies the absolute argument number
+ * | | for this field. Absolute and relative
+ * | | argument numbers cannot be mixed in a
+ * | | sprintf string.
+ * ---------+---------------+-----------------------------------------
+ * # | bBoxX | Use an alternative format.
+ * | aAeEfgG | For the conversions 'o', increase the precision
+ * | | until the first digit will be '0' if
+ * | | it is not formatted as complements.
+ * | | For the conversions 'x', 'X', 'b' and 'B'
+ * | | on non-zero, prefix the result with "0x",
+ * | | "0X", "0b" and "0B", respectively.
+ * | | For 'a', 'A', 'e', 'E', 'f', 'g', and 'G',
+ * | | force a decimal point to be added,
+ * | | even if no digits follow.
+ * | | For 'g' and 'G', do not remove trailing zeros.
+ * ---------+---------------+-----------------------------------------
+ * + | bBdiouxX | Add a leading plus sign to non-negative
+ * | aAeEfgG | numbers.
+ * | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use
+ * | | a minus sign with absolute value for
+ * | | negative values.
+ * ---------+---------------+-----------------------------------------
+ * - | all | Left-justify the result of this conversion.
+ * ---------+---------------+-----------------------------------------
+ * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
+ * | aAeEfgG | For 'o', 'x', 'X', 'b' and 'B', radix-1
+ * | (numeric fmt) | is used for negative numbers formatted as
+ * | | complements.
+ * ---------+---------------+-----------------------------------------
+ * * | all | Use the next argument as the field width.
+ * | | If negative, left-justify the result. If the
+ * | | asterisk is followed by a number and a dollar
+ * | | sign, use the indicated argument as the width.
+ *
+ * Examples of flags:
+ *
+ * # '+' and space flag specifies the sign of non-negative numbers.
+ * sprintf("%d", 123) #=> "123"
+ * sprintf("%+d", 123) #=> "+123"
+ * sprintf("% d", 123) #=> " 123"
+ *
+ * # '#' flag for 'o' increases number of digits to show '0'.
+ * # '+' and space flag changes format of negative numbers.
+ * sprintf("%o", 123) #=> "173"
+ * sprintf("%#o", 123) #=> "0173"
+ * sprintf("%+o", -123) #=> "-173"
+ * sprintf("%o", -123) #=> "..7605"
+ * sprintf("%#o", -123) #=> "..7605"
+ *
+ * # '#' flag for 'x' add a prefix '0x' for non-zero numbers.
+ * # '+' and space flag disables complements for negative numbers.
+ * sprintf("%x", 123) #=> "7b"
+ * sprintf("%#x", 123) #=> "0x7b"
+ * sprintf("%+x", -123) #=> "-7b"
+ * sprintf("%x", -123) #=> "..f85"
+ * sprintf("%#x", -123) #=> "0x..f85"
+ * sprintf("%#x", 0) #=> "0"
+ *
+ * # '#' for 'X' uses the prefix '0X'.
+ * sprintf("%X", 123) #=> "7B"
+ * sprintf("%#X", 123) #=> "0X7B"
+ *
+ * # '#' flag for 'b' add a prefix '0b' for non-zero numbers.
+ * # '+' and space flag disables complements for negative numbers.
+ * sprintf("%b", 123) #=> "1111011"
+ * sprintf("%#b", 123) #=> "0b1111011"
+ * sprintf("%+b", -123) #=> "-1111011"
+ * sprintf("%b", -123) #=> "..10000101"
+ * sprintf("%#b", -123) #=> "0b..10000101"
+ * sprintf("%#b", 0) #=> "0"
+ *
+ * # '#' for 'B' uses the prefix '0B'.
+ * sprintf("%B", 123) #=> "1111011"
+ * sprintf("%#B", 123) #=> "0B1111011"
+ *
+ * # '#' for 'e' forces to show the decimal point.
+ * sprintf("%.0e", 1) #=> "1e+00"
+ * sprintf("%#.0e", 1) #=> "1.e+00"
+ *
+ * # '#' for 'f' forces to show the decimal point.
+ * sprintf("%.0f", 1234) #=> "1234"
+ * sprintf("%#.0f", 1234) #=> "1234."
+ *
+ * # '#' for 'g' forces to show the decimal point.
+ * # It also disables stripping lowest zeros.
+ * sprintf("%g", 123.4) #=> "123.4"
+ * sprintf("%#g", 123.4) #=> "123.400"
+ * sprintf("%g", 123456) #=> "123456"
+ * sprintf("%#g", 123456) #=> "123456."
+ *
+ * The field width is an optional integer, followed optionally by a
+ * period and a precision. The width specifies the minimum number of
+ * characters that will be written to the result for this field.
+ *
+ * Examples of width:
+ *
+ * # padding is done by spaces, width=20
+ * # 0 or radix-1. <------------------>
+ * sprintf("%20d", 123) #=> " 123"
+ * sprintf("%+20d", 123) #=> " +123"
+ * sprintf("%020d", 123) #=> "00000000000000000123"
+ * sprintf("%+020d", 123) #=> "+0000000000000000123"
+ * sprintf("% 020d", 123) #=> " 0000000000000000123"
+ * sprintf("%-20d", 123) #=> "123 "
+ * sprintf("%-+20d", 123) #=> "+123 "
+ * sprintf("%- 20d", 123) #=> " 123 "
+ * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
+ *
+ * For
+ * numeric fields, the precision controls the number of decimal places
+ * displayed. For string fields, the precision determines the maximum
+ * number of characters to be copied from the string. (Thus, the format
+ * sequence <code>%10.10s</code> will always contribute exactly ten
+ * characters to the result.)
+ *
+ * Examples of precisions:
+ *
+ * # precision for 'd', 'o', 'x' and 'b' is
+ * # minimum number of digits <------>
+ * sprintf("%20.8d", 123) #=> " 00000123"
+ * sprintf("%20.8o", 123) #=> " 00000173"
+ * sprintf("%20.8x", 123) #=> " 0000007b"
+ * sprintf("%20.8b", 123) #=> " 01111011"
+ * sprintf("%20.8d", -123) #=> " -00000123"
+ * sprintf("%20.8o", -123) #=> " ..777605"
+ * sprintf("%20.8x", -123) #=> " ..ffff85"
+ * sprintf("%20.8b", -11) #=> " ..110101"
+ *
+ * # "0x" and "0b" for '#x' and '#b' is not counted for
+ * # precision but "0" for '#o' is counted. <------>
+ * sprintf("%#20.8d", 123) #=> " 00000123"
+ * sprintf("%#20.8o", 123) #=> " 00000173"
+ * sprintf("%#20.8x", 123) #=> " 0x0000007b"
+ * sprintf("%#20.8b", 123) #=> " 0b01111011"
+ * sprintf("%#20.8d", -123) #=> " -00000123"
+ * sprintf("%#20.8o", -123) #=> " ..777605"
+ * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
+ * sprintf("%#20.8b", -11) #=> " 0b..110101"
+ *
+ * # precision for 'e' is number of
+ * # digits after the decimal point <------>
+ * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
+ *
+ * # precision for 'f' is number of
+ * # digits after the decimal point <------>
+ * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
+ *
+ * # precision for 'g' is number of
+ * # significant digits <------->
+ * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
+ *
+ * # <------->
+ * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
+ *
+ * # precision for 's' is
+ * # maximum number of characters <------>
+ * sprintf("%20.8s", "string test") #=> " string t"
+ *
+ * Examples:
+ *
+ * sprintf("%d %04x", 123, 123) #=> "123 007b"
+ * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
+ * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
+ * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
+ * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
+ * sprintf("%u", -123) #=> "-123"
+ *
+ * For more complex formatting, Ruby supports a reference by name.
+ * %<name>s style uses format style, but %{name} style doesn't.
+ *
+ * Exapmles:
+ * sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
+ * #=> 1 : 2.000000
+ * sprintf("%{foo}f", { :foo => 1 })
+ * # => "1f"
+ */
+
+mrb_value
+mrb_f_sprintf(mrb_state *mrb, mrb_value obj)
+{
+ mrb_int argc;
+ mrb_value *argv;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ if (argc <= 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments");
+ return mrb_nil_value();
+ }
+ else {
+ return mrb_str_format(mrb, argc - 1, argv + 1, argv[0]);
+ }
+}
+
+mrb_value
+mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
+{
+ const char *p, *end;
+ char *buf;
+ mrb_int blen;
+ mrb_int bsiz;
+ mrb_value result;
+ mrb_int n;
+ mrb_int width;
+ mrb_int prec;
+ int nextarg = 1;
+ int posarg = 0;
+ mrb_value nextvalue;
+ mrb_value str;
+ mrb_value hash = mrb_undef_value();
+
+#define CHECK_FOR_WIDTH(f) \
+ if ((f) & FWIDTH) { \
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "width given twice"); \
+ } \
+ if ((f) & FPREC0) { \
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "width after precision"); \
+ }
+#define CHECK_FOR_FLAGS(f) \
+ if ((f) & FWIDTH) { \
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after width"); \
+ } \
+ if ((f) & FPREC0) { \
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "flag after precision"); \
+ }
+
+ ++argc;
+ --argv;
+ fmt = mrb_str_to_str(mrb, fmt);
+ p = RSTRING_PTR(fmt);
+ end = p + RSTRING_LEN(fmt);
+ blen = 0;
+ bsiz = 120;
+ result = mrb_str_new_capa(mrb, bsiz);
+ buf = RSTRING_PTR(result);
+ memset(buf, 0, bsiz);
+
+ for (; p < end; p++) {
+ const char *t;
+ mrb_sym id = 0;
+ int flags = FNONE;
+
+ for (t = p; t < end && *t != '%'; t++) ;
+ if (t + 1 == end) ++t;
+ PUSH(p, t - p);
+ if (t >= end)
+ goto sprint_exit; /* end of fmt string */
+
+ p = t + 1; /* skip '%' */
+
+ width = prec = -1;
+ nextvalue = mrb_undef_value();
+
+retry:
+ switch (*p) {
+ default:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - \\%%S", mrb_str_new(mrb, p, 1));
+ break;
+
+ case ' ':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FSPACE;
+ p++;
+ goto retry;
+
+ case '#':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FSHARP;
+ p++;
+ goto retry;
+
+ case '+':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FPLUS;
+ p++;
+ goto retry;
+
+ case '-':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FMINUS;
+ p++;
+ goto retry;
+
+ case '0':
+ CHECK_FOR_FLAGS(flags);
+ flags |= FZERO;
+ p++;
+ goto retry;
+
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ GETNUM(n, width);
+ if (*p == '$') {
+ if (!mrb_undef_p(nextvalue)) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %S$", mrb_fixnum_value(n));
+ }
+ nextvalue = GETPOSARG(n);
+ p++;
+ goto retry;
+ }
+ CHECK_FOR_WIDTH(flags);
+ width = n;
+ flags |= FWIDTH;
+ goto retry;
+
+ case '<':
+ case '{': {
+ const char *start = p;
+ char term = (*p == '<') ? '>' : '}';
+ mrb_value symname;
+
+ for (; p < end && *p != term; )
+ p++;
+ if (id) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%S after <%S>",
+ mrb_str_new(mrb, start, p - start + 1), mrb_sym2str(mrb, id));
+ }
+ symname = mrb_str_new(mrb, start + 1, p - start - 1);
+ id = mrb_intern_str(mrb, symname);
+ nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1));
+ if (mrb_undef_p(nextvalue)) {
+ mrb_raisef(mrb, E_KEY_ERROR, "key%S not found", mrb_str_new(mrb, start, p - start + 1));
+ }
+ if (term == '}') goto format_s;
+ p++;
+ goto retry;
+ }
+
+ case '*':
+ CHECK_FOR_WIDTH(flags);
+ flags |= FWIDTH;
+ GETASTER(width);
+ if (width < 0) {
+ flags |= FMINUS;
+ width = -width;
+ }
+ p++;
+ goto retry;
+
+ case '.':
+ if (flags & FPREC0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "precision given twice");
+ }
+ flags |= FPREC|FPREC0;
+
+ prec = 0;
+ p++;
+ if (*p == '*') {
+ GETASTER(prec);
+ if (prec < 0) { /* ignore negative precision */
+ flags &= ~FPREC;
+ }
+ p++;
+ goto retry;
+ }
+
+ GETNUM(prec, precision);
+ goto retry;
+
+ case '\n':
+ case '\0':
+ p--;
+ /* fallthrough */
+ case '%':
+ if (flags != FNONE) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format character - %");
+ }
+ PUSH("%", 1);
+ break;
+
+ case 'c': {
+ mrb_value val = GETARG();
+ mrb_value tmp;
+ char *c;
+
+ tmp = mrb_check_string_type(mrb, val);
+ if (!mrb_nil_p(tmp)) {
+ if (RSTRING_LEN(tmp) != 1) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character");
+ }
+ }
+ else if (mrb_fixnum_p(val)) {
+ mrb_int n = mrb_fixnum(val);
+
+ if (n < 0x80) {
+ char buf[1];
+
+ buf[0] = (char)n;
+ tmp = mrb_str_new(mrb, buf, 1);
+ }
+ else {
+ tmp = mrb_funcall(mrb, val, "chr", 0);
+ mrb_check_type(mrb, tmp, MRB_TT_STRING);
+ }
+ }
+ else {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
+ }
+ c = RSTRING_PTR(tmp);
+ n = RSTRING_LEN(tmp);
+ if (!(flags & FWIDTH)) {
+ PUSH(c, n);
+ }
+ else if ((flags & FMINUS)) {
+ PUSH(c, n);
+ if (width>0) FILL(' ', width-1);
+ }
+ else {
+ if (width>0) FILL(' ', width-1);
+ PUSH(c, n);
+ }
+ }
+ break;
+
+ case 's':
+ case 'p':
+ format_s:
+ {
+ mrb_value arg = GETARG();
+ mrb_int len;
+ mrb_int slen;
+
+ if (*p == 'p') arg = mrb_inspect(mrb, arg);
+ str = mrb_obj_as_string(mrb, arg);
+ len = RSTRING_LEN(str);
+ if (RSTRING(result)->flags & MRB_STR_EMBED) {
+ mrb_int tmp_n = len;
+ RSTRING(result)->flags &= ~MRB_STR_EMBED_LEN_MASK;
+ RSTRING(result)->flags |= tmp_n << MRB_STR_EMBED_LEN_SHIFT;
+ }
+ else {
+ RSTRING(result)->as.heap.len = blen;
+ }
+ if (flags&(FPREC|FWIDTH)) {
+ slen = RSTRING_LEN(str);
+ if (slen < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid mbstring sequence");
+ }
+ if ((flags&FPREC) && (prec < slen)) {
+ char *p = RSTRING_PTR(str) + prec;
+ slen = prec;
+ len = (mrb_int)(p - RSTRING_PTR(str));
+ }
+ /* need to adjust multi-byte string pos */
+ if ((flags&FWIDTH) && (width > slen)) {
+ width -= (int)slen;
+ if (!(flags&FMINUS)) {
+ FILL(' ', width);
+ }
+ PUSH(RSTRING_PTR(str), len);
+ if (flags&FMINUS) {
+ FILL(' ', width);
+ }
+ break;
+ }
+ }
+ PUSH(RSTRING_PTR(str), len);
+ }
+ break;
+
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'x':
+ case 'X':
+ case 'b':
+ case 'B':
+ case 'u': {
+ mrb_value val = GETARG();
+ char nbuf[68], *s;
+ const char *prefix = NULL;
+ int sign = 0, dots = 0;
+ char sc = 0;
+ mrb_int v = 0;
+ int base;
+ mrb_int len;
+
+ if (flags & FSHARP) {
+ switch (*p) {
+ case 'o': prefix = "0"; break;
+ case 'x': prefix = "0x"; break;
+ case 'X': prefix = "0X"; break;
+ case 'b': prefix = "0b"; break;
+ case 'B': prefix = "0B"; break;
+ default: break;
+ }
+ }
+
+ bin_retry:
+ switch (mrb_type(val)) {
+ case MRB_TT_FLOAT:
+ val = mrb_flo_to_fixnum(mrb, val);
+ if (mrb_fixnum_p(val)) goto bin_retry;
+ break;
+ case MRB_TT_STRING:
+ val = mrb_str_to_inum(mrb, val, 0, TRUE);
+ goto bin_retry;
+ case MRB_TT_FIXNUM:
+ v = mrb_fixnum(val);
+ break;
+ default:
+ val = mrb_Integer(mrb, val);
+ goto bin_retry;
+ }
+
+ switch (*p) {
+ case 'o':
+ base = 8; break;
+ case 'x':
+ case 'X':
+ base = 16; break;
+ case 'b':
+ case 'B':
+ base = 2; break;
+ case 'u':
+ case 'd':
+ case 'i':
+ sign = 1;
+ default:
+ base = 10; break;
+ }
+
+ if (sign) {
+ if (v >= 0) {
+ if (flags & FPLUS) {
+ sc = '+';
+ width--;
+ }
+ else if (flags & FSPACE) {
+ sc = ' ';
+ width--;
+ }
+ }
+ else {
+ sc = '-';
+ width--;
+ }
+ mrb_assert(base == 10);
+ snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
+ s = nbuf;
+ if (v < 0) s++; /* skip minus sign */
+ }
+ else {
+ s = nbuf;
+ if (v < 0) {
+ dots = 1;
+ }
+ switch (base) {
+ case 2:
+ if (v < 0) {
+ val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
+ }
+ else {
+ val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
+ }
+ strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1);
+ break;
+ case 8:
+ snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v);
+ break;
+ case 16:
+ snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v);
+ break;
+ }
+ if (v < 0) {
+ char d;
+
+ s = remove_sign_bits(s, base);
+ switch (base) {
+ case 16: d = 'f'; break;
+ case 8: d = '7'; break;
+ case 2: d = '1'; break;
+ default: d = 0; break;
+ }
+
+ if (d && *s != d) {
+ *--s = d;
+ }
+ }
+ }
+ {
+ size_t size;
+ size = strlen(s);
+ /* PARANOID: assert(size <= MRB_INT_MAX) */
+ len = (mrb_int)size;
+ }
+
+ if (*p == 'X') {
+ char *pp = s;
+ int c;
+ while ((c = (int)(unsigned char)*pp) != 0) {
+ *pp = toupper(c);
+ pp++;
+ }
+ }
+
+ if (prefix && !prefix[1]) { /* octal */
+ if (dots) {
+ prefix = NULL;
+ }
+ else if (len == 1 && *s == '0') {
+ len = 0;
+ if (flags & FPREC) prec--;
+ }
+ else if ((flags & FPREC) && (prec > len)) {
+ prefix = NULL;
+ }
+ }
+ else if (len == 1 && *s == '0') {
+ prefix = NULL;
+ }
+
+ if (prefix) {
+ size_t size;
+ size = strlen(prefix);
+ /* PARANOID: assert(size <= MRB_INT_MAX).
+ * this check is absolutely paranoid. */
+ width -= (mrb_int)size;
+ }
+
+ if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
+ prec = width;
+ width = 0;
+ }
+ else {
+ if (prec < len) {
+ if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
+ prec = len;
+ }
+ width -= prec;
+ }
+
+ if (!(flags&FMINUS) && width > 0) {
+ FILL(' ', width);
+ width = 0;
+ }
+
+ if (sc) PUSH(&sc, 1);
+
+ if (prefix) {
+ int plen = (int)strlen(prefix);
+ PUSH(prefix, plen);
+ }
+ if (dots) {
+ prec -= 2;
+ width -= 2;
+ PUSH("..", 2);
+ }
+
+ if (prec > len) {
+ CHECK(prec - len);
+ if ((flags & (FMINUS|FPREC)) != FMINUS) {
+ char c = '0';
+ FILL(c, prec - len);
+ } else if (v < 0) {
+ char c = sign_bits(base, p);
+ FILL(c, prec - len);
+ }
+ }
+ PUSH(s, len);
+ if (width > 0) {
+ FILL(' ', width);
+ }
+ }
+ break;
+
+ case 'f':
+ case 'g':
+ case 'G':
+ case 'e':
+ case 'E':
+ case 'a':
+ case 'A': {
+ mrb_value val = GETARG();
+ double fval;
+ int i, need = 6;
+ char fbuf[32];
+
+ fval = mrb_float(mrb_Float(mrb, val));
+ if (!isfinite(fval)) {
+ const char *expr;
+ const int elen = 3;
+ char sign = '\0';
+
+ if (isnan(fval)) {
+ expr = "NaN";
+ }
+ else {
+ expr = "Inf";
+ }
+ need = elen;
+ if (!isnan(fval) && fval < 0.0)
+ sign = '-';
+ else if (flags & (FPLUS|FSPACE))
+ sign = (flags & FPLUS) ? '+' : ' ';
+ if (sign)
+ ++need;
+ if ((flags & FWIDTH) && need < width)
+ need = width;
+
+ if (need < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "width too big");
+ }
+ FILL(' ', need);
+ if (flags & FMINUS) {
+ if (sign)
+ buf[blen - need--] = sign;
+ memcpy(&buf[blen - need], expr, elen);
+ }
+ else {
+ if (sign)
+ buf[blen - elen - 1] = sign;
+ memcpy(&buf[blen - elen], expr, elen);
+ }
+ break;
+ }
+
+ fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
+ need = 0;
+ if (*p != 'e' && *p != 'E') {
+ i = INT_MIN;
+ frexp(fval, &i);
+ if (i > 0)
+ need = BIT_DIGITS(i);
+ }
+ need += (flags&FPREC) ? prec : 6;
+ if ((flags&FWIDTH) && need < width)
+ need = width;
+ need += 20;
+ if (need <= 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR,
+ (width > prec ? "width too big" : "prec too big"));
+ }
+
+ CHECK(need);
+ n = snprintf(&buf[blen], need, fbuf, fval);
+ if (n < 0) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
+ }
+ blen += n;
+ }
+ break;
+ }
+ flags = FNONE;
+ }
+
+ sprint_exit:
+#if 0
+ /* XXX - We cannot validate the number of arguments if (digit)$ style used.
+ */
+ if (posarg >= 0 && nextarg < argc) {
+ const char *mesg = "too many arguments for format string";
+ if (mrb_test(ruby_debug)) mrb_raise(mrb, E_ARGUMENT_ERROR, mesg);
+ if (mrb_test(ruby_verbose)) mrb_warn(mrb, "%S", mrb_str_new_cstr(mrb, mesg));
+ }
+#endif
+ mrb_str_resize(mrb, result, blen);
+
+ return result;
+}
+
+static void
+fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec)
+{
+ char *end = buf + size;
+ int n;
+
+ *buf++ = '%';
+ if (flags & FSHARP) *buf++ = '#';
+ if (flags & FPLUS) *buf++ = '+';
+ if (flags & FMINUS) *buf++ = '-';
+ if (flags & FZERO) *buf++ = '0';
+ if (flags & FSPACE) *buf++ = ' ';
+
+ if (flags & FWIDTH) {
+ n = snprintf(buf, end - buf, "%d", (int)width);
+ buf += n;
+ }
+
+ if (flags & FPREC) {
+ n = snprintf(buf, end - buf, ".%d", (int)prec);
+ buf += n;
+ }
+
+ *buf++ = c;
+ *buf = '\0';
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/test/sprintf.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/test/sprintf.rb
new file mode 100644
index 00000000..e3b66ef9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-sprintf/test/sprintf.rb
@@ -0,0 +1,109 @@
+#assert('Kernel.sprintf') do
+#end
+
+assert('String#%') do
+ assert_equal "one=1", "one=%d" % 1
+ assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ]
+ assert_equal "123 < 456", "%{num} < %<str>s" % { num: 123, str: "456" }
+ assert_equal 15, ("%b" % (1<<14)).size
+end
+
+assert('String#% with inf') do
+ inf = Float::INFINITY
+
+ assert_equal "Inf", "%f" % inf
+ assert_equal "Inf", "%2f" % inf
+ assert_equal "Inf", "%3f" % inf
+ assert_equal " Inf", "%4f" % inf
+ assert_equal " Inf", "%5f" % inf
+
+ assert_equal "+Inf", "%+f" % inf
+ assert_equal "+Inf", "%+2f" % inf
+ assert_equal "+Inf", "%+3f" % inf
+ assert_equal "+Inf", "%+4f" % inf
+ assert_equal " +Inf", "%+5f" % inf
+
+ assert_equal "Inf", "%-f" % inf
+ assert_equal "Inf", "%-2f" % inf
+ assert_equal "Inf", "%-3f" % inf
+ assert_equal "Inf ", "%-4f" % inf
+ assert_equal "Inf ", "%-5f" % inf
+
+ assert_equal " Inf", "% f" % inf
+ assert_equal " Inf", "% 2f" % inf
+ assert_equal " Inf", "% 3f" % inf
+ assert_equal " Inf", "% 4f" % inf
+ assert_equal " Inf", "% 5f" % inf
+end
+
+assert('String#% with nan') do
+ nan = Float::NAN
+
+ assert_equal "NaN", "%f" % nan
+ assert_equal "NaN", "%2f" % nan
+ assert_equal "NaN", "%3f" % nan
+ assert_equal " NaN", "%4f" % nan
+ assert_equal " NaN", "%5f" % nan
+
+ assert_equal "+NaN", "%+f" % nan
+ assert_equal "+NaN", "%+2f" % nan
+ assert_equal "+NaN", "%+3f" % nan
+ assert_equal "+NaN", "%+4f" % nan
+ assert_equal " +NaN", "%+5f" % nan
+
+ assert_equal "NaN", "%-f" % nan
+ assert_equal "NaN", "%-2f" % nan
+ assert_equal "NaN", "%-3f" % nan
+ assert_equal "NaN ", "%-4f" % nan
+ assert_equal "NaN ", "%-5f" % nan
+
+ assert_equal " NaN", "% f" % nan
+ assert_equal " NaN", "% 2f" % nan
+ assert_equal " NaN", "% 3f" % nan
+ assert_equal " NaN", "% 4f" % nan
+ assert_equal " NaN", "% 5f" % nan
+end
+
+assert("String#% with invalid chr") do
+ begin
+ class Fixnum
+ alias_method :chr_, :chr if method_defined?(:chr)
+
+ def chr
+ nil
+ end
+ end
+
+ assert_raise TypeError do
+ "%c" % 0x80
+ end
+ ensure
+ class Fixnum
+ if method_defined?(:chr_)
+ alias_method :chr, :chr_
+ remove_method :chr_
+ end
+ end
+ end
+end
+
+assert("String#% %b") do
+ assert_equal("..10115", "%0b5" % -5)
+end
+
+assert("String#% %d") do
+ assert_equal(" 10", "%4d" % 10)
+ assert_equal("1000", "%4d" % 1000)
+ assert_equal("10000", "%4d" % 10000)
+end
+
+assert("String#% invalid format") do
+ assert_raise ArgumentError do
+ "%?" % ""
+ end
+end
+
+assert("String#% invalid format shared substring") do
+ fmt = ("x"*30+"%!")[0...-1]
+ assert_equal fmt, sprintf(fmt, "")
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrbgem.rake
new file mode 100644
index 00000000..9812f2cc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrbgem.rake
@@ -0,0 +1,6 @@
+MRuby::Gem::Specification.new('mruby-string-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'String class extension'
+ spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrblib/string.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrblib/string.rb
new file mode 100644
index 00000000..c3a7eb38
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/mrblib/string.rb
@@ -0,0 +1,355 @@
+class String
+
+ ##
+ # call-seq:
+ # String.try_convert(obj) -> string or nil
+ #
+ # Try to convert <i>obj</i> into a String, using to_str method.
+ # Returns converted string or nil if <i>obj</i> cannot be converted
+ # for any reason.
+ #
+ # String.try_convert("str") #=> "str"
+ # String.try_convert(/re/) #=> nil
+ #
+ def self.try_convert(obj)
+ if obj.respond_to?(:to_str)
+ obj.to_str
+ else
+ nil
+ end
+ end
+
+ ##
+ # call-seq:
+ # string.clear -> string
+ #
+ # Makes string empty.
+ #
+ # a = "abcde"
+ # a.clear #=> ""
+ #
+ def clear
+ self.replace("")
+ end
+
+ ##
+ # call-seq:
+ # str.lstrip -> new_str
+ #
+ # Returns a copy of <i>str</i> with leading whitespace removed. See also
+ # <code>String#rstrip</code> and <code>String#strip</code>.
+ #
+ # " hello ".lstrip #=> "hello "
+ # "hello".lstrip #=> "hello"
+ #
+ def lstrip
+ a = 0
+ z = self.size - 1
+ a += 1 while a <= z and " \f\n\r\t\v".include?(self[a])
+ (z >= 0) ? self[a..z] : ""
+ end
+
+ ##
+ # call-seq:
+ # str.rstrip -> new_str
+ #
+ # Returns a copy of <i>str</i> with trailing whitespace removed. See also
+ # <code>String#lstrip</code> and <code>String#strip</code>.
+ #
+ # " hello ".rstrip #=> " hello"
+ # "hello".rstrip #=> "hello"
+ #
+ def rstrip
+ a = 0
+ z = self.size - 1
+ z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z])
+ (z >= 0) ? self[a..z] : ""
+ end
+
+ ##
+ # call-seq:
+ # str.strip -> new_str
+ #
+ # Returns a copy of <i>str</i> with leading and trailing whitespace removed.
+ #
+ # " hello ".strip #=> "hello"
+ # "\tgoodbye\r\n".strip #=> "goodbye"
+ #
+ def strip
+ a = 0
+ z = self.size - 1
+ a += 1 while a <= z and " \f\n\r\t\v".include?(self[a])
+ z -= 1 while a <= z and " \f\n\r\t\v\0".include?(self[z])
+ (z >= 0) ? self[a..z] : ""
+ end
+
+ ##
+ # call-seq:
+ # str.lstrip! -> self or nil
+ #
+ # Removes leading whitespace from <i>str</i>, returning <code>nil</code> if no
+ # change was made. See also <code>String#rstrip!</code> and
+ # <code>String#strip!</code>.
+ #
+ # " hello ".lstrip #=> "hello "
+ # "hello".lstrip! #=> nil
+ #
+ def lstrip!
+ raise RuntimeError, "can't modify frozen String" if frozen?
+ s = self.lstrip
+ (s == self) ? nil : self.replace(s)
+ end
+
+ ##
+ # call-seq:
+ # str.rstrip! -> self or nil
+ #
+ # Removes trailing whitespace from <i>str</i>, returning <code>nil</code> if
+ # no change was made. See also <code>String#lstrip!</code> and
+ # <code>String#strip!</code>.
+ #
+ # " hello ".rstrip #=> " hello"
+ # "hello".rstrip! #=> nil
+ #
+ def rstrip!
+ raise RuntimeError, "can't modify frozen String" if frozen?
+ s = self.rstrip
+ (s == self) ? nil : self.replace(s)
+ end
+
+ ##
+ # call-seq:
+ # str.strip! -> str or nil
+ #
+ # Removes leading and trailing whitespace from <i>str</i>. Returns
+ # <code>nil</code> if <i>str</i> was not altered.
+ #
+ def strip!
+ raise RuntimeError, "can't modify frozen String" if frozen?
+ s = self.strip
+ (s == self) ? nil : self.replace(s)
+ end
+
+ ##
+ # call-seq:
+ # str.casecmp(other_str) -> -1, 0, +1 or nil
+ #
+ # Case-insensitive version of <code>String#<=></code>.
+ #
+ # "abcdef".casecmp("abcde") #=> 1
+ # "aBcDeF".casecmp("abcdef") #=> 0
+ # "abcdef".casecmp("abcdefg") #=> -1
+ # "abcdef".casecmp("ABCDEF") #=> 0
+ #
+ def casecmp(str)
+ self.downcase <=> str.to_str.downcase
+ rescue NoMethodError
+ raise TypeError, "no implicit conversion of #{str.class} into String"
+ end
+
+ def partition(sep)
+ raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String
+ n = index(sep)
+ unless n.nil?
+ m = n + sep.size
+ [ slice(0, n), sep, slice(m, size - m) ]
+ else
+ [ self, "", "" ]
+ end
+ end
+
+ def rpartition(sep)
+ raise TypeError, "type mismatch: #{sep.class} given" unless sep.is_a? String
+ n = rindex(sep)
+ unless n.nil?
+ m = n + sep.size
+ [ slice(0, n), sep, slice(m, size - m) ]
+ else
+ [ "", "", self ]
+ end
+ end
+
+ ##
+ # call-seq:
+ # str.slice!(fixnum) -> new_str or nil
+ # str.slice!(fixnum, fixnum) -> new_str or nil
+ # str.slice!(range) -> new_str or nil
+ # str.slice!(other_str) -> new_str or nil
+ #
+ # Deletes the specified portion from <i>str</i>, and returns the portion
+ # deleted.
+ #
+ # string = "this is a string"
+ # string.slice!(2) #=> "i"
+ # string.slice!(3..6) #=> " is "
+ # string.slice!("r") #=> "r"
+ # string #=> "thsa sting"
+ #
+ def slice!(arg1, arg2=nil)
+ raise RuntimeError, "can't modify frozen String" if frozen?
+ raise "wrong number of arguments (for 1..2)" if arg1.nil? && arg2.nil?
+
+ if !arg1.nil? && !arg2.nil?
+ idx = arg1
+ idx += self.size if arg1 < 0
+ if idx >= 0 && idx <= self.size && arg2 > 0
+ str = self[idx, arg2]
+ else
+ return nil
+ end
+ else
+ validated = false
+ if arg1.kind_of?(Range)
+ beg = arg1.begin
+ ed = arg1.end
+ beg += self.size if beg < 0
+ ed += self.size if ed < 0
+ ed -= 1 if arg1.exclude_end?
+ validated = true
+ elsif arg1.kind_of?(String)
+ validated = true
+ else
+ idx = arg1
+ idx += self.size if arg1 < 0
+ validated = true if idx >=0 && arg1 < self.size
+ end
+ if validated
+ str = self[arg1]
+ else
+ return nil
+ end
+ end
+ unless str.nil? || str == ""
+ if !arg1.nil? && !arg2.nil?
+ idx = arg1 >= 0 ? arg1 : self.size+arg1
+ str2 = self[0...idx] + self[idx+arg2..-1].to_s
+ else
+ if arg1.kind_of?(Range)
+ idx = beg >= 0 ? beg : self.size+beg
+ idx2 = ed>= 0 ? ed : self.size+ed
+ str2 = self[0...idx] + self[idx2+1..-1].to_s
+ elsif arg1.kind_of?(String)
+ idx = self.index(arg1)
+ str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx.nil?
+ else
+ idx = arg1 >= 0 ? arg1 : self.size+arg1
+ str2 = self[0...idx] + self[idx+1..-1].to_s
+ end
+ end
+ self.replace(str2) unless str2.nil?
+ end
+ str
+ end
+
+ ##
+ # call-seq:
+ # str.insert(index, other_str) -> str
+ #
+ # Inserts <i>other_str</i> before the character at the given
+ # <i>index</i>, modifying <i>str</i>. Negative indices count from the
+ # end of the string, and insert <em>after</em> the given character.
+ # The intent is insert <i>aString</i> so that it starts at the given
+ # <i>index</i>.
+ #
+ # "abcd".insert(0, 'X') #=> "Xabcd"
+ # "abcd".insert(3, 'X') #=> "abcXd"
+ # "abcd".insert(4, 'X') #=> "abcdX"
+ # "abcd".insert(-3, 'X') #=> "abXcd"
+ # "abcd".insert(-1, 'X') #=> "abcdX"
+ #
+ def insert(idx, str)
+ if idx == -1
+ return self << str
+ elsif idx < 0
+ idx += 1
+ end
+ self[idx, 0] = str
+ self
+ end
+
+ ##
+ # call-seq:
+ # str.ljust(integer, padstr=' ') -> new_str
+ #
+ # If <i>integer</i> is greater than the length of <i>str</i>, returns a new
+ # <code>String</code> of length <i>integer</i> with <i>str</i> left justified
+ # and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
+ #
+ # "hello".ljust(4) #=> "hello"
+ # "hello".ljust(20) #=> "hello "
+ # "hello".ljust(20, '1234') #=> "hello123412341234123"
+ def ljust(idx, padstr = ' ')
+ raise ArgumentError, 'zero width padding' if padstr == ''
+ return self if idx <= self.size
+ pad_repetitions = (idx / padstr.length).ceil
+ padding = (padstr * pad_repetitions)[0...(idx - self.length)]
+ self + padding
+ end
+
+ ##
+ # call-seq:
+ # str.rjust(integer, padstr=' ') -> new_str
+ #
+ # If <i>integer</i> is greater than the length of <i>str</i>, returns a new
+ # <code>String</code> of length <i>integer</i> with <i>str</i> right justified
+ # and padded with <i>padstr</i>; otherwise, returns <i>str</i>.
+ #
+ # "hello".rjust(4) #=> "hello"
+ # "hello".rjust(20) #=> " hello"
+ # "hello".rjust(20, '1234') #=> "123412341234123hello"
+ def rjust(idx, padstr = ' ')
+ raise ArgumentError, 'zero width padding' if padstr == ''
+ return self if idx <= self.size
+ pad_repetitions = (idx / padstr.length).ceil
+ padding = (padstr * pad_repetitions)[0...(idx - self.length)]
+ padding + self
+ end
+
+ def chars(&block)
+ if block_given?
+ self.split('').each do |i|
+ block.call(i)
+ end
+ self
+ else
+ self.split('')
+ end
+ end
+
+ def each_char(&block)
+ return to_enum :each_char unless block
+
+ split('').each do |i|
+ block.call(i)
+ end
+ self
+ end
+
+ def codepoints(&block)
+ len = self.size
+
+ if block_given?
+ self.split('').each do|x|
+ block.call(x.ord)
+ end
+ self
+ else
+ self.split('').map{|x| x.ord}
+ end
+ end
+ alias each_codepoint codepoints
+
+ ##
+ # call-seq:
+ # str.prepend(other_str) -> str
+ #
+ # Prepend---Prepend the given string to <i>str</i>.
+ #
+ # a = "world"
+ # a.prepend("hello ") #=> "hello world"
+ # a #=> "hello world"
+ def prepend(arg)
+ self[0, 0] = arg
+ self
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/src/string.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/src/string.c
new file mode 100644
index 00000000..6bc035d6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/src/string.c
@@ -0,0 +1,685 @@
+#include <string.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/string.h>
+#include <mruby/range.h>
+
+static mrb_value
+mrb_str_getbyte(mrb_state *mrb, mrb_value str)
+{
+ mrb_int pos;
+ mrb_get_args(mrb, "i", &pos);
+
+ if (pos < 0)
+ pos += RSTRING_LEN(str);
+ if (pos < 0 || RSTRING_LEN(str) <= pos)
+ return mrb_nil_value();
+
+ return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]);
+}
+
+static mrb_value
+mrb_str_setbyte(mrb_state *mrb, mrb_value str)
+{
+ mrb_int pos, byte;
+ long len;
+
+ mrb_get_args(mrb, "ii", &pos, &byte);
+
+ len = RSTRING_LEN(str);
+ if (pos < -len || len <= pos)
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos));
+ if (pos < 0)
+ pos += len;
+
+ mrb_str_modify(mrb, mrb_str_ptr(str));
+ byte &= 0xff;
+ RSTRING_PTR(str)[pos] = byte;
+ return mrb_fixnum_value((unsigned char)byte);
+}
+
+static mrb_value
+mrb_str_byteslice(mrb_state *mrb, mrb_value str)
+{
+ mrb_value a1;
+ mrb_int len;
+ int argc;
+
+ argc = mrb_get_args(mrb, "o|i", &a1, &len);
+ if (argc == 2) {
+ return mrb_str_substr(mrb, str, mrb_fixnum(a1), len);
+ }
+ switch (mrb_type(a1)) {
+ case MRB_TT_RANGE:
+ {
+ mrb_int beg;
+
+ len = RSTRING_LEN(str);
+ switch (mrb_range_beg_len(mrb, a1, &beg, &len, len, TRUE)) {
+ case 0: /* not range */
+ break;
+ case 1: /* range */
+ return mrb_str_substr(mrb, str, beg, len);
+ case 2: /* out of range */
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", a1);
+ break;
+ }
+ return mrb_nil_value();
+ }
+ case MRB_TT_FLOAT:
+ a1 = mrb_fixnum_value((mrb_int)mrb_float(a1));
+ /* fall through */
+ case MRB_TT_FIXNUM:
+ return mrb_str_substr(mrb, str, mrb_fixnum(a1), 1);
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong type of argument");
+ }
+ /* not reached */
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * str.swapcase! -> str or nil
+ *
+ * Equivalent to <code>String#swapcase</code>, but modifies the receiver in
+ * place, returning <i>str</i>, or <code>nil</code> if no changes were made.
+ * Note: case conversion is effective only in ASCII region.
+ */
+static mrb_value
+mrb_str_swapcase_bang(mrb_state *mrb, mrb_value str)
+{
+ char *p, *pend;
+ int modify = 0;
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ p = RSTRING_PTR(str);
+ pend = p + RSTRING_LEN(str);
+ while (p < pend) {
+ if (ISUPPER(*p)) {
+ *p = TOLOWER(*p);
+ modify = 1;
+ }
+ else if (ISLOWER(*p)) {
+ *p = TOUPPER(*p);
+ modify = 1;
+ }
+ p++;
+ }
+
+ if (modify) return str;
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * str.swapcase -> new_str
+ *
+ * Returns a copy of <i>str</i> with uppercase alphabetic characters converted
+ * to lowercase and lowercase characters converted to uppercase.
+ * Note: case conversion is effective only in ASCII region.
+ *
+ * "Hello".swapcase #=> "hELLO"
+ * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"
+ */
+static mrb_value
+mrb_str_swapcase(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_swapcase_bang(mrb, str);
+ return str;
+}
+
+static mrb_value mrb_fixnum_chr(mrb_state *mrb, mrb_value num);
+
+/*
+ * call-seq:
+ * str << integer -> str
+ * str.concat(integer) -> str
+ * str << obj -> str
+ * str.concat(obj) -> str
+ *
+ * Append---Concatenates the given object to <i>str</i>. If the object is a
+ * <code>Integer</code>, it is considered as a codepoint, and is converted
+ * to a character before concatenation.
+ *
+ * a = "hello "
+ * a << "world" #=> "hello world"
+ * a.concat(33) #=> "hello world!"
+ */
+static mrb_value
+mrb_str_concat_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ mrb_get_args(mrb, "o", &str);
+ if (mrb_fixnum_p(str))
+ str = mrb_fixnum_chr(mrb, str);
+ else
+ str = mrb_string_type(mrb, str);
+ mrb_str_concat(mrb, self, str);
+ return self;
+}
+
+/*
+ * call-seq:
+ * str.start_with?([prefixes]+) -> true or false
+ *
+ * Returns true if +str+ starts with one of the +prefixes+ given.
+ *
+ * "hello".start_with?("hell") #=> true
+ *
+ * # returns true if one of the prefixes matches.
+ * "hello".start_with?("heaven", "hell") #=> true
+ * "hello".start_with?("heaven", "paradise") #=> false
+ * "h".start_with?("heaven", "hell") #=> false
+ */
+static mrb_value
+mrb_str_start_with(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv, sub;
+ mrb_int argc, i;
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ for (i = 0; i < argc; i++) {
+ size_t len_l, len_r;
+ int ai = mrb_gc_arena_save(mrb);
+ sub = mrb_string_type(mrb, argv[i]);
+ mrb_gc_arena_restore(mrb, ai);
+ len_l = RSTRING_LEN(self);
+ len_r = RSTRING_LEN(sub);
+ if (len_l >= len_r) {
+ if (memcmp(RSTRING_PTR(self), RSTRING_PTR(sub), len_r) == 0) {
+ return mrb_true_value();
+ }
+ }
+ }
+ return mrb_false_value();
+}
+
+/*
+ * call-seq:
+ * str.end_with?([suffixes]+) -> true or false
+ *
+ * Returns true if +str+ ends with one of the +suffixes+ given.
+ */
+static mrb_value
+mrb_str_end_with(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv, sub;
+ mrb_int argc, i;
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ for (i = 0; i < argc; i++) {
+ size_t len_l, len_r;
+ int ai = mrb_gc_arena_save(mrb);
+ sub = mrb_string_type(mrb, argv[i]);
+ mrb_gc_arena_restore(mrb, ai);
+ len_l = RSTRING_LEN(self);
+ len_r = RSTRING_LEN(sub);
+ if (len_l >= len_r) {
+ if (memcmp(RSTRING_PTR(self) + (len_l - len_r),
+ RSTRING_PTR(sub),
+ len_r) == 0) {
+ return mrb_true_value();
+ }
+ }
+ }
+ return mrb_false_value();
+}
+
+static mrb_value
+mrb_str_hex(mrb_state *mrb, mrb_value self)
+{
+ return mrb_str_to_inum(mrb, self, 16, FALSE);
+}
+
+static mrb_value
+mrb_str_oct(mrb_state *mrb, mrb_value self)
+{
+ return mrb_str_to_inum(mrb, self, 8, FALSE);
+}
+
+/*
+ * call-seq:
+ * string.chr -> string
+ *
+ * Returns a one-character string at the beginning of the string.
+ *
+ * a = "abcde"
+ * a.chr #=> "a"
+ */
+static mrb_value
+mrb_str_chr(mrb_state *mrb, mrb_value self)
+{
+ return mrb_str_substr(mrb, self, 0, 1);
+}
+
+static mrb_value
+mrb_fixnum_chr(mrb_state *mrb, mrb_value num)
+{
+ mrb_int cp = mrb_fixnum(num);
+#ifdef MRB_UTF8_STRING
+ char utf8[4];
+ mrb_int len;
+
+ if (cp < 0 || 0x10FFFF < cp) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
+ }
+ if (cp < 0x80) {
+ utf8[0] = (char)cp;
+ len = 1;
+ }
+ else if (cp < 0x800) {
+ utf8[0] = (char)(0xC0 | (cp >> 6));
+ utf8[1] = (char)(0x80 | (cp & 0x3F));
+ len = 2;
+ }
+ else if (cp < 0x10000) {
+ utf8[0] = (char)(0xE0 | (cp >> 12));
+ utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
+ utf8[2] = (char)(0x80 | ( cp & 0x3F));
+ len = 3;
+ }
+ else {
+ utf8[0] = (char)(0xF0 | (cp >> 18));
+ utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
+ utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
+ utf8[3] = (char)(0x80 | ( cp & 0x3F));
+ len = 4;
+ }
+ return mrb_str_new(mrb, utf8, len);
+#else
+ char c;
+
+ if (cp < 0 || 0xff < cp) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
+ }
+ c = (char)cp;
+ return mrb_str_new(mrb, &c, 1);
+#endif
+}
+
+/*
+ * call-seq:
+ * string.lines -> array of string
+ *
+ * Returns strings per line;
+ *
+ * a = "abc\ndef"
+ * a.lines #=> ["abc\n", "def"]
+ */
+static mrb_value
+mrb_str_lines(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ mrb_value blk;
+ int ai;
+ mrb_int len;
+ mrb_value arg;
+ char *b = RSTRING_PTR(self);
+ char *p = b, *t;
+ char *e = b + RSTRING_LEN(self);
+
+ mrb_get_args(mrb, "&", &blk);
+
+ result = mrb_ary_new(mrb);
+ ai = mrb_gc_arena_save(mrb);
+ if (!mrb_nil_p(blk)) {
+ while (p < e) {
+ t = p;
+ while (p < e && *p != '\n') p++;
+ if (*p == '\n') p++;
+ len = (mrb_int) (p - t);
+ arg = mrb_str_new(mrb, t, len);
+ mrb_yield_argv(mrb, blk, 1, &arg);
+ mrb_gc_arena_restore(mrb, ai);
+ if (b != RSTRING_PTR(self)) {
+ ptrdiff_t diff = p - b;
+ b = RSTRING_PTR(self);
+ p = b + diff;
+ }
+ e = b + RSTRING_LEN(self);
+ }
+ return self;
+ }
+ while (p < e) {
+ t = p;
+ while (p < e && *p != '\n') p++;
+ if (*p == '\n') p++;
+ len = (mrb_int) (p - t);
+ mrb_ary_push(mrb, result, mrb_str_new(mrb, t, len));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ return result;
+}
+
+/*
+ * call-seq:
+ * string.succ -> string
+ *
+ * Returns next sequence of the string;
+ *
+ * a = "abc"
+ * a.succ #=> "abd"
+ */
+static mrb_value
+mrb_str_succ_bang(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ unsigned char *p, *e, *b, *t;
+ const char *prepend;
+ struct RString *s = mrb_str_ptr(self);
+ mrb_int l;
+
+ if (RSTRING_LEN(self) == 0)
+ return self;
+
+ mrb_str_modify(mrb, s);
+ l = RSTRING_LEN(self);
+ b = p = (unsigned char*) RSTRING_PTR(self);
+ t = e = p + l;
+ *(e--) = 0;
+
+ // find trailing ascii/number
+ while (e >= b) {
+ if (ISALNUM(*e))
+ break;
+ e--;
+ }
+ if (e < b) {
+ e = p + l - 1;
+ result = mrb_str_new_lit(mrb, "");
+ }
+ else {
+ // find leading letter of the ascii/number
+ b = e;
+ while (b > p) {
+ if (!ISALNUM(*b) || (ISALNUM(*b) && *b != '9' && *b != 'z' && *b != 'Z'))
+ break;
+ b--;
+ }
+ if (!ISALNUM(*b))
+ b++;
+ result = mrb_str_new(mrb, (char*) p, b - p);
+ }
+
+ while (e >= b) {
+ if (!ISALNUM(*e)) {
+ if (*e == 0xff) {
+ mrb_str_cat_lit(mrb, result, "\x01");
+ (*e) = 0;
+ }
+ else
+ (*e)++;
+ break;
+ }
+ prepend = NULL;
+ if (*e == '9') {
+ if (e == b) prepend = "1";
+ *e = '0';
+ }
+ else if (*e == 'z') {
+ if (e == b) prepend = "a";
+ *e = 'a';
+ }
+ else if (*e == 'Z') {
+ if (e == b) prepend = "A";
+ *e = 'A';
+ }
+ else {
+ (*e)++;
+ break;
+ }
+ if (prepend) mrb_str_cat_cstr(mrb, result, prepend);
+ e--;
+ }
+ result = mrb_str_cat(mrb, result, (char*) b, t - b);
+ l = RSTRING_LEN(result);
+ mrb_str_resize(mrb, self, l);
+ memcpy(RSTRING_PTR(self), RSTRING_PTR(result), l);
+ return self;
+}
+
+static mrb_value
+mrb_str_succ(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_succ_bang(mrb, str);
+ return str;
+}
+
+#ifdef MRB_UTF8_STRING
+static const char utf8len_codepage_zero[256] =
+{
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+static mrb_int
+utf8code(unsigned char* p)
+{
+ mrb_int len;
+
+ if (p[0] < 0x80)
+ return p[0];
+
+ len = utf8len_codepage_zero[p[0]];
+ if (len > 1 && (p[1] & 0xc0) == 0x80) {
+ if (len == 2)
+ return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
+ if ((p[2] & 0xc0) == 0x80) {
+ if (len == 3)
+ return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
+ + (p[2] & 0x3f);
+ if ((p[3] & 0xc0) == 0x80) {
+ if (len == 4)
+ return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
+ + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f);
+ if ((p[4] & 0xc0) == 0x80) {
+ if (len == 5)
+ return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
+ + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
+ + (p[4] & 0x3f);
+ if ((p[5] & 0xc0) == 0x80 && len == 6)
+ return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
+ + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
+ + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f);
+ }
+ }
+ }
+ }
+ return p[0];
+}
+
+static mrb_value
+mrb_str_ord(mrb_state* mrb, mrb_value str)
+{
+ if (RSTRING_LEN(str) == 0)
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string");
+ return mrb_fixnum_value(utf8code((unsigned char*) RSTRING_PTR(str)));
+}
+#else
+static mrb_value
+mrb_str_ord(mrb_state* mrb, mrb_value str)
+{
+ if (RSTRING_LEN(str) == 0)
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string");
+ return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[0]);
+}
+#endif
+
+static mrb_bool
+all_digits_p(const char *s, mrb_int len)
+{
+ while (len-- > 0) {
+ if (!ISDIGIT(*s)) return FALSE;
+ s++;
+ }
+ return TRUE;
+}
+
+/*
+ * call-seq:
+ * str.upto(other_str, exclusive=false) {|s| block } -> str
+ * str.upto(other_str, exclusive=false) -> an_enumerator
+ *
+ * Iterates through successive values, starting at <i>str</i> and
+ * ending at <i>other_str</i> inclusive, passing each value in turn to
+ * the block. The <code>String#succ</code> method is used to generate
+ * each value. If optional second argument exclusive is omitted or is false,
+ * the last value will be included; otherwise it will be excluded.
+ *
+ * If no block is given, an enumerator is returned instead.
+ *
+ * "a8".upto("b6") {|s| print s, ' ' }
+ * for s in "a8".."b6"
+ * print s, ' '
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * a8 a9 b0 b1 b2 b3 b4 b5 b6
+ * a8 a9 b0 b1 b2 b3 b4 b5 b6
+ *
+ * If <i>str</i> and <i>other_str</i> contains only ascii numeric characters,
+ * both are recognized as decimal numbers. In addition, the width of
+ * string (e.g. leading zeros) is handled appropriately.
+ *
+ * "9".upto("11").to_a #=> ["9", "10", "11"]
+ * "25".upto("5").to_a #=> []
+ * "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"]
+ */
+static mrb_value
+mrb_str_upto(mrb_state *mrb, mrb_value beg)
+{
+ mrb_value end;
+ mrb_value exclusive = mrb_false_value();
+ mrb_value block = mrb_nil_value();
+ mrb_value current, after_end;
+ mrb_int n;
+ mrb_bool excl;
+
+ mrb_get_args(mrb, "o|o&", &end, &exclusive, &block);
+
+ if (mrb_nil_p(block)) {
+ return mrb_funcall(mrb, beg, "to_enum", 3, mrb_symbol_value(mrb_intern_lit(mrb, "upto")), end, exclusive);
+ }
+ end = mrb_string_type(mrb, end);
+ excl = mrb_test(exclusive);
+
+ /* single character */
+ if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 &&
+ ISASCII(RSTRING_PTR(beg)[0]) && ISASCII(RSTRING_PTR(end)[0])) {
+ char c = RSTRING_PTR(beg)[0];
+ char e = RSTRING_PTR(end)[0];
+ int ai = mrb_gc_arena_save(mrb);
+
+ if (c > e || (excl && c == e)) return beg;
+ for (;;) {
+ mrb_yield(mrb, block, mrb_str_new(mrb, &c, 1));
+ mrb_gc_arena_restore(mrb, ai);
+ if (!excl && c == e) break;
+ c++;
+ if (excl && c == e) break;
+ }
+ return beg;
+ }
+ /* both edges are all digits */
+ if (ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0]) &&
+ all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
+ all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
+ mrb_int min_width = RSTRING_LEN(beg);
+ mrb_int bi = mrb_int(mrb, mrb_str_to_inum(mrb, beg, 10, FALSE));
+ mrb_int ei = mrb_int(mrb, mrb_str_to_inum(mrb, end, 10, FALSE));
+ int ai = mrb_gc_arena_save(mrb);
+
+ while (bi <= ei) {
+ mrb_value ns, str;
+
+ if (excl && bi == ei) break;
+ ns = mrb_format(mrb, "%S", mrb_fixnum_value(bi));
+ if (min_width > RSTRING_LEN(ns)) {
+ str = mrb_str_new(mrb, NULL, min_width);
+ memset(RSTRING_PTR(str), '0', min_width-RSTRING_LEN(ns));
+ memcpy(RSTRING_PTR(str)+min_width-RSTRING_LEN(ns),
+ RSTRING_PTR(ns), RSTRING_LEN(ns));
+ }
+ else {
+ str = ns;
+ }
+ mrb_yield(mrb, block, str);
+ mrb_gc_arena_restore(mrb, ai);
+ bi++;
+ }
+
+ return beg;
+ }
+ /* normal case */
+ n = mrb_int(mrb, mrb_funcall(mrb, beg, "<=>", 1, end));
+ if (n > 0 || (excl && n == 0)) return beg;
+
+ after_end = mrb_funcall(mrb, end, "succ", 0);
+ current = mrb_str_dup(mrb, beg);
+ while (!mrb_str_equal(mrb, current, after_end)) {
+ int ai = mrb_gc_arena_save(mrb);
+ mrb_value next = mrb_nil_value();
+ if (excl || !mrb_str_equal(mrb, current, end))
+ next = mrb_funcall(mrb, current, "succ", 0);
+ mrb_yield(mrb, block, current);
+ if (mrb_nil_p(next)) break;
+ current = mrb_str_to_str(mrb, next);
+ if (excl && mrb_str_equal(mrb, current, end)) break;
+ if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
+ break;
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ return beg;
+}
+
+void
+mrb_mruby_string_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass * s = mrb->string_class;
+
+ mrb_define_method(mrb, s, "dump", mrb_str_dump, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, s, "setbyte", mrb_str_setbyte, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, s, "swapcase!", mrb_str_swapcase_bang, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "swapcase", mrb_str_swapcase, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "concat", mrb_str_concat_m, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, s, "<<", mrb_str_concat_m, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, s, "start_with?", mrb_str_start_with, MRB_ARGS_REST());
+ mrb_define_method(mrb, s, "end_with?", mrb_str_end_with, MRB_ARGS_REST());
+ mrb_define_method(mrb, s, "hex", mrb_str_hex, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "oct", mrb_str_oct, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "lines", mrb_str_lines, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "succ", mrb_str_succ, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE());
+ mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ"));
+ mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!"));
+ mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "upto", mrb_str_upto, MRB_ARGS_ANY());
+
+ mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_string_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/test/string.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/test/string.rb
new file mode 100644
index 00000000..2a568c7d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-string-ext/test/string.rb
@@ -0,0 +1,667 @@
+##
+# String(Ext) Test
+
+UTF8STRING = ("\343\201\202".size == 1)
+
+assert('String.try_convert') do
+ assert_nil String.try_convert(nil)
+ assert_nil String.try_convert(:foo)
+ assert_equal "", String.try_convert("")
+ assert_equal "1,2,3", String.try_convert("1,2,3")
+end
+
+assert('String#getbyte') do
+ str1 = "hello"
+ bytes1 = [104, 101, 108, 108, 111]
+ assert_equal bytes1[0], str1.getbyte(0)
+ assert_equal bytes1[-1], str1.getbyte(-1)
+ assert_equal bytes1[6], str1.getbyte(6)
+
+ str2 = "\xFF"
+ bytes2 = [0xFF]
+ assert_equal bytes2[0], str2.getbyte(0)
+end
+
+assert('String#setbyte') do
+ str1 = "hello"
+ h = "H".getbyte(0)
+ str1.setbyte(0, h)
+ assert_equal(h, str1.getbyte(0))
+ assert_equal("Hello", str1)
+end
+
+assert("String#setbyte raises IndexError if arg conversion resizes String") do
+ $s = "01234\n"
+ class Tmp
+ def to_i
+ $s.chomp! ''
+ 95
+ end
+ end
+ tmp = Tmp.new
+ assert_raise(IndexError) { $s.setbyte(5, tmp) }
+end
+
+assert('String#byteslice') do
+ str1 = "hello"
+ assert_equal("e", str1.byteslice(1))
+ assert_equal("o", str1.byteslice(-1))
+ assert_equal("ell", str1.byteslice(1..3))
+ assert_equal("el", str1.byteslice(1...3))
+end
+
+assert('String#dump') do
+ ("\1" * 100).dump # should not raise an exception - regress #1210
+ "\0".inspect == "\"\\000\"" and
+ "foo".dump == "\"foo\""
+end
+
+assert('String#strip') do
+ s = " abc "
+ "".strip == "" and " \t\r\n\f\v".strip == "" and
+ "\0a\0".strip == "\0a" and
+ "abc".strip == "abc" and
+ " abc".strip == "abc" and
+ "abc ".strip == "abc" and
+ " abc ".strip == "abc" and
+ s == " abc "
+end
+
+assert('String#lstrip') do
+ s = " abc "
+ s.lstrip
+ "".lstrip == "" and " \t\r\n\f\v".lstrip == "" and
+ "\0a\0".lstrip == "\0a\0" and
+ "abc".lstrip == "abc" and
+ " abc".lstrip == "abc" and
+ "abc ".lstrip == "abc " and
+ " abc ".lstrip == "abc " and
+ s == " abc "
+end
+
+assert('String#rstrip') do
+ s = " abc "
+ s.rstrip
+ "".rstrip == "" and " \t\r\n\f\v".rstrip == "" and
+ "\0a\0".rstrip == "\0a" and
+ "abc".rstrip == "abc" and
+ " abc".rstrip == " abc" and
+ "abc ".rstrip == "abc" and
+ " abc ".rstrip == " abc" and
+ s == " abc "
+end
+
+assert('String#strip!') do
+ s = " abc "
+ t = "abc"
+ s.strip! == "abc" and s == "abc" and t.strip! == nil
+end
+
+assert('String#lstrip!') do
+ s = " abc "
+ t = "abc "
+ s.lstrip! == "abc " and s == "abc " and t.lstrip! == nil
+end
+
+assert('String#rstrip!') do
+ s = " abc "
+ t = " abc"
+ s.rstrip! == " abc" and s == " abc" and t.rstrip! == nil
+end
+
+assert('String#swapcase') do
+ assert_equal "hELLO", "Hello".swapcase
+ assert_equal "CyBeR_pUnK11", "cYbEr_PuNk11".swapcase
+end
+
+assert('String#swapcase!') do
+ s = "Hello"
+ t = s.clone
+ t.swapcase!
+ assert_equal s.swapcase, t
+end
+
+assert('String#concat') do
+ assert_equal "Hello World!", "Hello " << "World" << 33
+ assert_equal "Hello World!", "Hello ".concat("World").concat(33)
+
+ o = Object.new
+ def o.to_str
+ "to_str"
+ end
+ assert_equal "hi to_str", "hi " << o
+
+ assert_raise(TypeError) { "".concat(Object.new) }
+end
+
+assert('String#casecmp') do
+ assert_equal 1, "abcdef".casecmp("abcde")
+ assert_equal 0, "aBcDeF".casecmp("abcdef")
+ assert_equal(-1, "abcdef".casecmp("abcdefg"))
+ assert_equal 0, "abcdef".casecmp("ABCDEF")
+ o = Object.new
+ def o.to_str
+ "ABCDEF"
+ end
+ assert_equal 0, "abcdef".casecmp(o)
+end
+
+assert('String#start_with?') do
+ assert_true "hello".start_with?("heaven", "hell")
+ assert_true !"hello".start_with?("heaven", "paradise")
+ assert_true !"h".start_with?("heaven", "hell")
+ assert_raise TypeError do "hello".start_with?(true) end
+end
+
+assert('String#end_with?') do
+ assert_true "string".end_with?("ing", "mng")
+ assert_true !"string".end_with?("str", "tri")
+ assert_true !"ng".end_with?("ing", "mng")
+ assert_raise TypeError do "hello".end_with?(true) end
+end
+
+assert('String#partition') do
+ assert_equal ["a", "x", "axa"], "axaxa".partition("x")
+ assert_equal ["aaaaa", "", ""], "aaaaa".partition("x")
+ assert_equal ["", "", "aaaaa"], "aaaaa".partition("")
+ assert_equal ["", "a", "aaaa"], "aaaaa".partition("a")
+ assert_equal ["aaaa", "b", ""], "aaaab".partition("b")
+ assert_equal ["", "b", "aaaa"], "baaaa".partition("b")
+ assert_equal ["", "", ""], "".partition("a")
+end
+
+assert('String#rpartition') do
+ assert_equal ["axa", "x", "a"], "axaxa".rpartition("x")
+ assert_equal ["", "", "aaaaa"], "aaaaa".rpartition("x")
+ assert_equal ["aaaaa", "", ""], "aaaaa".rpartition("")
+ assert_equal ["aaaa", "a", ""], "aaaaa".rpartition("a")
+ assert_equal ["aaaa", "b", ""], "aaaab".rpartition("b")
+ assert_equal ["", "b", "aaaa"], "baaaa".rpartition("b")
+ assert_equal ["", "", ""], "".rpartition("a")
+end
+
+assert('String#hex') do
+ assert_equal 16, "10".hex
+ assert_equal 255, "ff".hex
+ assert_equal 16, "0x10".hex
+ assert_equal (-16), "-0x10".hex
+ assert_equal 0, "xyz".hex
+ assert_equal 16, "10z".hex
+ assert_equal 16, "1_0".hex
+ assert_equal 0, "".hex
+end
+
+assert('String#oct') do
+ assert_equal 8, "10".oct
+ assert_equal 7, "7".oct
+ assert_equal 0, "8".oct
+ assert_equal 0, "9".oct
+ assert_equal 0, "xyz".oct
+ assert_equal 8, "10z".oct
+ assert_equal 8, "1_0".oct
+ assert_equal 8, "010".oct
+ assert_equal (-8), "-10".oct
+end
+
+assert('String#chr') do
+ assert_equal "a", "abcde".chr
+ # test Fixnum#chr as well
+ assert_equal "a", 97.chr
+end
+
+assert('String#lines') do
+ assert_equal ["Hel\n", "lo\n", "World!"], "Hel\nlo\nWorld!".lines
+ assert_equal ["Hel\n", "lo\n", "World!\n"], "Hel\nlo\nWorld!\n".lines
+ assert_equal ["\n", "\n", "\n"], "\n\n\n".lines
+ assert_equal [], "".lines
+end
+
+assert('String#clear') do
+ # embed string
+ s = "foo"
+ assert_equal("", s.clear)
+ assert_equal("", s)
+
+ # not embed string and not shared string
+ s = "foo" * 100
+ a = s
+ assert_equal("", s.clear)
+ assert_equal("", s)
+ assert_equal("", a)
+
+ # shared string
+ s = "foo" * 100
+ a = s[10, 90] # create shared string
+ assert_equal("", s.clear) # clear
+ assert_equal("", s) # s is cleared
+ assert_not_equal("", a) # a should not be affected
+end
+
+assert('String#slice!') do
+ a = "AooBar"
+ b = a.dup
+ assert_equal "A", a.slice!(0)
+ assert_equal "AooBar", b
+
+ a = "FooBar"
+ assert_equal "r", a.slice!(-1)
+ assert_equal "FooBa", a
+
+ a = "FooBar"
+ assert_nil a.slice!(6)
+ assert_nil a.slice!(-7)
+ assert_equal "FooBar", a
+
+ a = "FooBar"
+ assert_equal "Foo", a.slice!(0, 3)
+ assert_equal "Bar", a
+
+ a = "FooBar"
+ assert_equal "Bar", a.slice!(-3, 3)
+ assert_equal "Foo", a
+
+ a = "FooBar"
+ assert_equal "", a.slice!(6, 2)
+ assert_equal "FooBar", a
+
+ a = "FooBar"
+ assert_nil a.slice!(-7,10)
+ assert_equal "FooBar", a
+
+ a = "FooBar"
+ assert_equal "Foo", a.slice!(0..2)
+ assert_equal "Bar", a
+
+ a = "FooBar"
+ assert_equal "Bar", a.slice!(-3..-1)
+ assert_equal "Foo", a
+
+ a = "FooBar"
+ assert_equal "", a.slice!(6..2)
+ assert_equal "FooBar", a
+
+ a = "FooBar"
+ assert_nil a.slice!(-10..-7)
+ assert_equal "FooBar", a
+
+ a = "FooBar"
+ assert_equal "Foo", a.slice!("Foo")
+ assert_equal "Bar", a
+
+ a = "FooBar"
+ assert_nil a.slice!("xyzzy")
+ assert_equal "FooBar", a
+
+ assert_raise(ArgumentError) { "foo".slice! }
+end
+
+assert('String#succ') do
+ assert_equal "", "".succ
+ assert_equal "1", "0".succ
+ assert_equal "10", "9".succ
+ assert_equal "01", "00".succ
+ assert_equal "a1", "a0".succ
+ assert_equal "A1", "A0".succ
+ assert_equal "10", "09".succ
+ assert_equal "b0", "a9".succ
+ assert_equal "B0", "A9".succ
+
+ assert_equal "b", "a".succ
+ assert_equal "aa", "z".succ
+ assert_equal "ab", "aa".succ
+ assert_equal "Ab", "Aa".succ
+ assert_equal "0b", "0a".succ
+ assert_equal "ba", "az".succ
+ assert_equal "Ba", "Az".succ
+ assert_equal "1a", "0z".succ
+
+ assert_equal "B", "A".succ
+ assert_equal "AA", "Z".succ
+ assert_equal "AB", "AA".succ
+ assert_equal "aB", "aA".succ
+ assert_equal "0B", "0A".succ
+ assert_equal "BA", "AZ".succ
+ assert_equal "bA", "aZ".succ
+ assert_equal "1A", "0Z".succ
+
+ assert_equal ".", "-".succ
+ assert_equal "\x01\x00", "\xff".succ
+ assert_equal "-b", "-a".succ
+ assert_equal "-aa", "-z".succ
+ assert_equal "-a-b-", "-a-a-".succ
+ assert_equal "-b-", "-a-".succ
+ assert_equal "-aa-", "-z-".succ
+ assert_equal "あb", "あa".succ
+ assert_equal "あba", "あaz".succ
+
+ a = ""; a.succ!
+ assert_equal "", a
+ a = "0"; a.succ!
+ assert_equal "1", a
+ a = "9"; a.succ!
+ assert_equal "10", a
+ a = "00"; a.succ!
+ assert_equal "01", a
+ a = "a0"; a.succ!
+ assert_equal "a1", a
+ a = "A0"; a.succ!
+ assert_equal "A1", a
+ a = "09"; a.succ!
+ assert_equal "10", a
+ a = "a9"; a.succ!
+ assert_equal "b0", a
+ a = "A9"; a.succ!
+ assert_equal "B0", a
+
+ a = "a"; a.succ!
+ assert_equal "b", a
+ a = "z"; a.succ!
+ assert_equal "aa", a
+ a = "aa"; a.succ!
+ assert_equal "ab", a
+ a = "Aa"; a.succ!
+ assert_equal "Ab", a
+ a = "0a"; a.succ!
+ assert_equal "0b", a
+ a = "az"; a.succ!
+ assert_equal "ba", a
+ a = "Az"; a.succ!
+ assert_equal "Ba", a
+ a = "0z"; a.succ!
+ assert_equal "1a", a
+
+ a = "A"; a.succ!
+ assert_equal "B", a
+ a = "Z"; a.succ!
+ assert_equal "AA", a
+ a = "AA"; a.succ!
+ assert_equal "AB", a
+ a = "aA"; a.succ!
+ assert_equal "aB", a
+ a = "0A"; a.succ!
+ assert_equal "0B", a
+ a = "AZ"; a.succ!
+ assert_equal "BA", a
+ a = "aZ"; a.succ!
+ assert_equal "bA", a
+ a = "0Z"; a.succ!
+ assert_equal "1A", a
+
+ a = "-"; a.succ!
+ assert_equal ".", a
+ a = "\xff"; a.succ!
+ assert_equal "\x01\x00", a
+ a = "-a"; a.succ!
+ assert_equal "-b", a
+ a = "-z"; a.succ!
+ assert_equal "-aa", a
+ a = "-a-a-"; a.succ!
+ assert_equal "-a-b-", a
+ a = "-a-"; a.succ!
+ assert_equal "-b-", a
+ a = "-z-"; a.succ!
+ assert_equal "-aa-", a
+ a = "あb"; a.succ!
+ assert_equal "あc", a
+ a = "あaz"; a.succ!
+ assert_equal "あba", a
+end
+
+assert('String#next') do
+ assert_equal "01", "00".next
+
+ a = "00"; a.next!
+ assert_equal "01", a
+end
+
+assert('String#insert') do
+ assert_equal "Xabcd", "abcd".insert(0, 'X')
+ assert_equal "abcXd", "abcd".insert(3, 'X')
+ assert_equal "abcdX", "abcd".insert(4, 'X')
+ assert_equal "abXcd", "abcd".insert(-3, 'X')
+ assert_equal "abcdX", "abcd".insert(-1, 'X')
+ assert_raise(IndexError) { "abcd".insert(5, 'X') }
+ assert_raise(IndexError) { "abcd".insert(-6, 'X') }
+
+ a = "abcd"
+ a.insert(0, 'X')
+ assert_equal "Xabcd", a
+end
+
+assert('String#prepend') do
+ a = "world"
+ assert_equal "hello world", a.prepend("hello ")
+ assert_equal "hello world", a
+end
+
+assert('String#ljust') do
+ assert_equal "hello", "hello".ljust(4)
+ assert_equal "hello ", "hello".ljust(20)
+ assert_equal 20, "hello".ljust(20).length
+ assert_equal "hello123412341234123", "hello".ljust(20, '1234')
+ assert_equal "hello", "hello".ljust(-3)
+end
+
+assert('String#rjust') do
+ assert_equal "hello", "hello".rjust(4)
+ assert_equal " hello", "hello".rjust(20)
+ assert_equal 20, "hello".rjust(20).length
+ assert_equal "123412341234123hello", "hello".rjust(20, '1234')
+ assert_equal "hello", "hello".rjust(-3)
+end
+
+if UTF8STRING
+ assert('String#ljust with UTF8') do
+ assert_equal "helloん ", "helloん".ljust(20)
+ assert_equal "helloó ", "helloó".ljust(34)
+ assert_equal 34, "helloó".ljust(34).length
+ assert_equal "helloんんんんんんんんんんんんんん", "hello".ljust(19, 'ん')
+ assert_equal "helloんんんんんんんんんんんんんんん", "hello".ljust(20, 'ん')
+ end
+
+ assert('String#rjust with UTF8') do
+ assert_equal " helloん", "helloん".rjust(20)
+ assert_equal " helloó", "helloó".rjust(34)
+ # assert_equal 34, "helloó".rjust(34).length
+ assert_equal "んんんんんんんんんんんんんんhello", "hello".rjust(19, 'ん')
+ assert_equal "んんんんんんんんんんんんんんんhello", "hello".rjust(20, 'ん')
+ end
+
+ assert('UTF8 byte counting') do
+ ret = ' '
+ ret[-6..-1] = "helloó"
+ assert_equal 34, ret.length
+ end
+end
+
+assert('String#ljust should not change string') do
+ a = "hello"
+ a.ljust(20)
+ assert_equal "hello", a
+end
+
+assert('String#rjust should not change string') do
+ a = "hello"
+ a.rjust(20)
+ assert_equal "hello", a
+end
+
+assert('String#ljust should raise on zero width padding') do
+ assert_raise(ArgumentError) { "foo".ljust(10, '') }
+end
+
+assert('String#rjust should raise on zero width padding') do
+ assert_raise(ArgumentError) { "foo".rjust(10, '') }
+end
+
+assert('String#upto') do
+ assert_equal %w(a8 a9 b0 b1 b2 b3 b4 b5 b6), "a8".upto("b6").to_a
+ assert_equal ["9", "10", "11"], "9".upto("11").to_a
+ assert_equal [], "25".upto("5").to_a
+ assert_equal ["07", "08", "09", "10", "11"], "07".upto("11").to_a
+
+if UTF8STRING
+ assert_equal ["あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お"], "あ".upto("お").to_a
+end
+
+ assert_equal ["9", ":", ";", "<", "=", ">", "?", "@", "A"], "9".upto("A").to_a
+
+ a = "aa"
+ start = "aa"
+ count = 0
+ assert_equal("aa", a.upto("zz") {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(676, count)
+
+ a = "a"
+ start = "a"
+ count = 0
+ assert_equal("a", a.upto("a") {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(1, count)
+
+ a = "a"
+ start = "a"
+ count = 0
+ assert_equal("a", a.upto("b", true) {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(1, count)
+
+ a = "0"
+ start = "0"
+ count = 0
+ assert_equal("0", a.upto("0") {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(1, count)
+
+ a = "0"
+ start = "0"
+ count = 0
+ assert_equal("0", a.upto("-1") {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(0, count)
+
+ a = "-1"
+ start = "-1"
+ count = 0
+ assert_equal("-1", a.upto("-2") {|s|
+ assert_equal(start, s)
+ start.succ!
+ count += 1
+ })
+ assert_equal(2, count)
+
+ assert_raise(TypeError) { "a".upto(:c) {} }
+end
+
+assert('String#ord') do
+ got = "hello!".split('').map {|x| x.ord}
+ expect = [104, 101, 108, 108, 111, 33]
+ unless UTF8STRING
+ got << "\xff".ord
+ expect << 0xff
+ end
+ assert_equal expect, got
+end
+
+assert('String#ord(UTF-8)') do
+ got = "こんにちは世界!".split('').map {|x| x.ord}
+ expect = [0x3053,0x3093,0x306b,0x3061,0x306f,0x4e16,0x754c,0x21]
+ assert_equal expect, got
+end if UTF8STRING
+
+assert('String#chr') do
+ assert_equal "h", "hello!".chr
+end
+assert('String#chr(UTF-8)') do
+ assert_equal "こ", "こんにちは世界!".chr
+end if UTF8STRING
+
+assert('String#chars') do
+ expect = ["h", "e", "l", "l", "o", "!"]
+ assert_equal expect, "hello!".chars
+ s = ""
+ "hello!".chars do |x|
+ s += x
+ end
+ assert_equal "hello!", s
+end
+
+assert('String#chars(UTF-8)') do
+ expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!']
+ assert_equal expect, "こんにちは世界!".chars
+ s = ""
+ "こんにちは世界!".chars do |x|
+ s += x
+ end
+ assert_equal "こんにちは世界!", s
+end if UTF8STRING
+
+assert('String#each_char') do
+ s = ""
+ "hello!".each_char do |x|
+ s += x
+ end
+ assert_equal "hello!", s
+end
+
+assert('String#each_char(UTF-8)') do
+ s = ""
+ "こんにちは世界!".each_char do |x|
+ s += x
+ end
+ assert_equal "こんにちは世界!", s
+end if UTF8STRING
+
+assert('String#codepoints') do
+ expect = [104, 101, 108, 108, 111, 33]
+ assert_equal expect, "hello!".codepoints
+ cp = []
+ "hello!".codepoints do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end
+
+assert('String#codepoints(UTF-8)') do
+ expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33]
+ assert_equal expect, "こんにちは世界!".codepoints
+ cp = []
+ "こんにちは世界!".codepoints do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end if UTF8STRING
+
+assert('String#each_codepoint') do
+ expect = [104, 101, 108, 108, 111, 33]
+ cp = []
+ "hello!".each_codepoint do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end
+
+assert('String#each_codepoint(UTF-8)') do
+ expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33]
+ cp = []
+ "こんにちは世界!".each_codepoint do |x|
+ cp << x
+ end
+ assert_equal expect, cp
+end if UTF8STRING
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrbgem.rake
new file mode 100644
index 00000000..2826ad2a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-struct') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'standard Struct class'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrblib/struct.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrblib/struct.rb
new file mode 100644
index 00000000..7cf3dd3a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/mrblib/struct.rb
@@ -0,0 +1,103 @@
+##
+# Struct
+#
+# ISO 15.2.18
+
+if Object.const_defined?(:Struct)
+ class Struct
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element.
+ #
+ # ISO 15.2.18.4.4
+ def each(&block)
+ self.class.members.each{|field|
+ block.call(self[field])
+ }
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the name and value of the respectiev
+ # element.
+ #
+ # ISO 15.2.18.4.5
+ def each_pair(&block)
+ self.class.members.each{|field|
+ block.call(field.to_sym, self[field])
+ }
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and returns an array with all elements of which
+ # block is not false.
+ #
+ # ISO 15.2.18.4.7
+ def select(&block)
+ ary = []
+ self.class.members.each{|field|
+ val = self[field]
+ ary.push(val) if block.call(val)
+ }
+ ary
+ end
+
+ def _inspect
+ name = self.class.to_s
+ if name[0] == "#"
+ str = "#<struct "
+ else
+ str = "#<struct #{name} "
+ end
+ buf = []
+ self.each_pair do |k,v|
+ buf.push [k.to_s + "=" + v._inspect]
+ end
+ str + buf.join(", ") + ">"
+ end
+
+ ##
+ # call-seq:
+ # struct.to_s -> string
+ # struct.inspect -> string
+ #
+ # Describe the contents of this struct in a string.
+ #
+ # 15.2.18.4.10(x)
+ #
+ def inspect
+ begin
+ self._inspect
+ rescue SystemStackError
+ "#<struct #{self.class.to_s}:...>"
+ end
+ end
+
+ ##
+ # 15.2.18.4.11(x)
+ #
+ alias to_s inspect
+ end
+
+ ##
+ # call-seq:
+ # hsh.dig(key,...) -> object
+ #
+ # Extracts the nested value specified by the sequence of <i>key</i>
+ # objects by calling +dig+ at each step, returning +nil+ if any
+ # intermediate step is +nil+.
+ #
+ def dig(idx,*args)
+ n = self[idx]
+ if args.size > 0
+ n&.dig(*args)
+ else
+ n
+ end
+ end
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c
new file mode 100644
index 00000000..67762a94
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/src/struct.c
@@ -0,0 +1,714 @@
+/*
+** struct.c - Struct class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <string.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/class.h>
+#include <mruby/variable.h>
+#include <mruby/hash.h>
+#include <mruby/range.h>
+
+#define RSTRUCT_LEN(st) RARRAY_LEN(st)
+#define RSTRUCT_PTR(st) RARRAY_PTR(st)
+
+static struct RClass *
+struct_class(mrb_state *mrb)
+{
+ return mrb_class_get(mrb, "Struct");
+}
+
+static inline mrb_value
+struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id)
+{
+ struct RClass* kclass;
+ struct RClass* sclass = struct_class(mrb);
+ mrb_value ans;
+
+ for (;;) {
+ ans = mrb_iv_get(mrb, c, id);
+ if (!mrb_nil_p(ans)) return ans;
+ kclass = RCLASS_SUPER(c);
+ if (kclass == 0 || kclass == sclass)
+ return mrb_nil_value();
+ c = mrb_obj_value(kclass);
+ }
+}
+
+static mrb_value
+struct_s_members(mrb_state *mrb, struct RClass *klass)
+{
+ mrb_value members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__"));
+
+ if (mrb_nil_p(members)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct");
+ }
+ if (!mrb_array_p(members)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
+ }
+ return members;
+}
+
+static mrb_value
+struct_members(mrb_state *mrb, mrb_value s)
+{
+ mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s));
+ if (!mrb_array_p(s)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
+ }
+ if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
+ if (RSTRUCT_LEN(s) == 0) { /* probably uninitialized */
+ mrb_ary_resize(mrb, s, RARRAY_LEN(members));
+ }
+ else {
+ mrb_raisef(mrb, E_TYPE_ERROR,
+ "struct size differs (%S required %S given)",
+ mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ }
+ }
+ return members;
+}
+
+static mrb_value
+mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value members, ary;
+
+ members = struct_s_members(mrb, mrb_class_ptr(klass));
+ ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members));
+ mrb_ary_replace(mrb, ary, members);
+ return ary;
+}
+
+static void
+mrb_struct_modify(mrb_state *mrb, mrb_value strct)
+{
+ if (MRB_FROZEN_P(mrb_basic_ptr(strct))) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen struct");
+ }
+
+ mrb_write_barrier(mrb, mrb_basic_ptr(strct));
+}
+
+/* 15.2.18.4.6 */
+/*
+ * call-seq:
+ * struct.members -> array
+ *
+ * Returns an array of strings representing the names of the instance
+ * variables.
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joe.members #=> [:name, :address, :zip]
+ */
+
+static mrb_value
+mrb_struct_members(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj)));
+}
+
+static mrb_value struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id);
+
+static mrb_value
+mrb_struct_ref(mrb_state *mrb, mrb_value obj)
+{
+ return struct_aref_sym(mrb, obj, mrb->c->ci->mid);
+}
+
+static mrb_sym
+mrb_id_attrset(mrb_state *mrb, mrb_sym id)
+{
+ const char *name;
+ char *buf;
+ mrb_int len;
+ mrb_sym mid;
+
+ name = mrb_sym2name_len(mrb, id, &len);
+ buf = (char *)mrb_malloc(mrb, (size_t)len+2);
+ memcpy(buf, name, (size_t)len);
+ buf[len] = '=';
+ buf[len+1] = '\0';
+
+ mid = mrb_intern(mrb, buf, len+1);
+ mrb_free(mrb, buf);
+ return mid;
+}
+
+static mrb_value mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val);
+
+static mrb_value
+mrb_struct_set_m(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value val;
+
+ const char *name;
+ mrb_int slen;
+ mrb_sym mid;
+
+ mrb_get_args(mrb, "o", &val);
+
+ /* get base id */
+ name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen);
+ mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */
+
+ return mrb_struct_aset_sym(mrb, obj, mid, val);
+}
+
+static mrb_bool
+is_local_id(mrb_state *mrb, const char *name)
+{
+ if (!name) return FALSE;
+ return !ISUPPER(name[0]);
+}
+
+static mrb_bool
+is_const_id(mrb_state *mrb, const char *name)
+{
+ if (!name) return FALSE;
+ return ISUPPER(name[0]);
+}
+
+static void
+make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c)
+{
+ const mrb_value *ptr_members = RARRAY_PTR(members);
+ mrb_int i;
+ mrb_int len = RARRAY_LEN(members);
+ int ai = mrb_gc_arena_save(mrb);
+
+ for (i=0; i<len; i++) {
+ mrb_sym id = mrb_symbol(ptr_members[i]);
+ const char *name = mrb_sym2name_len(mrb, id, NULL);
+
+ if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
+ mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE());
+ mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ }
+}
+
+static mrb_value
+make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass)
+{
+ mrb_value nstr;
+ mrb_sym id;
+ struct RClass *c;
+
+ if (mrb_nil_p(name)) {
+ c = mrb_class_new(mrb, klass);
+ }
+ else {
+ /* old style: should we warn? */
+ name = mrb_str_to_str(mrb, name);
+ id = mrb_obj_to_sym(mrb, name);
+ if (!is_const_id(mrb, mrb_sym2name_len(mrb, id, NULL))) {
+ mrb_name_error(mrb, id, "identifier %S needs to be constant", name);
+ }
+ if (mrb_const_defined_at(mrb, mrb_obj_value(klass), id)) {
+ mrb_warn(mrb, "redefining constant Struct::%S", name);
+ mrb_const_remove(mrb, mrb_obj_value(klass), id);
+ }
+ c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass);
+ }
+ MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY);
+ nstr = mrb_obj_value(c);
+ mrb_iv_set(mrb, nstr, mrb_intern_lit(mrb, "__members__"), members);
+
+ mrb_define_class_method(mrb, c, "new", mrb_instance_new, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, c, "[]", mrb_instance_new, MRB_ARGS_ANY());
+ mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, MRB_ARGS_NONE());
+ /* RSTRUCT(nstr)->basic.c->super = c->c; */
+ make_struct_define_accessors(mrb, members, c);
+ return nstr;
+}
+
+/* 15.2.18.3.1 */
+/*
+ * call-seq:
+ * Struct.new( [aString] [, aSym]+> ) -> StructClass
+ * StructClass.new(arg, ...) -> obj
+ * StructClass[arg, ...] -> obj
+ *
+ * Creates a new class, named by <i>aString</i>, containing accessor
+ * methods for the given symbols. If the name <i>aString</i> is
+ * omitted, an anonymous structure class will be created. Otherwise,
+ * the name of this struct will appear as a constant in class
+ * <code>Struct</code>, so it must be unique for all
+ * <code>Struct</code>s in the system and should start with a capital
+ * letter. Assigning a structure class to a constant effectively gives
+ * the class the name of the constant.
+ *
+ * <code>Struct::new</code> returns a new <code>Class</code> object,
+ * which can then be used to create specific instances of the new
+ * structure. The number of actual parameters must be
+ * less than or equal to the number of attributes defined for this
+ * class; unset parameters default to <code>nil</code>. Passing too many
+ * parameters will raise an <code>ArgumentError</code>.
+ *
+ * The remaining methods listed in this section (class and instance)
+ * are defined for this generated class.
+ *
+ * # Create a structure with a name in Struct
+ * Struct.new("Customer", :name, :address) #=> Struct::Customer
+ * Struct::Customer.new("Dave", "123 Main") #=> #<struct Struct::Customer name="Dave", address="123 Main">
+ *
+ * # Create a structure named by its constant
+ * Customer = Struct.new(:name, :address) #=> Customer
+ * Customer.new("Dave", "123 Main") #=> #<struct Customer name="Dave", address="123 Main">
+ */
+static mrb_value
+mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value name, rest;
+ mrb_value *pargv;
+ mrb_int argcnt;
+ mrb_int i;
+ mrb_value b, st;
+ mrb_sym id;
+ mrb_value *argv;
+ mrb_int argc;
+
+ name = mrb_nil_value();
+ mrb_get_args(mrb, "*&", &argv, &argc, &b);
+ if (argc == 0) { /* special case to avoid crash */
+ rest = mrb_ary_new(mrb);
+ }
+ else {
+ if (argc > 0) name = argv[0];
+ pargv = &argv[1];
+ argcnt = argc-1;
+ if (!mrb_nil_p(name) && mrb_symbol_p(name)) {
+ /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
+ name = mrb_nil_value();
+ pargv = &argv[0];
+ argcnt++;
+ }
+ rest = mrb_ary_new_from_values(mrb, argcnt, pargv);
+ for (i=0; i<RARRAY_LEN(rest); i++) {
+ id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]);
+ mrb_ary_set(mrb, rest, i, mrb_symbol_value(id));
+ }
+ }
+ st = make_struct(mrb, name, rest, mrb_class_ptr(klass));
+ if (!mrb_nil_p(b)) {
+ mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(st));
+ }
+
+ return st;
+}
+
+static mrb_int
+num_members(mrb_state *mrb, struct RClass *klass)
+{
+ mrb_value members;
+
+ members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__"));
+ if (!mrb_array_p(members)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "broken members");
+ }
+ return RARRAY_LEN(members);
+}
+
+/* 15.2.18.4.8 */
+/*
+ */
+static mrb_value
+mrb_struct_initialize_withArg(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value self)
+{
+ struct RClass *klass = mrb_obj_class(mrb, self);
+ mrb_int i, n;
+
+ n = num_members(mrb, klass);
+ if (n < argc) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs");
+ }
+
+ for (i = 0; i < argc; i++) {
+ mrb_ary_set(mrb, self, i, argv[i]);
+ }
+ for (i = argc; i < n; i++) {
+ mrb_ary_set(mrb, self, i, mrb_nil_value());
+ }
+ return self;
+}
+
+static mrb_value
+mrb_struct_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ mrb_int argc;
+
+ mrb_get_args(mrb, "*!", &argv, &argc);
+ return mrb_struct_initialize_withArg(mrb, argc, argv, self);
+}
+
+/* 15.2.18.4.9 */
+/* :nodoc: */
+static mrb_value
+mrb_struct_init_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_value s;
+
+ mrb_get_args(mrb, "o", &s);
+
+ if (mrb_obj_equal(mrb, copy, s)) return copy;
+ if (!mrb_obj_is_instance_of(mrb, s, mrb_obj_class(mrb, copy))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+ if (!mrb_array_p(s)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
+ }
+ mrb_ary_replace(mrb, copy, s);
+ return copy;
+}
+
+static mrb_value
+struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id)
+{
+ mrb_value members, *ptr;
+ const mrb_value *ptr_members;
+ mrb_int i, len;
+
+ members = struct_members(mrb, obj);
+ ptr_members = RARRAY_PTR(members);
+ len = RARRAY_LEN(members);
+ ptr = RSTRUCT_PTR(obj);
+ for (i=0; i<len; i++) {
+ mrb_value slot = ptr_members[i];
+ if (mrb_symbol_p(slot) && mrb_symbol(slot) == id) {
+ return ptr[i];
+ }
+ }
+ mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
+ return mrb_nil_value(); /* not reached */
+}
+
+static mrb_value
+struct_aref_int(mrb_state *mrb, mrb_value s, mrb_int i)
+{
+ if (i < 0) i = RSTRUCT_LEN(s) + i;
+ if (i < 0)
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too small for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ if (RSTRUCT_LEN(s) <= i)
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too large for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ return RSTRUCT_PTR(s)[i];
+}
+
+/* 15.2.18.4.2 */
+/*
+ * call-seq:
+ * struct[symbol] -> anObject
+ * struct[fixnum] -> anObject
+ *
+ * Attribute Reference---Returns the value of the instance variable
+ * named by <i>symbol</i>, or indexed (0..length-1) by
+ * <i>fixnum</i>. Will raise <code>NameError</code> if the named
+ * variable does not exist, or <code>IndexError</code> if the index is
+ * out of range.
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ *
+ * joe["name"] #=> "Joe Smith"
+ * joe[:name] #=> "Joe Smith"
+ * joe[0] #=> "Joe Smith"
+ */
+static mrb_value
+mrb_struct_aref(mrb_state *mrb, mrb_value s)
+{
+ mrb_value idx;
+
+ mrb_get_args(mrb, "o", &idx);
+ if (mrb_string_p(idx)) {
+ mrb_value sym = mrb_check_intern_str(mrb, idx);
+
+ if (mrb_nil_p(sym)) {
+ mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
+ }
+ idx = sym;
+ }
+ if (mrb_symbol_p(idx)) {
+ return struct_aref_sym(mrb, s, mrb_symbol(idx));
+ }
+ return struct_aref_int(mrb, s, mrb_int(mrb, idx));
+}
+
+static mrb_value
+mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
+{
+ mrb_value members, *ptr;
+ const mrb_value *ptr_members;
+ mrb_int i, len;
+
+ members = struct_members(mrb, s);
+ len = RARRAY_LEN(members);
+ ptr = RSTRUCT_PTR(s);
+ ptr_members = RARRAY_PTR(members);
+ for (i=0; i<len; i++) {
+ if (mrb_symbol(ptr_members[i]) == id) {
+ mrb_struct_modify(mrb, s);
+ ptr[i] = val;
+ return val;
+ }
+ }
+ mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id));
+ return val; /* not reach */
+}
+
+/* 15.2.18.4.3 */
+/*
+ * call-seq:
+ * struct[symbol] = obj -> obj
+ * struct[fixnum] = obj -> obj
+ *
+ * Attribute Assignment---Assigns to the instance variable named by
+ * <i>symbol</i> or <i>fixnum</i> the value <i>obj</i> and
+ * returns it. Will raise a <code>NameError</code> if the named
+ * variable does not exist, or an <code>IndexError</code> if the index
+ * is out of range.
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ *
+ * joe["name"] = "Luke"
+ * joe[:zip] = "90210"
+ *
+ * joe.name #=> "Luke"
+ * joe.zip #=> "90210"
+ */
+
+static mrb_value
+mrb_struct_aset(mrb_state *mrb, mrb_value s)
+{
+ mrb_int i;
+ mrb_value idx;
+ mrb_value val;
+
+ mrb_get_args(mrb, "oo", &idx, &val);
+
+ if (mrb_string_p(idx)) {
+ mrb_value sym = mrb_check_intern_str(mrb, idx);
+
+ if (mrb_nil_p(sym)) {
+ mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
+ }
+ idx = sym;
+ }
+ if (mrb_symbol_p(idx)) {
+ return mrb_struct_aset_sym(mrb, s, mrb_symbol(idx), val);
+ }
+
+ i = mrb_int(mrb, idx);
+ if (i < 0) i = RSTRUCT_LEN(s) + i;
+ if (i < 0) {
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too small for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ }
+ if (RSTRUCT_LEN(s) <= i) {
+ mrb_raisef(mrb, E_INDEX_ERROR,
+ "offset %S too large for struct(size:%S)",
+ mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
+ }
+ mrb_struct_modify(mrb, s);
+ return RSTRUCT_PTR(s)[i] = val;
+}
+
+/* 15.2.18.4.1 */
+/*
+ * call-seq:
+ * struct == other_struct -> true or false
+ *
+ * Equality---Returns <code>true</code> if <i>other_struct</i> is
+ * equal to this one: they must be of the same class as generated by
+ * <code>Struct::new</code>, and the values of all instance variables
+ * must be equal (according to <code>Object#==</code>).
+ *
+ * Customer = Struct.new(:name, :address, :zip)
+ * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
+ * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
+ * joe == joejr #=> true
+ * joe == jane #=> false
+ */
+
+static mrb_value
+mrb_struct_equal(mrb_state *mrb, mrb_value s)
+{
+ mrb_value s2;
+ mrb_value *ptr, *ptr2;
+ mrb_int i, len;
+
+ mrb_get_args(mrb, "o", &s2);
+ if (mrb_obj_equal(mrb, s, s2)) {
+ return mrb_true_value();
+ }
+ if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
+ return mrb_false_value();
+ }
+ if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
+ mrb_bug(mrb, "inconsistent struct"); /* should never happen */
+ }
+ ptr = RSTRUCT_PTR(s);
+ ptr2 = RSTRUCT_PTR(s2);
+ len = RSTRUCT_LEN(s);
+ for (i=0; i<len; i++) {
+ if (!mrb_equal(mrb, ptr[i], ptr2[i])) {
+ return mrb_false_value();
+ }
+ }
+
+ return mrb_true_value();
+}
+
+/* 15.2.18.4.12(x) */
+/*
+ * code-seq:
+ * struct.eql?(other) -> true or false
+ *
+ * Two structures are equal if they are the same object, or if all their
+ * fields are equal (using <code>eql?</code>).
+ */
+static mrb_value
+mrb_struct_eql(mrb_state *mrb, mrb_value s)
+{
+ mrb_value s2;
+ mrb_value *ptr, *ptr2;
+ mrb_int i, len;
+
+ mrb_get_args(mrb, "o", &s2);
+ if (mrb_obj_equal(mrb, s, s2)) {
+ return mrb_true_value();
+ }
+ if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
+ return mrb_false_value();
+ }
+ if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
+ mrb_bug(mrb, "inconsistent struct"); /* should never happen */
+ }
+ ptr = RSTRUCT_PTR(s);
+ ptr2 = RSTRUCT_PTR(s2);
+ len = RSTRUCT_LEN(s);
+ for (i=0; i<len; i++) {
+ if (!mrb_eql(mrb, ptr[i], ptr2[i])) {
+ return mrb_false_value();
+ }
+ }
+
+ return mrb_true_value();
+}
+
+/*
+ * call-seq:
+ * struct.length -> Fixnum
+ * struct.size -> Fixnum
+ *
+ * Returns number of struct members.
+ */
+static mrb_value
+mrb_struct_len(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(RSTRUCT_LEN(self));
+}
+
+/*
+ * call-seq:
+ * struct.to_a -> array
+ * struct.values -> array
+ *
+ * Create an array from struct values.
+ */
+static mrb_value
+mrb_struct_to_a(mrb_state *mrb, mrb_value self)
+{
+ return mrb_ary_new_from_values(mrb, RSTRUCT_LEN(self), RSTRUCT_PTR(self));
+}
+
+/*
+ * call-seq:
+ * struct.to_h -> hash
+ *
+ * Create a hash from member names and struct values.
+ */
+static mrb_value
+mrb_struct_to_h(mrb_state *mrb, mrb_value self)
+{
+ mrb_value members, ret;
+ mrb_int i;
+
+ members = struct_members(mrb, self);
+ ret = mrb_hash_new_capa(mrb, RARRAY_LEN(members));
+
+ for (i = 0; i < RARRAY_LEN(members); ++i) {
+ mrb_hash_set(mrb, ret, RARRAY_PTR(members)[i], RSTRUCT_PTR(self)[i]);
+ }
+
+ return ret;
+}
+
+static mrb_value
+mrb_struct_values_at(mrb_state *mrb, mrb_value self)
+{
+ mrb_int argc;
+ mrb_value *argv;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+
+ return mrb_get_values_at(mrb, self, RSTRUCT_LEN(self), argc, argv, struct_aref_int);
+}
+
+/*
+ * A <code>Struct</code> is a convenient way to bundle a number of
+ * attributes together, using accessor methods, without having to write
+ * an explicit class.
+ *
+ * The <code>Struct</code> class is a generator of specific classes,
+ * each one of which is defined to hold a set of variables and their
+ * accessors. In these examples, we'll call the generated class
+ * "<i>Customer</i>Class," and we'll show an example instance of that
+ * class as "<i>Customer</i>Inst."
+ *
+ * In the descriptions that follow, the parameter <i>symbol</i> refers
+ * to a symbol, which is either a quoted string or a
+ * <code>Symbol</code> (such as <code>:name</code>).
+ */
+void
+mrb_mruby_struct_gem_init(mrb_state* mrb)
+{
+ struct RClass *st;
+ st = mrb_define_class(mrb, "Struct", mrb->object_class);
+ MRB_SET_INSTANCE_TT(st, MRB_TT_ARRAY);
+
+ mrb_define_class_method(mrb, st, "new", mrb_struct_s_def, MRB_ARGS_ANY()); /* 15.2.18.3.1 */
+
+ mrb_define_method(mrb, st, "==", mrb_struct_equal, MRB_ARGS_REQ(1)); /* 15.2.18.4.1 */
+ mrb_define_method(mrb, st, "[]", mrb_struct_aref, MRB_ARGS_REQ(1)); /* 15.2.18.4.2 */
+ mrb_define_method(mrb, st, "[]=", mrb_struct_aset, MRB_ARGS_REQ(2)); /* 15.2.18.4.3 */
+ mrb_define_method(mrb, st, "members", mrb_struct_members, MRB_ARGS_NONE()); /* 15.2.18.4.6 */
+ mrb_define_method(mrb, st, "initialize", mrb_struct_initialize, MRB_ARGS_ANY()); /* 15.2.18.4.8 */
+ mrb_define_method(mrb, st, "initialize_copy", mrb_struct_init_copy, MRB_ARGS_REQ(1)); /* 15.2.18.4.9 */
+ mrb_define_method(mrb, st, "eql?", mrb_struct_eql, MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x) */
+
+ mrb_define_method(mrb, st, "size", mrb_struct_len, MRB_ARGS_NONE());
+ mrb_define_method(mrb, st, "length", mrb_struct_len, MRB_ARGS_NONE());
+ mrb_define_method(mrb, st, "to_a", mrb_struct_to_a, MRB_ARGS_NONE());
+ mrb_define_method(mrb, st, "values", mrb_struct_to_a, MRB_ARGS_NONE());
+ mrb_define_method(mrb, st, "to_h", mrb_struct_to_h, MRB_ARGS_NONE());
+ mrb_define_method(mrb, st, "values_at", mrb_struct_values_at, MRB_ARGS_ANY());
+}
+
+void
+mrb_mruby_struct_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/test/struct.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/test/struct.rb
new file mode 100644
index 00000000..421fe4b5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-struct/test/struct.rb
@@ -0,0 +1,212 @@
+##
+# Struct ISO Test
+
+assert('Struct', '15.2.18') do
+ assert_equal Class, Struct.class
+end
+
+assert('Struct.new', '15.2.18.3.1') do
+ c = Struct.new(:m1, :m2)
+ assert_equal Struct, c.superclass
+ assert_equal [:m1, :m2], c.members
+end
+
+# Check crash bug with Struc.new and no params.
+assert('Struct.new', '15.2.18.3.1') do
+ c = Struct.new()
+ assert_equal Struct, c.superclass
+ assert_equal [], c.members
+end
+
+assert('Struct#==', '15.2.18.4.1') do
+ c = Struct.new(:m1, :m2)
+ cc1 = c.new(1,2)
+ cc2 = c.new(1,2)
+ assert_true cc1 == cc2
+
+ Struct.new(:m1, :m2) { def foo; end }
+ assert_raise(NoMethodError) { Struct.new(:m1).new.foo }
+end
+
+assert('Struct#[]', '15.2.18.4.2') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ assert_equal 1, cc[:m1]
+ assert_equal 2, cc["m2"]
+ assert_equal 1, cc[0]
+ assert_equal 2, cc[-1]
+ assert_raise(TypeError) { cc[[]] }
+ assert_raise(IndexError) { cc[2] }
+ assert_raise(NameError) { cc['tama'] }
+end
+
+assert('Struct#[]=', '15.2.18.4.3') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ cc[:m1] = 3
+ assert_equal 3, cc[:m1]
+ cc["m2"] = 3
+ assert_equal 3, cc["m2"]
+ cc[0] = 4
+ assert_equal 4, cc[0]
+ cc[-1] = 5
+ assert_equal 5, cc[-1]
+ assert_raise(TypeError) { cc[[]] = 3 }
+ assert_raise(IndexError) { cc[2] = 7 }
+ assert_raise(NameError) { cc['pochi'] = 8 }
+end
+
+assert('Struct#each', '15.2.18.4.4') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ a = []
+ cc.each{|x|
+ a << x
+ }
+ assert_equal [1, 2], a
+end
+
+assert('Struct#each_pair', '15.2.18.4.5') do
+ c = Struct.new(:m1, :m2)
+ cc = c.new(1,2)
+ a = []
+ cc.each_pair{|k,v|
+ a << [k,v]
+ }
+ assert_equal [[:m1, 1], [:m2, 2]], a
+end
+
+assert('Struct#members', '15.2.18.4.6') do
+ c = Struct.new(:m1, :m2)
+ assert_equal [:m1, :m2], c.new(1,2).members
+end
+
+assert('Struct#select', '15.2.18.4.7') do
+ c = Struct.new(:m1, :m2)
+ assert_equal([2]) { c.new(1,2).select{|v| v % 2 == 0} }
+end
+
+assert('large struct') do
+ c = Struct.new(:m1, :m2, :m3, :m4, :m5, :m6, :m7, :m8, :m9, :m10, :m11, :m12, :m13)
+ cc = c.new(1,2,3,4,5,6,7,8,9,10,11,12,13)
+ assert_equal 1, cc.m1
+ assert_equal 2, cc.m2
+ assert_equal 3, cc.m3
+ assert_equal 4, cc.m4
+ assert_equal 5, cc.m5
+ assert_equal 6, cc.m6
+ assert_equal 7, cc.m7
+ assert_equal 8, cc.m8
+ assert_equal 9, cc.m9
+ assert_equal 10, cc.m10
+ assert_equal 13, cc.m13
+
+ cc.m13 = 'test'
+ assert_equal 'test', cc.m13
+
+ assert_raise(NoMethodError) { cc.m14 }
+end
+
+assert('wrong struct arg count') do
+ c = Struct.new(:m1)
+ assert_raise ArgumentError do
+ cc = c.new(1,2,3)
+ end
+end
+
+assert('struct dup') do
+ c = Struct.new(:m1, :m2, :m3, :m4, :m5)
+ cc = c.new(1,2,3,4,5)
+ assert_nothing_raised {
+ assert_equal(cc, cc.dup)
+ }
+end
+
+assert('struct inspect') do
+ c = Struct.new(:m1, :m2, :m3, :m4, :m5)
+ cc = c.new(1,2,3,4,5)
+ assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5>", cc.inspect
+end
+
+assert('Struct#length, Struct#size') do
+ s = Struct.new(:f1, :f2).new(0, 1)
+ assert_equal 2, s.size
+ assert_equal 2, s.length
+end
+
+assert('Struct#to_a, Struct#values') do
+ s = Struct.new(:mem1, :mem2).new('a', 'b')
+ assert_equal ['a', 'b'], s.to_a
+ assert_equal ['a', 'b'], s.values
+end
+
+assert('Struct#to_h') do
+ s = Struct.new(:white, :red, :green).new('ruuko', 'yuzuki', 'hitoe')
+ assert_equal(:white => 'ruuko', :red => 'yuzuki', :green => 'hitoe') { s.to_h }
+end
+
+assert('Struct#values_at') do
+ a = Struct.new(:blue, :purple).new('aki', 'io')
+ assert_equal ['aki'], a.values_at(0)
+ assert_equal ['io', 'aki'], a.values_at(1, 0)
+ assert_raise(IndexError) { a.values_at 2 }
+end
+
+assert("Struct#dig") do
+ a = Struct.new(:blue, :purple).new('aki', Struct.new(:red).new(1))
+ assert_equal 'aki', a.dig(:blue)
+ assert_equal 1, a.dig(:purple, :red)
+ assert_equal 1, a.dig(1, 0)
+end
+
+assert("Struct.new removes existing constant") do
+ skip "redefining Struct with same name cause warnings"
+ begin
+ assert_not_equal Struct.new("Test", :a), Struct.new("Test", :a, :b)
+ ensure
+ Struct.remove_const :Test
+ end
+end
+
+assert("Struct#initialize_copy requires struct to be the same type") do
+ begin
+ Struct.new("Test", :a)
+ a = Struct::Test.new("a")
+ Struct.remove_const :Test
+ Struct.new("Test", :a, :b)
+ assert_raise(TypeError) do
+ a.initialize_copy(Struct::Test.new("a", "b"))
+ end
+ ensure
+ Struct.remove_const :Test
+ end
+end
+
+assert("Struct.new does not allow array") do
+ assert_raise(TypeError) do
+ Struct.new("Test", [:a])
+ end
+end
+
+assert("Struct.new generates subclass of Struct") do
+ begin
+ original_struct = Struct
+ Struct = String
+ assert_equal original_struct, original_struct.new.superclass
+ ensure
+ Struct = original_struct
+ end
+end
+
+assert 'Struct#freeze' do
+ c = Struct.new :m
+
+ o = c.new
+ o.m = :test
+ assert_equal :test, o.m
+
+ o.freeze
+ assert_raise(RuntimeError) { o.m = :modify }
+ assert_raise(RuntimeError) { o[:m] = :modify }
+ assert_equal :test, o.m
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake
new file mode 100644
index 00000000..4f3fa43b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-symbol-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'Symbol class extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb
new file mode 100644
index 00000000..1e3d24b8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb
@@ -0,0 +1,65 @@
+class Symbol
+ include Comparable
+
+ alias intern to_sym
+
+ def to_proc
+ ->(obj,*args,&block) do
+ obj.__send__(self, *args, &block)
+ end
+ end
+
+ ##
+ # call-seq:
+ # sym.capitalize -> symbol
+ #
+ # Same as <code>sym.to_s.capitalize.intern</code>.
+
+ def capitalize
+ (self.to_s.capitalize! || self).to_sym
+ end
+
+ ##
+ # call-seq:
+ # sym.downcase -> symbol
+ #
+ # Same as <code>sym.to_s.downcase.intern</code>.
+
+ def downcase
+ (self.to_s.downcase! || self).to_sym
+ end
+
+ ##
+ # call-seq:
+ # sym.upcase -> symbol
+ #
+ # Same as <code>sym.to_s.upcase.intern</code>.
+
+ def upcase
+ (self.to_s.upcase! || self).to_sym
+ end
+
+ ##
+ # call-seq:
+ # sym.casecmp(other) -> -1, 0, +1 or nil
+ #
+ # Case-insensitive version of <code>Symbol#<=></code>.
+
+ def casecmp(other)
+ return nil unless other.kind_of?(Symbol)
+ lhs = self.to_s; lhs.upcase!
+ rhs = other.to_s; rhs.upcase!
+ lhs <=> rhs
+ end
+
+ #
+ # call-seq:
+ # sym.empty? -> true or false
+ #
+ # Returns that _sym_ is :"" or not.
+
+ def empty?
+ self.length == 0
+ end
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/src/symbol.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/src/symbol.c
new file mode 100644
index 00000000..a992dbfc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/src/symbol.c
@@ -0,0 +1,64 @@
+#include <mruby.h>
+#include <mruby/khash.h>
+#include <mruby/array.h>
+
+typedef struct symbol_name {
+ size_t len;
+ const char *name;
+} symbol_name;
+
+/*
+ * call-seq:
+ * Symbol.all_symbols => array
+ *
+ * Returns an array of all the symbols currently in Ruby's symbol
+ * table.
+ *
+ * Symbol.all_symbols.size #=> 903
+ * Symbol.all_symbols[1,20] #=> [:floor, :ARGV, :Binding, :symlink,
+ * :chown, :EOFError, :$;, :String,
+ * :LOCK_SH, :"setuid?", :$<,
+ * :default_proc, :compact, :extend,
+ * :Tms, :getwd, :$=, :ThreadGroup,
+ * :wait2, :$>]
+ */
+static mrb_value
+mrb_sym_all_symbols(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym i, lim;
+ mrb_value ary = mrb_ary_new_capa(mrb, mrb->symidx);
+
+ for (i=1, lim=mrb->symidx+1; i<lim; i++) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(i));
+ }
+
+ return ary;
+}
+
+/*
+ * call-seq:
+ * sym.length -> integer
+ *
+ * Same as <code>sym.to_s.length</code>.
+ */
+static mrb_value
+mrb_sym_length(mrb_state *mrb, mrb_value self)
+{
+ mrb_int len;
+ mrb_sym2name_len(mrb, mrb_symbol(self), &len);
+ return mrb_fixnum_value(len);
+}
+
+void
+mrb_mruby_symbol_ext_gem_init(mrb_state* mrb)
+{
+ struct RClass *s = mrb->symbol_class;
+ mrb_define_class_method(mrb, s, "all_symbols", mrb_sym_all_symbols, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "length", mrb_sym_length, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "size", mrb_sym_length, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_symbol_ext_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb
new file mode 100644
index 00000000..6070d141
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb
@@ -0,0 +1,48 @@
+##
+# Symbol(Ext) Test
+
+assert('Symbol#to_proc') do
+ assert_equal 5, :abs.to_proc[-5]
+end
+
+assert('Symbol.all_symbols') do
+ foo = [:__symbol_test_1, :__symbol_test_2, :__symbol_test_3].sort
+ symbols = Symbol.all_symbols.select{|sym|sym.to_s.include? '__symbol_test'}.sort
+ assert_equal foo, symbols
+end
+
+assert("Symbol#length") do
+ assert_equal 5, :hello.size
+ assert_equal 5, :mruby.length
+end
+
+assert("Symbol#capitalize") do
+ assert_equal :Hello, :hello.capitalize
+ assert_equal :Hello, :HELLO.capitalize
+ assert_equal :Hello, :Hello.capitalize
+end
+
+assert("Symbol#downcase") do
+ assert_equal :hello, :hEllO.downcase
+ assert_equal :hello, :hello.downcase
+end
+
+assert("Symbol#upcase") do
+ assert_equal :HELLO, :hEllO.upcase
+ assert_equal :HELLO, :HELLO.upcase
+end
+
+assert("Symbol#casecmp") do
+ assert_equal 0, :HELLO.casecmp(:hEllO)
+ assert_equal 1, :HELLO.casecmp(:hEllN)
+ assert_equal(-1, :HELLO.casecmp(:hEllP))
+ assert_nil :HELLO.casecmp("hEllO")
+end
+
+assert("Symbol#empty?") do
+ assert_true :''.empty?
+end
+
+assert('Symbol#intern') do
+ assert_equal :test, :test.intern
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/README.md b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/README.md
new file mode 100644
index 00000000..fa4b91e3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/README.md
@@ -0,0 +1,7 @@
+Running Tests
+=============
+
+To run the tests, execute the following from the project's root directory.
+
+ $ make test
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/driver.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/driver.c
new file mode 100644
index 00000000..14e93ff3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/driver.c
@@ -0,0 +1,172 @@
+/*
+** mrbtest - Test for Embeddable Ruby
+**
+** This program runs Ruby test programs in test/t directory
+** against the current mruby implementation.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mruby.h>
+#include <mruby/proc.h>
+#include <mruby/data.h>
+#include <mruby/compile.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/array.h>
+
+void
+mrb_init_mrbtest(mrb_state *);
+
+/* Print a short remark for the user */
+static void
+print_hint(void)
+{
+ printf("mrbtest - Embeddable Ruby Test\n\n");
+}
+
+static int
+check_error(mrb_state *mrb)
+{
+ /* Error check */
+ /* $ko_test and $kill_test should be 0 */
+ mrb_value ko_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$ko_test"));
+ mrb_value kill_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$kill_test"));
+
+ return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0;
+}
+
+static int
+eval_test(mrb_state *mrb)
+{
+ /* evaluate the test */
+ mrb_funcall(mrb, mrb_top_self(mrb), "report", 0);
+ /* did an exception occur? */
+ if (mrb->exc) {
+ mrb_print_error(mrb);
+ mrb->exc = 0;
+ return EXIT_FAILURE;
+ }
+ else if (!check_error(mrb)) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+static void
+t_printstr(mrb_state *mrb, mrb_value obj)
+{
+ char *s;
+ int len;
+
+ if (mrb_string_p(obj)) {
+ s = RSTRING_PTR(obj);
+ len = RSTRING_LEN(obj);
+ fwrite(s, len, 1, stdout);
+ }
+}
+
+mrb_value
+mrb_t_printstr(mrb_state *mrb, mrb_value self)
+{
+ mrb_value argv;
+
+ mrb_get_args(mrb, "o", &argv);
+ t_printstr(mrb, argv);
+
+ return argv;
+}
+
+void
+mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose)
+{
+ struct RClass *krn, *mrbtest;
+
+ krn = mrb->kernel_module;
+ mrb_define_method(mrb, krn, "__t_printstr__", mrb_t_printstr, MRB_ARGS_REQ(1));
+
+ mrbtest = mrb_define_module(mrb, "Mrbtest");
+
+ mrb_define_const(mrb, mrbtest, "FIXNUM_MAX", mrb_fixnum_value(MRB_INT_MAX));
+ mrb_define_const(mrb, mrbtest, "FIXNUM_MIN", mrb_fixnum_value(MRB_INT_MIN));
+ mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT));
+
+#ifdef MRB_USE_FLOAT
+ mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-6));
+#else
+ mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-12));
+#endif
+
+ if (verbose) {
+ mrb_gv_set(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"), mrb_true_value());
+ }
+}
+
+void
+mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src)
+{
+ mrb_value res_src;
+
+ if (mrb_src->exc) {
+ mrb_print_error(mrb_src);
+ exit(EXIT_FAILURE);
+ }
+
+#define TEST_COUNT_PASS(name) \
+ do { \
+ res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$" #name)); \
+ if (mrb_fixnum_p(res_src)) { \
+ mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name)); \
+ mrb_gv_set(mrb_dst, mrb_intern_lit(mrb_dst, "$" #name), mrb_fixnum_value(mrb_fixnum(res_dst) + mrb_fixnum(res_src))); \
+ } \
+ } while (FALSE) \
+
+ TEST_COUNT_PASS(ok_test);
+ TEST_COUNT_PASS(ko_test);
+ TEST_COUNT_PASS(kill_test);
+
+#undef TEST_COUNT_PASS
+
+ res_src = mrb_gv_get(mrb_src, mrb_intern_lit(mrb_src, "$asserts"));
+
+ if (mrb_array_p(res_src)) {
+ mrb_int i;
+ mrb_value res_dst = mrb_gv_get(mrb_dst, mrb_intern_lit(mrb_dst, "$asserts"));
+ for (i = 0; i < RARRAY_LEN(res_src); ++i) {
+ mrb_value val_src = RARRAY_PTR(res_src)[i];
+ mrb_ary_push(mrb_dst, res_dst, mrb_str_new(mrb_dst, RSTRING_PTR(val_src), RSTRING_LEN(val_src)));
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ mrb_state *mrb;
+ int ret;
+ mrb_bool verbose = FALSE;
+
+ print_hint();
+
+ /* new interpreter instance */
+ mrb = mrb_open();
+ if (mrb == NULL) {
+ fprintf(stderr, "Invalid mrb_state, exiting test driver");
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') {
+ printf("verbose mode: enable\n\n");
+ verbose = TRUE;
+ }
+
+ mrb_init_test_driver(mrb, verbose);
+ mrb_init_mrbtest(mrb);
+ ret = eval_test(mrb);
+ mrb_close(mrb);
+
+ return ret;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/init_mrbtest.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/init_mrbtest.c
new file mode 100644
index 00000000..17ac1bde
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/init_mrbtest.c
@@ -0,0 +1,38 @@
+#include <stdlib.h>
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/variable.h>
+
+extern const uint8_t mrbtest_assert_irep[];
+
+void mrbgemtest_init(mrb_state* mrb);
+void mrb_init_test_driver(mrb_state* mrb, mrb_bool verbose);
+void mrb_t_pass_result(mrb_state *mrb_dst, mrb_state *mrb_src);
+
+void
+mrb_init_mrbtest(mrb_state *mrb)
+{
+ mrb_state *core_test;
+
+ mrb_load_irep(mrb, mrbtest_assert_irep);
+
+ core_test = mrb_open_core(mrb_default_allocf, NULL);
+ if (core_test == NULL) {
+ fprintf(stderr, "Invalid mrb_state, exiting %s", __FUNCTION__);
+ exit(EXIT_FAILURE);
+ }
+ mrb_init_test_driver(core_test, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));
+ mrb_load_irep(core_test, mrbtest_assert_irep);
+ mrb_t_pass_result(mrb, core_test);
+
+#ifndef DISABLE_GEMS
+ mrbgemtest_init(mrb);
+#endif
+
+ if (mrb->exc) {
+ mrb_print_error(mrb);
+ exit(EXIT_FAILURE);
+ }
+ mrb_close(core_test);
+}
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/mrbgem.rake
new file mode 100644
index 00000000..ae4c2f13
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-test/mrbgem.rake
@@ -0,0 +1,187 @@
+MRuby::Gem::Specification.new('mruby-test') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mruby test'
+
+ build.bins << 'mrbtest'
+ spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
+
+ spec.test_rbfiles = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb")
+
+ clib = "#{build_dir}/mrbtest.c"
+ mlib = clib.ext(exts.object)
+ exec = exefile("#{build.build_dir}/bin/mrbtest")
+
+ libmruby = libfile("#{build.build_dir}/lib/libmruby")
+ libmruby_core = libfile("#{build.build_dir}/lib/libmruby_core")
+
+ mrbtest_lib = libfile("#{build_dir}/mrbtest")
+ mrbtest_objs = []
+
+ driver_obj = objfile("#{build_dir}/driver")
+ driver = "#{spec.dir}/driver.c"
+
+ assert_c = "#{build_dir}/assert.c"
+ assert_rb = "#{MRUBY_ROOT}/test/assert.rb"
+ assert_lib = assert_c.ext(exts.object)
+ mrbtest_objs << assert_lib
+
+ file assert_lib => assert_c
+ file assert_c => assert_rb do |t|
+ open(t.name, 'w') do |f|
+ mrbc.run f, assert_rb, 'mrbtest_assert_irep'
+ end
+ end
+
+ gem_table = build.gems.generate_gem_table build
+
+ build.gems.each do |g|
+ test_rbobj = g.test_rbireps.ext(exts.object)
+ g.test_objs << test_rbobj
+ dep_list = build.gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions)
+
+ file test_rbobj => g.test_rbireps
+ file g.test_rbireps => [g.test_rbfiles].flatten do |t|
+ FileUtils.mkdir_p File.dirname(t.name)
+ open(t.name, 'w') do |f|
+ g.print_gem_test_header(f)
+ test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir|
+ File.expand_path(g.test_preload, dir)
+ }.find {|file| File.exist?(file) }
+
+ f.puts %Q[/*]
+ f.puts %Q[ * This file contains a test code for #{g.name} gem.]
+ f.puts %Q[ *]
+ f.puts %Q[ * IMPORTANT:]
+ f.puts %Q[ * This file was generated!]
+ f.puts %Q[ * All manual changes will get lost.]
+ f.puts %Q[ */]
+ if test_preload.nil?
+ f.puts %Q[extern const uint8_t mrbtest_assert_irep[];]
+ else
+ g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload"
+ end
+ g.test_rbfiles.flatten.each_with_index do |rbfile, i|
+ g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}"
+ end
+ f.puts %Q[void mrb_#{g.funcname}_gem_test(mrb_state *mrb);] unless g.test_objs.empty?
+ dep_list.each do |d|
+ f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb_state *mrb);]
+ f.puts %Q[void GENERATED_TMP_mrb_#{d.funcname}_gem_final(mrb_state *mrb);]
+ end
+ f.puts %Q[void mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose);]
+ f.puts %Q[void mrb_t_pass_result(mrb_state *dst, mrb_state *src);]
+ f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb) {]
+ unless g.test_rbfiles.empty?
+ f.puts %Q[ mrb_state *mrb2;]
+ unless g.test_args.empty?
+ f.puts %Q[ mrb_value test_args_hash;]
+ end
+ f.puts %Q[ int ai;]
+ g.test_rbfiles.count.times do |i|
+ f.puts %Q[ ai = mrb_gc_arena_save(mrb);]
+ f.puts %Q[ mrb2 = mrb_open_core(mrb_default_allocf, NULL);]
+ f.puts %Q[ if (mrb2 == NULL) {]
+ f.puts %Q[ fprintf(stderr, "Invalid mrb_state, exiting \%s", __FUNCTION__);]
+ f.puts %Q[ exit(EXIT_FAILURE);]
+ f.puts %Q[ }]
+ dep_list.each do |d|
+ f.puts %Q[ GENERATED_TMP_mrb_#{d.funcname}_gem_init(mrb2);]
+ f.puts %Q[ mrb_state_atexit(mrb2, GENERATED_TMP_mrb_#{d.funcname}_gem_final);]
+ end
+ f.puts %Q[ mrb_init_test_driver(mrb2, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));]
+ if test_preload.nil?
+ f.puts %Q[ mrb_load_irep(mrb2, mrbtest_assert_irep);]
+ else
+ f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);]
+ end
+ f.puts %Q[ if (mrb2->exc) {]
+ f.puts %Q[ mrb_print_error(mrb2);]
+ f.puts %Q[ exit(EXIT_FAILURE);]
+ f.puts %Q[ }]
+ f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "GEMNAME"), mrb_str_new(mrb2, "#{g.name}", #{g.name.length}));]
+
+ unless g.test_args.empty?
+ f.puts %Q[ test_args_hash = mrb_hash_new_capa(mrb, #{g.test_args.length}); ]
+ g.test_args.each do |arg_name, arg_value|
+ escaped_arg_name = arg_name.gsub('\\', '\\\\\\\\').gsub('"', '\"')
+ escaped_arg_value = arg_value.gsub('\\', '\\\\\\\\').gsub('"', '\"')
+ f.puts %Q[ mrb_hash_set(mrb2, test_args_hash, mrb_str_new(mrb2, "#{escaped_arg_name.to_s}", #{escaped_arg_name.to_s.length}), mrb_str_new(mrb2, "#{escaped_arg_value.to_s}", #{escaped_arg_value.to_s.length})); ]
+ end
+ f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern_lit(mrb2, "TEST_ARGS"), test_args_hash); ]
+ end
+
+ f.puts %Q[ mrb_#{g.funcname}_gem_test(mrb2);] if g.custom_test_init?
+
+ f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_#{i});]
+ f.puts %Q[ ]
+
+ f.puts %Q[ mrb_t_pass_result(mrb, mrb2);]
+ f.puts %Q[ mrb_close(mrb2);]
+ f.puts %Q[ mrb_gc_arena_restore(mrb, ai);]
+ end
+ end
+ f.puts %Q[}]
+ end
+ end
+ end
+
+ build.gems.each do |v|
+ mrbtest_objs.concat v.test_objs
+ end
+
+ file mrbtest_lib => mrbtest_objs do |t|
+ build.archiver.run t.name, t.prerequisites
+ end
+
+ unless build.build_mrbtest_lib_only?
+ file exec => [driver_obj, mlib, mrbtest_lib, libmruby_core, libmruby] do |t|
+ gem_flags = build.gems.map { |g| g.linker.flags }
+ gem_flags_before_libraries = build.gems.map { |g| g.linker.flags_before_libraries }
+ gem_flags_after_libraries = build.gems.map { |g| g.linker.flags_after_libraries }
+ gem_libraries = build.gems.map { |g| g.linker.libraries }
+ gem_library_paths = build.gems.map { |g| g.linker.library_paths }
+ build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries
+ end
+ end
+
+ init = "#{spec.dir}/init_mrbtest.c"
+
+ # store the last gem selection and make the re-build
+ # of the test gem depending on a change to the gem
+ # selection
+ active_gems = "#{build_dir}/active_gems.lst"
+ FileUtils.mkdir_p File.dirname(active_gems)
+ open(active_gems, 'w+') do |f|
+ build.gems.each do |g|
+ f.puts g.name
+ end
+ end
+ file clib => active_gems
+
+ file mlib => clib
+ file clib => init do |t|
+ _pp "GEN", "*.rb", "#{clib.relative_path}"
+ FileUtils.mkdir_p File.dirname(clib)
+ open(clib, 'w') do |f|
+ f.puts %Q[/*]
+ f.puts %Q[ * This file contains a list of all]
+ f.puts %Q[ * test functions.]
+ f.puts %Q[ *]
+ f.puts %Q[ * IMPORTANT:]
+ f.puts %Q[ * This file was generated!]
+ f.puts %Q[ * All manual changes will get lost.]
+ f.puts %Q[ */]
+ f.puts %Q[]
+ f.puts IO.read(init)
+ build.gems.each do |g|
+ f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);]
+ end
+ f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {]
+ build.gems.each do |g|
+ f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);]
+ end
+ f.puts %Q[}]
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrbgem.rake
new file mode 100644
index 00000000..45b2ead7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-time') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'standard Time class'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrblib/time.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrblib/time.rb
new file mode 100644
index 00000000..df0d8ca8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/mrblib/time.rb
@@ -0,0 +1,9 @@
+class Time
+ def sunday?; wday == 0 end
+ def monday?; wday == 1 end
+ def tuesday?; wday == 2 end
+ def wednesday?; wday == 3 end
+ def thursday?; wday == 4 end
+ def friday?; wday == 5 end
+ def saturday?; wday == 6 end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/src/time.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/src/time.c
new file mode 100644
index 00000000..5e862483
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/src/time.c
@@ -0,0 +1,869 @@
+/*
+** time.c - Time class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <math.h>
+#include <time.h>
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+
+#ifndef DISABLE_STDIO
+#include <stdio.h>
+#else
+#include <string.h>
+#endif
+
+#define NDIV(x,y) (-(-((x)+1)/(y))-1)
+
+#if defined(_MSC_VER) && _MSC_VER < 1800
+double round(double x) {
+ return floor(x + 0.5);
+}
+#endif
+
+#if !defined(__MINGW64__) && defined(_WIN32)
+# define llround(x) round(x)
+#endif
+
+#if defined(__MINGW64__) || defined(__MINGW32__)
+# include <sys/time.h>
+#endif
+
+/** Time class configuration */
+
+/* gettimeofday(2) */
+/* C99 does not have gettimeofday that is required to retrieve microseconds */
+/* uncomment following macro on platforms without gettimeofday(2) */
+/* #define NO_GETTIMEOFDAY */
+
+/* gmtime(3) */
+/* C99 does not have reentrant gmtime_r() so it might cause troubles under */
+/* multi-threading environment. undef following macro on platforms that */
+/* does not have gmtime_r() and localtime_r(). */
+/* #define NO_GMTIME_R */
+
+#ifdef _WIN32
+#if _MSC_VER
+/* Win32 platform do not provide gmtime_r/localtime_r; emulate them using gmtime_s/localtime_s */
+#define gmtime_r(tp, tm) ((gmtime_s((tm), (tp)) == 0) ? (tm) : NULL)
+#define localtime_r(tp, tm) ((localtime_s((tm), (tp)) == 0) ? (tm) : NULL)
+#else
+#define NO_GMTIME_R
+#endif
+#endif
+
+/* asctime(3) */
+/* mruby usually use its own implementation of struct tm to string conversion */
+/* except when DISABLE_STDIO is set. In that case, it uses asctime() or asctime_r(). */
+/* By default mruby tries to use asctime_r() which is reentrant. */
+/* Undef following macro on platforms that does not have asctime_r(). */
+/* #define NO_ASCTIME_R */
+
+/* timegm(3) */
+/* mktime() creates tm structure for localtime; timegm() is for UTC time */
+/* define following macro to use probably faster timegm() on the platform */
+/* #define USE_SYSTEM_TIMEGM */
+
+/** end of Time class configuration */
+
+#ifndef NO_GETTIMEOFDAY
+# ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN /* don't include winsock.h */
+# include <windows.h>
+# define gettimeofday my_gettimeofday
+
+# ifdef _MSC_VER
+# define UI64(x) x##ui64
+# else
+# define UI64(x) x##ull
+# endif
+
+typedef long suseconds_t;
+
+# if (!defined __MINGW64__) && (!defined __MINGW32__)
+struct timeval {
+ time_t tv_sec;
+ suseconds_t tv_usec;
+};
+# endif
+
+static int
+gettimeofday(struct timeval *tv, void *tz)
+{
+ if (tz) {
+ mrb_assert(0); /* timezone is not supported */
+ }
+ if (tv) {
+ union {
+ FILETIME ft;
+ unsigned __int64 u64;
+ } t;
+ GetSystemTimeAsFileTime(&t.ft); /* 100 ns intervals since Windows epoch */
+ t.u64 -= UI64(116444736000000000); /* Unix epoch bias */
+ t.u64 /= 10; /* to microseconds */
+ tv->tv_sec = (time_t)(t.u64 / (1000 * 1000));
+ tv->tv_usec = t.u64 % (1000 * 1000);
+ }
+ return 0;
+}
+# else
+# include <sys/time.h>
+# endif
+#endif
+#ifdef NO_GMTIME_R
+#define gmtime_r(t,r) gmtime(t)
+#define localtime_r(t,r) localtime(t)
+#endif
+
+#ifndef USE_SYSTEM_TIMEGM
+#define timegm my_timgm
+
+static unsigned int
+is_leapyear(unsigned int y)
+{
+ return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
+}
+
+static time_t
+timegm(struct tm *tm)
+{
+ static const unsigned int ndays[2][12] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+ };
+ time_t r = 0;
+ int i;
+ unsigned int *nday = (unsigned int*) ndays[is_leapyear(tm->tm_year+1900)];
+
+ for (i = 70; i < tm->tm_year; ++i)
+ r += is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60;
+ for (i = 0; i < tm->tm_mon; ++i)
+ r += nday[i] * 24 * 60 * 60;
+ r += (tm->tm_mday - 1) * 24 * 60 * 60;
+ r += tm->tm_hour * 60 * 60;
+ r += tm->tm_min * 60;
+ r += tm->tm_sec;
+ return r;
+}
+#endif
+
+/* Since we are limited to using ISO C99, this implementation is based
+* on time_t. That means the resolution of time is only precise to the
+* second level. Also, there are only 2 timezones, namely UTC and LOCAL.
+*/
+
+enum mrb_timezone {
+ MRB_TIMEZONE_NONE = 0,
+ MRB_TIMEZONE_UTC = 1,
+ MRB_TIMEZONE_LOCAL = 2,
+ MRB_TIMEZONE_LAST = 3
+};
+
+typedef struct mrb_timezone_name {
+ const char name[8];
+ size_t len;
+} mrb_timezone_name;
+
+static const mrb_timezone_name timezone_names[] = {
+ { "none", sizeof("none") - 1 },
+ { "UTC", sizeof("UTC") - 1 },
+ { "LOCAL", sizeof("LOCAL") - 1 },
+};
+
+#ifndef DISABLE_STDIO
+static const char mon_names[12][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
+
+static const char wday_names[7][4] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+};
+#endif
+
+struct mrb_time {
+ time_t sec;
+ time_t usec;
+ enum mrb_timezone timezone;
+ struct tm datetime;
+};
+
+static const struct mrb_data_type mrb_time_type = { "Time", mrb_free };
+
+/** Updates the datetime of a mrb_time based on it's timezone and
+seconds setting. Returns self on success, NULL of failure. */
+static struct mrb_time*
+time_update_datetime(mrb_state *mrb, struct mrb_time *self)
+{
+ struct tm *aid;
+
+ if (self->timezone == MRB_TIMEZONE_UTC) {
+ aid = gmtime_r(&self->sec, &self->datetime);
+ }
+ else {
+ aid = localtime_r(&self->sec, &self->datetime);
+ }
+ if (!aid) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, (mrb_float)self->sec));
+ /* not reached */
+ return NULL;
+ }
+#ifdef NO_GMTIME_R
+ self->datetime = *aid; /* copy data */
+#endif
+
+ return self;
+}
+
+static mrb_value
+mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm)
+{
+ return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm));
+}
+
+void mrb_check_num_exact(mrb_state *mrb, mrb_float num);
+
+/* Allocates a mrb_time object and initializes it. */
+static struct mrb_time*
+time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
+{
+ struct mrb_time *tm;
+ time_t tsec = 0;
+
+ mrb_check_num_exact(mrb, (mrb_float)sec);
+ mrb_check_num_exact(mrb, (mrb_float)usec);
+
+ if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) {
+ goto out_of_range;
+ }
+ if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) {
+ goto out_of_range;
+ }
+ tsec = (time_t)sec;
+ if ((sec > 0 && tsec < 0) || (sec < 0 && (double)tsec > sec)) {
+ out_of_range:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec));
+ }
+ tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
+ tm->sec = tsec;
+ tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec);
+ if (tm->usec < 0) {
+ long sec2 = (long)NDIV(usec,1000000); /* negative div */
+ tm->usec -= sec2 * 1000000;
+ tm->sec += sec2;
+ }
+ else if (tm->usec >= 1000000) {
+ long sec2 = (long)(usec / 1000000);
+ tm->usec -= sec2 * 1000000;
+ tm->sec += sec2;
+ }
+ tm->timezone = timezone;
+ time_update_datetime(mrb, tm);
+
+ return tm;
+}
+
+static mrb_value
+mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone)
+{
+ return mrb_time_wrap(mrb, c, time_alloc(mrb, sec, usec, timezone));
+}
+
+static struct mrb_time*
+current_mrb_time(mrb_state *mrb)
+{
+ struct mrb_time *tm;
+
+ tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
+#if defined(TIME_UTC)
+ {
+ struct timespec ts;
+ if (timespec_get(&ts, TIME_UTC) == 0) {
+ mrb_free(mrb, tm);
+ mrb_raise(mrb, E_RUNTIME_ERROR, "timespec_get() failed for unknown reasons");
+ }
+ tm->sec = ts.tv_sec;
+ tm->usec = ts.tv_nsec / 1000;
+ }
+#elif defined(NO_GETTIMEOFDAY)
+ {
+ static time_t last_sec = 0, last_usec = 0;
+
+ tm->sec = time(NULL);
+ if (tm->sec != last_sec) {
+ last_sec = tm->sec;
+ last_usec = 0;
+ }
+ else {
+ /* add 1 usec to differentiate two times */
+ last_usec += 1;
+ }
+ tm->usec = last_usec;
+ }
+#else
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ tm->sec = tv.tv_sec;
+ tm->usec = tv.tv_usec;
+ }
+#endif
+ tm->timezone = MRB_TIMEZONE_LOCAL;
+ time_update_datetime(mrb, tm);
+
+ return tm;
+}
+
+/* Allocates a new Time object with given millis value. */
+static mrb_value
+mrb_time_now(mrb_state *mrb, mrb_value self)
+{
+ return mrb_time_wrap(mrb, mrb_class_ptr(self), current_mrb_time(mrb));
+}
+
+/* 15.2.19.6.1 */
+/* Creates an instance of time at the given time in seconds, etc. */
+static mrb_value
+mrb_time_at(mrb_state *mrb, mrb_value self)
+{
+ mrb_float f, f2 = 0;
+
+ mrb_get_args(mrb, "f|f", &f, &f2);
+ return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL);
+}
+
+static struct mrb_time*
+time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
+ mrb_int ahour, mrb_int amin, mrb_int asec, mrb_int ausec,
+ enum mrb_timezone timezone)
+{
+ time_t nowsecs;
+ struct tm nowtime = { 0 };
+
+ nowtime.tm_year = (int)ayear - 1900;
+ nowtime.tm_mon = (int)amonth - 1;
+ nowtime.tm_mday = (int)aday;
+ nowtime.tm_hour = (int)ahour;
+ nowtime.tm_min = (int)amin;
+ nowtime.tm_sec = (int)asec;
+ nowtime.tm_isdst = -1;
+
+ if (nowtime.tm_mon < 0 || nowtime.tm_mon > 11
+ || nowtime.tm_mday < 1 || nowtime.tm_mday > 31
+ || nowtime.tm_hour < 0 || nowtime.tm_hour > 24
+ || (nowtime.tm_hour == 24 && (nowtime.tm_min > 0 || nowtime.tm_sec > 0))
+ || nowtime.tm_min < 0 || nowtime.tm_min > 59
+ || nowtime.tm_sec < 0 || nowtime.tm_sec > 60)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "argument out of range");
+
+ if (timezone == MRB_TIMEZONE_UTC) {
+ nowsecs = timegm(&nowtime);
+ }
+ else {
+ nowsecs = mktime(&nowtime);
+ }
+ if (nowsecs == (time_t)-1) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time.");
+ }
+
+ return time_alloc(mrb, (double)nowsecs, ausec, timezone);
+}
+
+/* 15.2.19.6.2 */
+/* Creates an instance of time at the given time in UTC. */
+static mrb_value
+mrb_time_gm(mrb_state *mrb, mrb_value self)
+{
+ mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0;
+
+ mrb_get_args(mrb, "i|iiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ return mrb_time_wrap(mrb, mrb_class_ptr(self),
+ time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC));
+}
+
+
+/* 15.2.19.6.3 */
+/* Creates an instance of time at the given time in local time zone. */
+static mrb_value
+mrb_time_local(mrb_state *mrb, mrb_value self)
+{
+ mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0, amin = 0, asec = 0, ausec = 0;
+
+ mrb_get_args(mrb, "i|iiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ return mrb_time_wrap(mrb, mrb_class_ptr(self),
+ time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL));
+}
+
+static struct mrb_time*
+time_get_ptr(mrb_state *mrb, mrb_value time)
+{
+ struct mrb_time *tm;
+
+ tm = DATA_GET_PTR(mrb, time, &mrb_time_type, struct mrb_time);
+ if (!tm) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized time");
+ }
+ return tm;
+}
+
+static mrb_value
+mrb_time_eq(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+ struct mrb_time *tm1, *tm2;
+ mrb_bool eq_p;
+
+ mrb_get_args(mrb, "o", &other);
+ tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
+ eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec;
+
+ return mrb_bool_value(eq_p);
+}
+
+static mrb_value
+mrb_time_cmp(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+ struct mrb_time *tm1, *tm2;
+
+ mrb_get_args(mrb, "o", &other);
+ tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
+ tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
+ if (!tm1 || !tm2) return mrb_nil_value();
+ if (tm1->sec > tm2->sec) {
+ return mrb_fixnum_value(1);
+ }
+ else if (tm1->sec < tm2->sec) {
+ return mrb_fixnum_value(-1);
+ }
+ /* tm1->sec == tm2->sec */
+ if (tm1->usec > tm2->usec) {
+ return mrb_fixnum_value(1);
+ }
+ else if (tm1->usec < tm2->usec) {
+ return mrb_fixnum_value(-1);
+ }
+ return mrb_fixnum_value(0);
+}
+
+static mrb_value
+mrb_time_plus(mrb_state *mrb, mrb_value self)
+{
+ mrb_float f;
+ struct mrb_time *tm;
+
+ mrb_get_args(mrb, "f", &f);
+ tm = time_get_ptr(mrb, self);
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone);
+}
+
+static mrb_value
+mrb_time_minus(mrb_state *mrb, mrb_value self)
+{
+ mrb_float f;
+ mrb_value other;
+ struct mrb_time *tm, *tm2;
+
+ mrb_get_args(mrb, "o", &other);
+ tm = time_get_ptr(mrb, self);
+ tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
+ if (tm2) {
+ f = (mrb_float)(tm->sec - tm2->sec)
+ + (mrb_float)(tm->usec - tm2->usec) / 1.0e6;
+ return mrb_float_value(mrb, f);
+ }
+ else {
+ mrb_get_args(mrb, "f", &f);
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, (double)tm->usec, tm->timezone);
+ }
+}
+
+/* 15.2.19.7.30 */
+/* Returns week day number of time. */
+static mrb_value
+mrb_time_wday(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_wday);
+}
+
+/* 15.2.19.7.31 */
+/* Returns year day number of time. */
+static mrb_value
+mrb_time_yday(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_yday + 1);
+}
+
+/* 15.2.19.7.32 */
+/* Returns year of time. */
+static mrb_value
+mrb_time_year(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_year + 1900);
+}
+
+/* 15.2.19.7.33 */
+/* Returns name of time's timezone. */
+static mrb_value
+mrb_time_zone(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ if (tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value();
+ if (tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value();
+ return mrb_str_new_static(mrb,
+ timezone_names[tm->timezone].name,
+ timezone_names[tm->timezone].len);
+}
+
+/* 15.2.19.7.4 */
+/* Returns a string that describes the time. */
+static mrb_value
+mrb_time_asctime(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm = time_get_ptr(mrb, self);
+ struct tm *d = &tm->datetime;
+ int len;
+
+#if defined(DISABLE_STDIO)
+ char *s;
+# ifdef NO_ASCTIME_R
+ s = asctime(d);
+# else
+ char buf[32];
+ s = asctime_r(d, buf);
+# endif
+ len = strlen(s)-1; /* truncate the last newline */
+#else
+ char buf[256];
+
+ len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
+ wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
+ d->tm_hour, d->tm_min, d->tm_sec,
+ tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
+ d->tm_year + 1900);
+#endif
+ return mrb_str_new(mrb, buf, len);
+}
+
+/* 15.2.19.7.6 */
+/* Returns the day in the month of the time. */
+static mrb_value
+mrb_time_day(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_mday);
+}
+
+
+/* 15.2.19.7.7 */
+/* Returns true if daylight saving was applied for this time. */
+static mrb_value
+mrb_time_dst_p(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_bool_value(tm->datetime.tm_isdst);
+}
+
+/* 15.2.19.7.8 */
+/* 15.2.19.7.10 */
+/* Returns the Time object of the UTC(GMT) timezone. */
+static mrb_value
+mrb_time_getutc(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm, *tm2;
+
+ tm = time_get_ptr(mrb, self);
+ tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
+ *tm2 = *tm;
+ tm2->timezone = MRB_TIMEZONE_UTC;
+ time_update_datetime(mrb, tm2);
+ return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
+}
+
+/* 15.2.19.7.9 */
+/* Returns the Time object of the LOCAL timezone. */
+static mrb_value
+mrb_time_getlocal(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm, *tm2;
+
+ tm = time_get_ptr(mrb, self);
+ tm2 = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
+ *tm2 = *tm;
+ tm2->timezone = MRB_TIMEZONE_LOCAL;
+ time_update_datetime(mrb, tm2);
+ return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
+}
+
+/* 15.2.19.7.15 */
+/* Returns hour of time. */
+static mrb_value
+mrb_time_hour(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_hour);
+}
+
+/* 15.2.19.7.16 */
+/* Initializes a time by setting the amount of milliseconds since the epoch.*/
+static mrb_value
+mrb_time_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0,
+ amin = 0, asec = 0, ausec = 0;
+ int n;
+ struct mrb_time *tm;
+
+ n = mrb_get_args(mrb, "|iiiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ tm = (struct mrb_time*)DATA_PTR(self);
+ if (tm) {
+ mrb_free(mrb, tm);
+ }
+ mrb_data_init(self, NULL, &mrb_time_type);
+
+ if (n == 0) {
+ tm = current_mrb_time(mrb);
+ }
+ else {
+ tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL);
+ }
+ mrb_data_init(self, tm, &mrb_time_type);
+ return self;
+}
+
+/* 15.2.19.7.17(x) */
+/* Initializes a copy of this time object. */
+static mrb_value
+mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_value src;
+ struct mrb_time *t1, *t2;
+
+ mrb_get_args(mrb, "o", &src);
+ if (mrb_obj_equal(mrb, copy, src)) return copy;
+ if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+ t1 = (struct mrb_time *)DATA_PTR(copy);
+ t2 = (struct mrb_time *)DATA_PTR(src);
+ if (!t2) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized time");
+ }
+ if (!t1) {
+ t1 = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
+ mrb_data_init(copy, t1, &mrb_time_type);
+ }
+ *t1 = *t2;
+ return copy;
+}
+
+/* 15.2.19.7.18 */
+/* Sets the timezone attribute of the Time object to LOCAL. */
+static mrb_value
+mrb_time_localtime(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ tm->timezone = MRB_TIMEZONE_LOCAL;
+ time_update_datetime(mrb, tm);
+ return self;
+}
+
+/* 15.2.19.7.19 */
+/* Returns day of month of time. */
+static mrb_value
+mrb_time_mday(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_mday);
+}
+
+/* 15.2.19.7.20 */
+/* Returns minutes of time. */
+static mrb_value
+mrb_time_min(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_min);
+}
+
+/* 15.2.19.7.21 and 15.2.19.7.22 */
+/* Returns month of time. */
+static mrb_value
+mrb_time_mon(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_mon + 1);
+}
+
+/* 15.2.19.7.23 */
+/* Returns seconds in minute of time. */
+static mrb_value
+mrb_time_sec(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_fixnum_value(tm->datetime.tm_sec);
+}
+
+
+/* 15.2.19.7.24 */
+/* Returns a Float with the time since the epoch in seconds. */
+static mrb_value
+mrb_time_to_f(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6);
+}
+
+/* 15.2.19.7.25 */
+/* Returns a Fixnum with the time since the epoch in seconds. */
+static mrb_value
+mrb_time_to_i(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
+ return mrb_float_value(mrb, (mrb_float)tm->sec);
+ }
+ return mrb_fixnum_value((mrb_int)tm->sec);
+}
+
+/* 15.2.19.7.26 */
+/* Returns a Float with the time since the epoch in microseconds. */
+static mrb_value
+mrb_time_usec(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
+ return mrb_float_value(mrb, (mrb_float)tm->usec);
+ }
+ return mrb_fixnum_value((mrb_int)tm->usec);
+}
+
+/* 15.2.19.7.27 */
+/* Sets the timezone attribute of the Time object to UTC. */
+static mrb_value
+mrb_time_utc(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ tm->timezone = MRB_TIMEZONE_UTC;
+ time_update_datetime(mrb, tm);
+ return self;
+}
+
+/* 15.2.19.7.28 */
+/* Returns true if this time is in the UTC timezone false if not. */
+static mrb_value
+mrb_time_utc_p(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = time_get_ptr(mrb, self);
+ return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC);
+}
+
+
+void
+mrb_mruby_time_gem_init(mrb_state* mrb)
+{
+ struct RClass *tc;
+ /* ISO 15.2.19.2 */
+ tc = mrb_define_class(mrb, "Time", mrb->object_class);
+ MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA);
+ mrb_include_module(mrb, tc, mrb_module_get(mrb, "Comparable"));
+ mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_ARG(1, 1)); /* 15.2.19.6.1 */
+ mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.2 */
+ mrb_define_class_method(mrb, tc, "local", mrb_time_local, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.3 */
+ mrb_define_class_method(mrb, tc, "mktime", mrb_time_local, MRB_ARGS_ARG(1,6));/* 15.2.19.6.4 */
+ mrb_define_class_method(mrb, tc, "now", mrb_time_now, MRB_ARGS_NONE()); /* 15.2.19.6.5 */
+ mrb_define_class_method(mrb, tc, "utc", mrb_time_gm, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.6 */
+
+ mrb_define_method(mrb, tc, "==" , mrb_time_eq , MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , MRB_ARGS_REQ(1)); /* 15.2.19.7.1 */
+ mrb_define_method(mrb, tc, "+" , mrb_time_plus , MRB_ARGS_REQ(1)); /* 15.2.19.7.2 */
+ mrb_define_method(mrb, tc, "-" , mrb_time_minus , MRB_ARGS_REQ(1)); /* 15.2.19.7.3 */
+ mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, MRB_ARGS_NONE());
+ mrb_define_method(mrb, tc, "inspect", mrb_time_asctime, MRB_ARGS_NONE());
+ mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.4 */
+ mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.5 */
+ mrb_define_method(mrb, tc, "day" , mrb_time_day , MRB_ARGS_NONE()); /* 15.2.19.7.6 */
+ mrb_define_method(mrb, tc, "dst?" , mrb_time_dst_p , MRB_ARGS_NONE()); /* 15.2.19.7.7 */
+ mrb_define_method(mrb, tc, "getgm" , mrb_time_getutc , MRB_ARGS_NONE()); /* 15.2.19.7.8 */
+ mrb_define_method(mrb, tc, "getlocal",mrb_time_getlocal,MRB_ARGS_NONE()); /* 15.2.19.7.9 */
+ mrb_define_method(mrb, tc, "getutc" , mrb_time_getutc , MRB_ARGS_NONE()); /* 15.2.19.7.10 */
+ mrb_define_method(mrb, tc, "gmt?" , mrb_time_utc_p , MRB_ARGS_NONE()); /* 15.2.19.7.11 */
+ mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , MRB_ARGS_NONE()); /* 15.2.19.7.13 */
+ mrb_define_method(mrb, tc, "hour" , mrb_time_hour, MRB_ARGS_NONE()); /* 15.2.19.7.15 */
+ mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, MRB_ARGS_NONE()); /* 15.2.19.7.18 */
+ mrb_define_method(mrb, tc, "mday" , mrb_time_mday, MRB_ARGS_NONE()); /* 15.2.19.7.19 */
+ mrb_define_method(mrb, tc, "min" , mrb_time_min, MRB_ARGS_NONE()); /* 15.2.19.7.20 */
+
+ mrb_define_method(mrb, tc, "mon" , mrb_time_mon, MRB_ARGS_NONE()); /* 15.2.19.7.21 */
+ mrb_define_method(mrb, tc, "month", mrb_time_mon, MRB_ARGS_NONE()); /* 15.2.19.7.22 */
+
+ mrb_define_method(mrb, tc, "sec" , mrb_time_sec, MRB_ARGS_NONE()); /* 15.2.19.7.23 */
+ mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, MRB_ARGS_NONE()); /* 15.2.19.7.25 */
+ mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, MRB_ARGS_NONE()); /* 15.2.19.7.24 */
+ mrb_define_method(mrb, tc, "usec", mrb_time_usec, MRB_ARGS_NONE()); /* 15.2.19.7.26 */
+ mrb_define_method(mrb, tc, "utc" , mrb_time_utc, MRB_ARGS_NONE()); /* 15.2.19.7.27 */
+ mrb_define_method(mrb, tc, "utc?", mrb_time_utc_p,MRB_ARGS_NONE()); /* 15.2.19.7.28 */
+ mrb_define_method(mrb, tc, "wday", mrb_time_wday, MRB_ARGS_NONE()); /* 15.2.19.7.30 */
+ mrb_define_method(mrb, tc, "yday", mrb_time_yday, MRB_ARGS_NONE()); /* 15.2.19.7.31 */
+ mrb_define_method(mrb, tc, "year", mrb_time_year, MRB_ARGS_NONE()); /* 15.2.19.7.32 */
+ mrb_define_method(mrb, tc, "zone", mrb_time_zone, MRB_ARGS_NONE()); /* 15.2.19.7.33 */
+
+ mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, MRB_ARGS_REQ(1)); /* 15.2.19.7.16 */
+ mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.19.7.17 */
+
+ /*
+ methods not available:
+ gmt_offset(15.2.19.7.12)
+ gmtoff(15.2.19.7.14)
+ utc_offset(15.2.19.7.29)
+ */
+}
+
+void
+mrb_mruby_time_gem_final(mrb_state* mrb)
+{
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/test/time.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/test/time.rb
new file mode 100644
index 00000000..52b93117
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-time/test/time.rb
@@ -0,0 +1,228 @@
+##
+# Time ISO Test
+
+assert('Time.new', '15.2.3.3.3') do
+ Time.new.class == Time
+end
+
+assert('Time', '15.2.19') do
+ Time.class == Class
+end
+
+assert('Time.at', '15.2.19.6.1') do
+ assert_kind_of(Time, Time.at(1300000000.0))
+
+ assert_raise(FloatDomainError) { Time.at(Float::NAN) }
+ assert_raise(FloatDomainError) { Time.at(Float::INFINITY) }
+ assert_raise(FloatDomainError) { Time.at(-Float::INFINITY) }
+ assert_raise(FloatDomainError) { Time.at(0, Float::NAN) }
+ assert_raise(FloatDomainError) { Time.at(0, Float::INFINITY) }
+ assert_raise(FloatDomainError) { Time.at(0, -Float::INFINITY) }
+end
+
+assert('Time.gm', '15.2.19.6.2') do
+ Time.gm(2012, 12, 23)
+end
+
+assert('Time.local', '15.2.19.6.3') do
+ Time.local(2012, 12, 23)
+end
+
+assert('Time.mktime', '15.2.19.6.4') do
+ Time.mktime(2012, 12, 23)
+end
+
+assert('Time.now', '15.2.19.6.5') do
+ Time.now.class == Time
+end
+
+assert('Time.utc', '15.2.19.6.6') do
+ Time.utc(2012, 12, 23)
+end
+
+assert('Time#+', '15.2.19.7.1') do
+ t1 = Time.at(1300000000.0)
+ t2 = t1.+(60)
+
+ assert_equal(t2.utc.asctime, "Sun Mar 13 07:07:40 UTC 2011")
+
+ assert_raise(FloatDomainError) { Time.at(0) + Float::NAN }
+ assert_raise(FloatDomainError) { Time.at(0) + Float::INFINITY }
+ assert_raise(FloatDomainError) { Time.at(0) + -Float::INFINITY }
+end
+
+assert('Time#-', '15.2.19.7.2') do
+ t1 = Time.at(1300000000.0)
+ t2 = t1.-(60)
+
+ assert_equal(t2.utc.asctime, "Sun Mar 13 07:05:40 UTC 2011")
+
+ assert_raise(FloatDomainError) { Time.at(0) - Float::NAN }
+ assert_raise(FloatDomainError) { Time.at(0) - Float::INFINITY }
+ assert_raise(FloatDomainError) { Time.at(0) - -Float::INFINITY }
+end
+
+assert('Time#<=>', '15.2.19.7.3') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1400000000.0)
+ t3 = Time.at(1500000000.0)
+
+ t2.<=>(t1) == 1 and
+ t2.<=>(t2) == 0 and
+ t2.<=>(t3) == -1 and
+ t2.<=>(nil) == nil
+end
+
+assert('Time#asctime', '15.2.19.7.4') do
+ Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
+
+assert('Time#ctime', '15.2.19.7.5') do
+ Time.at(1300000000.0).utc.ctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
+
+assert('Time#day', '15.2.19.7.6') do
+ Time.gm(2012, 12, 23).day == 23
+end
+
+assert('Time#dst?', '15.2.19.7.7') do
+ not Time.gm(2012, 12, 23).utc.dst?
+end
+
+assert('Time#getgm', '15.2.19.7.8') do
+ Time.at(1300000000.0).getgm.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
+
+assert('Time#getlocal', '15.2.19.7.9') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1300000000.0)
+ t3 = t1.getlocal
+
+ t1 == t3 and t3 == t2.getlocal
+end
+
+assert('Time#getutc', '15.2.19.7.10') do
+ Time.at(1300000000.0).getutc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
+end
+
+assert('Time#gmt?', '15.2.19.7.11') do
+ Time.at(1300000000.0).utc.gmt?
+end
+
+# ATM not implemented
+# assert('Time#gmt_offset', '15.2.19.7.12') do
+
+assert('Time#gmtime', '15.2.19.7.13') do
+ Time.at(1300000000.0).gmtime
+end
+
+# ATM not implemented
+# assert('Time#gmtoff', '15.2.19.7.14') do
+
+assert('Time#hour', '15.2.19.7.15') do
+ Time.gm(2012, 12, 23, 7, 6).hour == 7
+end
+
+# ATM doesn't really work
+# assert('Time#initialize', '15.2.19.7.16') do
+
+assert('Time#initialize_copy', '15.2.19.7.17') do
+ time_tmp_2 = Time.at(7.0e6)
+ time_tmp_2.clone == time_tmp_2
+end
+
+assert('Time#localtime', '15.2.19.7.18') do
+ t1 = Time.at(1300000000.0)
+ t2 = Time.at(1300000000.0)
+
+ t1.localtime
+ t1 == t2.getlocal
+end
+
+assert('Time#mday', '15.2.19.7.19') do
+ Time.gm(2012, 12, 23).mday == 23
+end
+
+assert('Time#min', '15.2.19.7.20') do
+ Time.gm(2012, 12, 23, 7, 6).min == 6
+end
+
+assert('Time#mon', '15.2.19.7.21') do
+ Time.gm(2012, 12, 23).mon == 12
+end
+
+assert('Time#month', '15.2.19.7.22') do
+ Time.gm(2012, 12, 23).month == 12
+end
+
+assert('Times#sec', '15.2.19.7.23') do
+ Time.gm(2012, 12, 23, 7, 6, 40).sec == 40
+end
+
+assert('Time#to_f', '15.2.19.7.24') do
+ Time.at(1300000000.0).to_f == 1300000000.0
+end
+
+assert('Time#to_i', '15.2.19.7.25') do
+ Time.at(1300000000.0).to_i == 1300000000
+end
+
+assert('Time#usec', '15.2.19.7.26') do
+ Time.at(1300000000.0).usec == 0
+end
+
+assert('Time#utc', '15.2.19.7.27') do
+ Time.at(1300000000.0).utc
+end
+
+assert('Time#utc?', '15.2.19.7.28') do
+ Time.at(1300000000.0).utc.utc?
+end
+
+# ATM not implemented
+# assert('Time#utc_offset', '15.2.19.7.29') do
+
+assert('Time#wday', '15.2.19.7.30') do
+ Time.gm(2012, 12, 23).wday == 0
+end
+
+assert('Time#yday', '15.2.19.7.31') do
+ Time.gm(2012, 12, 23).yday == 358
+end
+
+assert('Time#year', '15.2.19.7.32') do
+ Time.gm(2012, 12, 23).year == 2012
+end
+
+assert('Time#zone', '15.2.19.7.33') do
+ Time.at(1300000000.0).utc.zone == 'UTC'
+end
+
+# Not ISO specified
+
+assert('Time#to_s') do
+ Time.at(1300000000.0).utc.to_s == "Sun Mar 13 07:06:40 UTC 2011"
+end
+
+assert('Time#inspect') do
+ Time.at(1300000000.0).utc.inspect == "Sun Mar 13 07:06:40 UTC 2011"
+end
+
+assert('day of week methods') do
+ t = Time.gm(2012, 12, 24)
+ assert_false t.sunday?
+ assert_true t.monday?
+ assert_false t.tuesday?
+ assert_false t.wednesday?
+ assert_false t.thursday?
+ assert_false t.friday?
+ assert_false t.saturday?
+end
+
+assert('2000 times 500us make a second') do
+ t = Time.utc 2015
+ 2000.times do
+ t += 0.0005
+ end
+ t.usec == 0
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake
new file mode 100644
index 00000000..ce77e0bc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake
@@ -0,0 +1,5 @@
+MRuby::Gem::Specification.new('mruby-toplevel-ext') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'toplevel object (main) methods extension'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb
new file mode 100644
index 00000000..77456239
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb
@@ -0,0 +1,11 @@
+
+def self.include (*modules)
+ self.class.include(*modules)
+end
+
+def self.private(*methods)
+end
+def self.protected(*methods)
+end
+def self.public(*methods)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb
new file mode 100644
index 00000000..aebdd8b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb
@@ -0,0 +1,24 @@
+##
+# Toplevel Self(Ext) Test
+
+assert('Toplevel#include') do
+ module ToplevelTestModule1
+ def method_foo
+ :foo
+ end
+
+ CONST_BAR = :bar
+ end
+
+ module ToplevelTestModule2
+ CONST_BAR = :bar2
+ end
+
+ self.include ToplevelTestModule2, ToplevelTestModule1
+
+ assert_true self.class.included_modules.include?( ToplevelTestModule1 )
+ assert_true self.class.included_modules.include?( ToplevelTestModule2 )
+ assert_equal :foo, method_foo
+ assert_equal :bar2, CONST_BAR
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/00class.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/00class.rb
new file mode 100644
index 00000000..1a2d833c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/00class.rb
@@ -0,0 +1,28 @@
+class Module
+ # 15.2.2.4.12
+ def attr_accessor(*names)
+ attr_reader(*names)
+ attr_writer(*names)
+ end
+ # 15.2.2.4.11
+ def attr(name)
+ attr_reader(name)
+ end
+
+ # 15.2.2.4.27
+ def include(*args)
+ args.reverse.each do |m|
+ m.append_features(self)
+ m.included(self)
+ end
+ self
+ end
+
+ def prepend(*args)
+ args.reverse.each do |m|
+ m.prepend_features(self)
+ m.prepended(self)
+ end
+ self
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/10error.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/10error.rb
new file mode 100644
index 00000000..22a8d1ad
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/10error.rb
@@ -0,0 +1,56 @@
+# ISO 15.2.24
+class ArgumentError < StandardError
+end
+
+# ISO 15.2.25 says "LocalJumpError < StandardError"
+class LocalJumpError < ScriptError
+end
+
+# ISO 15.2.26
+class RangeError < StandardError
+end
+
+class FloatDomainError < RangeError
+end
+
+# ISO 15.2.26
+class RegexpError < StandardError
+end
+
+# ISO 15.2.29
+class TypeError < StandardError
+end
+
+# ISO 15.2.31
+class NameError < StandardError
+ attr_accessor :name
+
+ def initialize(message=nil, name=nil)
+ @name = name
+ super(message)
+ end
+end
+
+# ISO 15.2.32
+class NoMethodError < NameError
+ attr_reader :args
+
+ def initialize(message=nil, name=nil, args=nil)
+ @args = args
+ super message, name
+ end
+end
+
+# ISO 15.2.33
+class IndexError < StandardError
+end
+
+class KeyError < IndexError
+end
+
+class NotImplementedError < ScriptError
+end
+
+class StopIteration < IndexError
+ attr_accessor :result
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/array.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/array.rb
new file mode 100644
index 00000000..a75ed622
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/array.rb
@@ -0,0 +1,243 @@
+# coding: utf-8
+##
+# Array
+#
+# ISO 15.2.12
+class Array
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element.
+ #
+ # ISO 15.2.12.5.10
+ def each(&block)
+ return to_enum :each unless block
+
+ idx = 0
+ while idx < length
+ block.call(self[idx])
+ idx += 1
+ end
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the index of the respective element.
+ #
+ # ISO 15.2.12.5.11
+ def each_index(&block)
+ return to_enum :each_index unless block
+
+ idx = 0
+ while idx < length
+ block.call(idx)
+ idx += 1
+ end
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element. Each element will
+ # be replaced by the resulting values.
+ #
+ # ISO 15.2.12.5.7
+ def collect!(&block)
+ return to_enum :collect! unless block
+
+ idx = 0
+ len = size
+ while idx < len
+ self[idx] = block.call self[idx]
+ idx += 1
+ end
+ self
+ end
+
+ ##
+ # Alias for collect!
+ #
+ # ISO 15.2.12.5.20
+ alias map! collect!
+
+ ##
+ # Private method for Array creation.
+ #
+ # ISO 15.2.12.5.15
+ def initialize(size=0, obj=nil, &block)
+ raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integer
+ raise ArgumentError, "negative array size" if size < 0
+
+ self.clear
+ if size > 0
+ self[size - 1] = nil # allocate
+
+ idx = 0
+ while idx < size
+ self[idx] = (block)? block.call(idx): obj
+ idx += 1
+ end
+ end
+
+ self
+ end
+
+ def _inspect
+ return "[]" if self.size == 0
+ "["+self.map{|x|x.inspect}.join(", ")+"]"
+ end
+ ##
+ # Return the contents of this array as a string.
+ #
+ # ISO 15.2.12.5.31 (x)
+ def inspect
+ begin
+ self._inspect
+ rescue SystemStackError
+ "[...]"
+ end
+ end
+ # ISO 15.2.12.5.32 (x)
+ alias to_s inspect
+
+ ##
+ # Equality---Two arrays are equal if they contain the same number
+ # of elements and if each element is equal to (according to
+ # Object.==) the corresponding element in the other array.
+ #
+ # ISO 15.2.12.5.33 (x)
+ def ==(other)
+ other = self.__ary_eq(other)
+ return false if other == false
+ return true if other == true
+ len = self.size
+ i = 0
+ while i < len
+ return false if self[i] != other[i]
+ i += 1
+ end
+ return true
+ end
+
+ ##
+ # Returns <code>true</code> if +self+ and _other_ are the same object,
+ # or are both arrays with the same content.
+ #
+ # ISO 15.2.12.5.34 (x)
+ def eql?(other)
+ other = self.__ary_eq(other)
+ return false if other == false
+ return true if other == true
+ len = self.size
+ i = 0
+ while i < len
+ return false unless self[i].eql?(other[i])
+ i += 1
+ end
+ return true
+ end
+
+ ##
+ # Comparison---Returns an integer (-1, 0, or +1)
+ # if this array is less than, equal to, or greater than <i>other_ary</i>.
+ # Each object in each array is compared (using <=>). If any value isn't
+ # equal, then that inequality is the return value. If all the
+ # values found are equal, then the return is based on a
+ # comparison of the array lengths. Thus, two arrays are
+ # "equal" according to <code>Array#<=></code> if and only if they have
+ # the same length and the value of each element is equal to the
+ # value of the corresponding element in the other array.
+ #
+ # ISO 15.2.12.5.36 (x)
+ def <=>(other)
+ other = self.__ary_cmp(other)
+ return 0 if 0 == other
+ return nil if nil == other
+
+ len = self.size
+ n = other.size
+ len = n if len > n
+ i = 0
+ while i < len
+ n = (self[i] <=> other[i])
+ return n if n.nil? || n != 0
+ i += 1
+ end
+ len = self.size - other.size
+ if len == 0
+ 0
+ elsif len > 0
+ 1
+ else
+ -1
+ end
+ end
+
+ ##
+ # Delete element with index +key+
+ def delete(key, &block)
+ while i = self.index(key)
+ self.delete_at(i)
+ ret = key
+ end
+ return block.call if ret.nil? && block
+ ret
+ end
+
+ # internal method to convert multi-value to single value
+ def __svalue
+ return self.first if self.size < 2
+ self
+ end
+end
+
+##
+# Array is enumerable
+class Array
+ # ISO 15.2.12.3
+ include Enumerable
+
+ ##
+ # Quick sort
+ # a : the array to sort
+ # left : the beginning of sort region
+ # right : the end of sort region
+ def __sort_sub__(a, left, right, &block)
+ if left < right
+ i = left
+ j = right
+ pivot = a[i + (j - i) / 2]
+ while true
+ while ((block)? block.call(a[i], pivot): (a[i] <=> pivot)) < 0
+ i += 1
+ end
+ while ((block)? block.call(pivot, a[j]): (pivot <=> a[j])) < 0
+ j -= 1
+ end
+ break if (i >= j)
+ tmp = a[i]; a[i] = a[j]; a[j] = tmp;
+ i += 1
+ j -= 1
+ end
+ __sort_sub__(a, left, i-1, &block)
+ __sort_sub__(a, j+1, right, &block)
+ end
+ end
+ # private :__sort_sub__
+
+ ##
+ # Sort all elements and replace +self+ with these
+ # elements.
+ def sort!(&block)
+ size = self.size
+ if size > 1
+ __sort_sub__(self, 0, size - 1, &block)
+ end
+ self
+ end
+
+ def sort(&block)
+ self.dup.sort!(&block)
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/compar.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/compar.rb
new file mode 100644
index 00000000..84b96259
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/compar.rb
@@ -0,0 +1,84 @@
+##
+# Comparable
+#
+# ISO 15.3.3
+module Comparable
+
+ ##
+ # Return true if +self+ is less
+ # than +other+. Otherwise return
+ # false.
+ #
+ # ISO 15.3.3.2.1
+ def < other
+ cmp = self <=> other
+ if cmp.nil?
+ raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
+ end
+ cmp < 0
+ end
+
+ ##
+ # Return true if +self+ is less
+ # than or equal to +other+.
+ # Otherwise return false.
+ #
+ # ISO 15.3.3.2.2
+ def <= other
+ cmp = self <=> other
+ if cmp.nil?
+ raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
+ end
+ cmp <= 0
+ end
+
+ ##
+ # Return true if +self+ is equal
+ # to +other+. Otherwise return
+ # false.
+ #
+ # ISO 15.3.3.2.3
+ def == other
+ cmp = self <=> other
+ cmp == 0
+ end
+
+ ##
+ # Return true if +self+ is greater
+ # than +other+. Otherwise return
+ # false.
+ #
+ # ISO 15.3.3.2.4
+ def > other
+ cmp = self <=> other
+ if cmp.nil?
+ raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
+ end
+ cmp > 0
+ end
+
+ ##
+ # Return true if +self+ is greater
+ # than or equal to +other+.
+ # Otherwise return false.
+ #
+ # ISO 15.3.3.2.5
+ def >= other
+ cmp = self <=> other
+ if cmp.nil?
+ raise ArgumentError, "comparison of #{self.class} with #{other.class} failed"
+ end
+ cmp >= 0
+ end
+
+ ##
+ # Return true if +self+ is greater
+ # than or equal to +min+ and
+ # less than or equal to +max+.
+ # Otherwise return false.
+ #
+ # ISO 15.3.3.2.6
+ def between?(min, max)
+ self >= min and self <= max
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/enum.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/enum.rb
new file mode 100644
index 00000000..12bd1d37
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/enum.rb
@@ -0,0 +1,348 @@
+##
+# Enumerable
+#
+# The <code>Enumerable</code> mixin provides collection classes with
+# several traversal and searching methods, and with the ability to
+# sort. The class must provide a method `each`, which
+# yields successive members of the collection. If
+# {Enumerable#max}, {#min}, or
+# {#sort} is used, the objects in the collection must also
+# implement a meaningful `<=>` operator, as these methods
+# rely on an ordering between members of the collection.
+#
+# @ISO 15.3.2
+module Enumerable
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return false
+ # if one block value is false. Otherwise
+ # return true. If no block is given and
+ # +self+ is false return false.
+ #
+ # ISO 15.3.2.2.1
+ def all?(&block)
+ if block
+ self.each{|*val| return false unless block.call(*val)}
+ else
+ self.each{|*val| return false unless val.__svalue}
+ end
+ true
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return true
+ # if one block value is true. Otherwise
+ # return false. If no block is given and
+ # +self+ is true object return true.
+ #
+ # ISO 15.3.2.2.2
+ def any?(&block)
+ if block
+ self.each{|*val| return true if block.call(*val)}
+ else
+ self.each{|*val| return true if val.__svalue}
+ end
+ false
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Append all
+ # values of each block together and
+ # return this value.
+ #
+ # ISO 15.3.2.2.3
+ def collect(&block)
+ return to_enum :collect unless block
+
+ ary = []
+ self.each{|*val| ary.push(block.call(*val))}
+ ary
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return
+ # +ifnone+ if no block value was true.
+ # Otherwise return the first block value
+ # which had was true.
+ #
+ # ISO 15.3.2.2.4
+ def detect(ifnone=nil, &block)
+ ret = ifnone
+ self.each{|*val|
+ if block.call(*val)
+ ret = val.__svalue
+ break
+ end
+ }
+ ret
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Pass an
+ # index to the block which starts at 0
+ # and increase by 1 for each element.
+ #
+ # ISO 15.3.2.2.5
+ def each_with_index(&block)
+ return to_enum :each_with_index unless block
+
+ i = 0
+ self.each{|*val|
+ block.call(val.__svalue, i)
+ i += 1
+ }
+ self
+ end
+
+ ##
+ # Return an array of all elements which
+ # are yield by +each+.
+ #
+ # ISO 15.3.2.2.6
+ def entries
+ ary = []
+ self.each{|*val|
+ # __svalue is an internal method
+ ary.push val.__svalue
+ }
+ ary
+ end
+
+ ##
+ # Alias for find
+ #
+ # ISO 15.3.2.2.7
+ alias find detect
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return an array
+ # which contains all elements whose block
+ # value was true.
+ #
+ # ISO 15.3.2.2.8
+ def find_all(&block)
+ return to_enum :find_all unless block
+
+ ary = []
+ self.each{|*val|
+ ary.push(val.__svalue) if block.call(*val)
+ }
+ ary
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+ and which return
+ # value was true when invoking === with
+ # +pattern+. Return an array with all
+ # elements or the respective block values.
+ #
+ # ISO 15.3.2.2.9
+ def grep(pattern, &block)
+ ary = []
+ self.each{|*val|
+ sv = val.__svalue
+ if pattern === sv
+ ary.push((block)? block.call(*val): sv)
+ end
+ }
+ ary
+ end
+
+ ##
+ # Return true if at least one element which
+ # is yield by +each+ returns a true value
+ # by invoking == with +obj+. Otherwise return
+ # false.
+ #
+ # ISO 15.3.2.2.10
+ def include?(obj)
+ self.each{|*val|
+ return true if val.__svalue == obj
+ }
+ false
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return value
+ # is the sum of all block values. Pass
+ # to each block the current sum and the
+ # current element.
+ #
+ # ISO 15.3.2.2.11
+ def inject(*args, &block)
+ raise ArgumentError, "too many arguments" if args.size > 2
+ if Symbol === args[-1]
+ sym = args[-1]
+ block = ->(x,y){x.__send__(sym,y)}
+ args.pop
+ end
+ if args.empty?
+ flag = true # no initial argument
+ result = nil
+ else
+ flag = false
+ result = args[0]
+ end
+ self.each{|*val|
+ val = val.__svalue
+ if flag
+ # push first element as initial
+ flag = false
+ result = val
+ else
+ result = block.call(result, val)
+ end
+ }
+ result
+ end
+ alias reduce inject
+
+ ##
+ # Alias for collect
+ #
+ # ISO 15.3.2.2.12
+ alias map collect
+
+ ##
+ # Return the maximum value of all elements
+ # yield by +each+. If no block is given <=>
+ # will be invoked to define this value. If
+ # a block is given it will be used instead.
+ #
+ # ISO 15.3.2.2.13
+ def max(&block)
+ flag = true # 1st element?
+ result = nil
+ self.each{|*val|
+ val = val.__svalue
+ if flag
+ # 1st element
+ result = val
+ flag = false
+ else
+ if block
+ result = val if block.call(val, result) > 0
+ else
+ result = val if (val <=> result) > 0
+ end
+ end
+ }
+ result
+ end
+
+ ##
+ # Return the minimum value of all elements
+ # yield by +each+. If no block is given <=>
+ # will be invoked to define this value. If
+ # a block is given it will be used instead.
+ #
+ # ISO 15.3.2.2.14
+ def min(&block)
+ flag = true # 1st element?
+ result = nil
+ self.each{|*val|
+ val = val.__svalue
+ if flag
+ # 1st element
+ result = val
+ flag = false
+ else
+ if block
+ result = val if block.call(val, result) < 0
+ else
+ result = val if (val <=> result) < 0
+ end
+ end
+ }
+ result
+ end
+
+ ##
+ # Alias for include?
+ #
+ # ISO 15.3.2.2.15
+ alias member? include?
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return an
+ # array which contains two arrays. The
+ # first array contains all elements
+ # whose block value was true. The second
+ # array contains all elements whose
+ # block value was false.
+ #
+ # ISO 15.3.2.2.16
+ def partition(&block)
+ ary_T = []
+ ary_F = []
+ self.each{|*val|
+ if block.call(*val)
+ ary_T.push(val.__svalue)
+ else
+ ary_F.push(val.__svalue)
+ end
+ }
+ [ary_T, ary_F]
+ end
+
+ ##
+ # Call the given block for each element
+ # which is yield by +each+. Return an
+ # array which contains only the elements
+ # whose block value was false.
+ #
+ # ISO 15.3.2.2.17
+ def reject(&block)
+ ary = []
+ self.each{|*val|
+ ary.push(val.__svalue) unless block.call(*val)
+ }
+ ary
+ end
+
+ ##
+ # Alias for find_all.
+ #
+ # ISO 15.3.2.2.18
+ alias select find_all
+
+ ##
+ # Return a sorted array of all elements
+ # which are yield by +each+. If no block
+ # is given <=> will be invoked on each
+ # element to define the order. Otherwise
+ # the given block will be used for
+ # sorting.
+ #
+ # ISO 15.3.2.2.19
+ def sort(&block)
+ self.map{|*val| val.__svalue}.sort
+ end
+
+ ##
+ # Alias for entries.
+ #
+ # ISO 15.3.2.2.20
+ alias to_a entries
+
+ # redefine #hash 15.3.1.3.15
+ def hash
+ h = 12347
+ i = 0
+ self.each do |e|
+ n = (e.hash & (0x7fffffff >> (i % 16))) << (i % 16)
+ h ^= n
+ i += 1
+ end
+ h
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/hash.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/hash.rb
new file mode 100644
index 00000000..6b4803cc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/hash.rb
@@ -0,0 +1,358 @@
+##
+# Hash
+#
+# ISO 15.2.13
+class Hash
+ ##
+ # Equality---Two hashes are equal if they each contain the same number
+ # of keys and if each key-value pair is equal to (according to
+ # <code>Object#==</code>) the corresponding elements in the other
+ # hash.
+ #
+ # ISO 15.2.13.4.1
+ def ==(hash)
+ return true if self.equal?(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ return false
+ end
+ return false if self.size != hash.size
+ self.each do |k,v|
+ return false unless hash.key?(k)
+ return false unless self[k] == hash[k]
+ end
+ return true
+ end
+
+ ##
+ # Returns <code>true</code> if <i>hash</i> and <i>other</i> are
+ # both hashes with the same content compared by eql?.
+ #
+ # ISO 15.2.13.4.32 (x)
+ def eql?(hash)
+ return true if self.equal?(hash)
+ begin
+ hash = hash.to_hash
+ rescue NoMethodError
+ return false
+ end
+ return false if self.size != hash.size
+ self.each do |k,v|
+ return false unless hash.key?(k)
+ return false unless self[k].eql?(hash[k])
+ end
+ return true
+ end
+
+ ##
+ # Delete the element with the key +key+.
+ # Return the value of the element if +key+
+ # was found. Return nil if nothing was
+ # found. If a block is given, call the
+ # block with the value of the element.
+ #
+ # ISO 15.2.13.4.8
+ def delete(key, &block)
+ if block && !self.has_key?(key)
+ block.call(key)
+ else
+ self.__delete(key)
+ end
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the key and value of each element.
+ #
+ # call-seq:
+ # hsh.each {| key, value | block } -> hsh
+ # hsh.each_pair {| key, value | block } -> hsh
+ # hsh.each -> an_enumerator
+ # hsh.each_pair -> an_enumerator
+ #
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200 }
+ # h.each {|key, value| puts "#{key} is #{value}" }
+ #
+ # <em>produces:</em>
+ #
+ # a is 100
+ # b is 200
+ #
+ # ISO 15.2.13.4.9
+ def each(&block)
+ return to_enum :each unless block
+
+ keys = self.keys
+ vals = self.values
+ len = self.size
+ i = 0
+ while i < len
+ block.call [keys[i], vals[i]]
+ i += 1
+ end
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the key of each element.
+ #
+ # call-seq:
+ # hsh.each_key {| key | block } -> hsh
+ # hsh.each_key -> an_enumerator
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200 }
+ # h.each_key {|key| puts key }
+ #
+ # <em>produces:</em>
+ #
+ # a
+ # b
+ #
+ # ISO 15.2.13.4.10
+ def each_key(&block)
+ return to_enum :each_key unless block
+
+ self.keys.each{|k| block.call(k)}
+ self
+ end
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the value of each element.
+ #
+ # call-seq:
+ # hsh.each_value {| value | block } -> hsh
+ # hsh.each_value -> an_enumerator
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200 }
+ # h.each_value {|value| puts value }
+ #
+ # <em>produces:</em>
+ #
+ # 100
+ # 200
+ #
+ # ISO 15.2.13.4.11
+ def each_value(&block)
+ return to_enum :each_value unless block
+
+ self.keys.each{|k| block.call(self[k])}
+ self
+ end
+
+ ##
+ # Replaces the contents of <i>hsh</i> with the contents of other hash
+ #
+ # ISO 15.2.13.4.23
+ def replace(hash)
+ raise TypeError, "can't convert argument into Hash" unless hash.respond_to?(:to_hash)
+ self.clear
+ hash = hash.to_hash
+ hash.each_key{|k|
+ self[k] = hash[k]
+ }
+ if hash.default_proc
+ self.default_proc = hash.default_proc
+ else
+ self.default = hash.default
+ end
+ self
+ end
+ # ISO 15.2.13.4.17
+ alias initialize_copy replace
+
+ ##
+ # Return a hash which contains the content of
+ # +self+ and +other+. If a block is given
+ # it will be called for each element with
+ # a duplicate key. The value of the block
+ # will be the final value of this element.
+ #
+ # ISO 15.2.13.4.22
+ def merge(other, &block)
+ h = {}
+ raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
+ other = other.to_hash
+ self.each_key{|k| h[k] = self[k]}
+ if block
+ other.each_key{|k|
+ h[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
+ }
+ else
+ other.each_key{|k| h[k] = other[k]}
+ end
+ h
+ end
+
+ # internal method for Hash inspection
+ def _inspect
+ return "{}" if self.size == 0
+ "{"+self.map {|k,v|
+ k._inspect + "=>" + v._inspect
+ }.join(", ")+"}"
+ end
+ ##
+ # Return the contents of this hash as a string.
+ #
+ # ISO 15.2.13.4.30 (x)
+ def inspect
+ begin
+ self._inspect
+ rescue SystemStackError
+ "{...}"
+ end
+ end
+ # ISO 15.2.13.4.31 (x)
+ alias to_s inspect
+
+ ##
+ # call-seq:
+ # hsh.reject! {| key, value | block } -> hsh or nil
+ # hsh.reject! -> an_enumerator
+ #
+ # Equivalent to <code>Hash#delete_if</code>, but returns
+ # <code>nil</code> if no changes were made.
+ #
+ # 1.8/1.9 Hash#reject! returns Hash; ISO says nothing.
+ #
+ def reject!(&block)
+ return to_enum :reject! unless block
+
+ keys = []
+ self.each{|k,v|
+ if block.call([k, v])
+ keys.push(k)
+ end
+ }
+ return nil if keys.size == 0
+ keys.each{|k|
+ self.delete(k)
+ }
+ self
+ end
+
+ ##
+ # call-seq:
+ # hsh.reject {|key, value| block} -> a_hash
+ # hsh.reject -> an_enumerator
+ #
+ # Returns a new hash consisting of entries for which the block returns false.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300 }
+ # h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300}
+ # h.reject {|k,v| v > 100} #=> {"a" => 100}
+ #
+ # 1.8/1.9 Hash#reject returns Hash; ISO says nothing.
+ #
+ def reject(&block)
+ return to_enum :reject unless block
+
+ h = {}
+ self.each{|k,v|
+ unless block.call([k, v])
+ h[k] = v
+ end
+ }
+ h
+ end
+
+ ##
+ # call-seq:
+ # hsh.select! {| key, value | block } -> hsh or nil
+ # hsh.select! -> an_enumerator
+ #
+ # Equivalent to <code>Hash#keep_if</code>, but returns
+ # <code>nil</code> if no changes were made.
+ #
+ # 1.9 Hash#select! returns Hash; ISO says nothing.
+ #
+ def select!(&block)
+ return to_enum :select! unless block
+
+ keys = []
+ self.each{|k,v|
+ unless block.call([k, v])
+ keys.push(k)
+ end
+ }
+ return nil if keys.size == 0
+ keys.each{|k|
+ self.delete(k)
+ }
+ self
+ end
+
+ ##
+ # call-seq:
+ # hsh.select {|key, value| block} -> a_hash
+ # hsh.select -> an_enumerator
+ #
+ # Returns a new hash consisting of entries for which the block returns true.
+ #
+ # If no block is given, an enumerator is returned instead.
+ #
+ # h = { "a" => 100, "b" => 200, "c" => 300 }
+ # h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300}
+ # h.select {|k,v| v < 200} #=> {"a" => 100}
+ #
+ # 1.9 Hash#select returns Hash; ISO says nothing
+ #
+ def select(&block)
+ return to_enum :select unless block
+
+ h = {}
+ self.each{|k,v|
+ if block.call([k, v])
+ h[k] = v
+ end
+ }
+ h
+ end
+
+ ##
+ # call-seq:
+ # hsh.rehash -> hsh
+ #
+ # Rebuilds the hash based on the current hash values for each key. If
+ # values of key objects have changed since they were inserted, this
+ # method will reindex <i>hsh</i>.
+ #
+ # h = {"AAA" => "b"}
+ # h.keys[0].chop!
+ # h #=> {"AA"=>"b"}
+ # h["AA"] #=> nil
+ # h.rehash #=> {"AA"=>"b"}
+ # h["AA"] #=> "b"
+ #
+ def rehash
+ h = {}
+ self.each{|k,v|
+ h[k] = v
+ }
+ self.replace(h)
+ end
+
+ def __update(h)
+ h.each_key{|k| self[k] = h[k]}
+ self
+ end
+end
+
+##
+# Hash is enumerable
+#
+# ISO 15.2.13.3
+class Hash
+ include Enumerable
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/init_mrblib.c b/web/server/h2o/libh2o/deps/mruby/mrblib/init_mrblib.c
new file mode 100644
index 00000000..4d4bcd25
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/init_mrblib.c
@@ -0,0 +1,11 @@
+#include <mruby.h>
+#include <mruby/irep.h>
+
+extern const uint8_t mrblib_irep[];
+
+void
+mrb_init_mrblib(mrb_state *mrb)
+{
+ mrb_load_irep(mrb, mrblib_irep);
+}
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/kernel.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/kernel.rb
new file mode 100644
index 00000000..550ae817
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/kernel.rb
@@ -0,0 +1,50 @@
+##
+# Kernel
+#
+# ISO 15.3.1
+module Kernel
+
+ # 15.3.1.2.1 Kernel.`
+ # provided by Kernel#`
+ # 15.3.1.3.5
+ def `(s)
+ raise NotImplementedError.new("backquotes not implemented")
+ end
+
+ ##
+ # 15.3.1.2.3 Kernel.eval
+ # 15.3.1.3.12 Kernel#eval
+ # NotImplemented by mruby core; use mruby-eval gem
+
+ ##
+ # ISO 15.3.1.2.8 Kernel.loop
+ # provided by Kernel#loop
+
+ ##
+ # Calls the given block repetitively.
+ #
+ # ISO 15.3.1.3.29
+ def loop(&block)
+ return to_enum :loop unless block
+
+ while true
+ yield
+ end
+ rescue StopIteration => e
+ e.result
+ end
+
+ # 11.4.4 Step c)
+ def !~(y)
+ !(self =~ y)
+ end
+
+ # internal method for inspect
+ def _inspect
+ self.inspect
+ end
+
+ def to_enum(*a)
+ raise NotImplementedError.new("fiber required for enumerator")
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/mrblib.rake b/web/server/h2o/libh2o/deps/mruby/mrblib/mrblib.rake
new file mode 100644
index 00000000..19fd00d6
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/mrblib.rake
@@ -0,0 +1,18 @@
+MRuby.each_target do
+ current_dir = File.dirname(__FILE__)
+ relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT)
+ current_build_dir = "#{build_dir}/#{relative_from_root}"
+
+ self.libmruby << objfile("#{current_build_dir}/mrblib")
+
+ file objfile("#{current_build_dir}/mrblib") => "#{current_build_dir}/mrblib.c"
+ file "#{current_build_dir}/mrblib.c" => [mrbcfile, __FILE__] + Dir.glob("#{current_dir}/*.rb").sort do |t|
+ _, _, *rbfiles = t.prerequisites
+ FileUtils.mkdir_p File.dirname(t.name)
+ open(t.name, 'w') do |f|
+ _pp "GEN", "*.rb", "#{t.name.relative_path}"
+ f.puts File.read("#{current_dir}/init_mrblib.c")
+ mrbc.run f, rbfiles, 'mrblib_irep'
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/numeric.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/numeric.rb
new file mode 100644
index 00000000..89401a08
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/numeric.rb
@@ -0,0 +1,173 @@
+##
+# Numeric
+#
+# ISO 15.2.7
+class Numeric
+ include Comparable
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.7.4.1
+ def +@
+ self
+ end
+
+ ##
+ # Returns the receiver's value, negated.
+ #
+ # ISO 15.2.7.4.2
+ def -@
+ 0 - self
+ end
+
+ ##
+ # Returns the absolute value of the receiver.
+ #
+ # ISO 15.2.7.4.3
+ def abs
+ if self < 0
+ -self
+ else
+ self
+ end
+ end
+end
+
+##
+# Integral
+#
+# mruby special - module to share methods between Floats and Integers
+# to make them compatible
+module Integral
+ ##
+ # Calls the given block once for each Integer
+ # from +self+ downto +num+.
+ #
+ # ISO 15.2.8.3.15
+ def downto(num, &block)
+ return to_enum(:downto, num) unless block
+
+ i = self.to_i
+ while i >= num
+ block.call(i)
+ i -= 1
+ end
+ self
+ end
+
+ ##
+ # Returns self + 1
+ #
+ # ISO 15.2.8.3.19
+ def next
+ self + 1
+ end
+ # ISO 15.2.8.3.21
+ alias succ next
+
+ ##
+ # Calls the given block +self+ times.
+ #
+ # ISO 15.2.8.3.22
+ def times &block
+ return to_enum :times unless block
+
+ i = 0
+ while i < self
+ block.call i
+ i += 1
+ end
+ self
+ end
+
+ ##
+ # Calls the given block once for each Integer
+ # from +self+ upto +num+.
+ #
+ # ISO 15.2.8.3.27
+ def upto(num, &block)
+ return to_enum(:upto, num) unless block
+
+ i = self.to_i
+ while i <= num
+ block.call(i)
+ i += 1
+ end
+ self
+ end
+
+ ##
+ # Calls the given block from +self+ to +num+
+ # incremented by +step+ (default 1).
+ #
+ def step(num=nil, step=1, &block)
+ raise ArgumentError, "step can't be 0" if step == 0
+ return to_enum(:step, num, step) unless block
+
+ i = if num.kind_of? Float then self.to_f else self end
+ if num == nil
+ while true
+ block.call(i)
+ i+=step
+ end
+ return self
+ end
+ if step > 0
+ while i <= num
+ block.call(i)
+ i += step
+ end
+ else
+ while i >= num
+ block.call(i)
+ i += step
+ end
+ end
+ self
+ end
+end
+
+##
+# Integer
+#
+# ISO 15.2.8
+class Integer
+ include Integral
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.14
+ def ceil
+ self
+ end
+
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.17
+ def floor
+ self
+ end
+
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.24
+ alias round floor
+
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.26
+ alias truncate floor
+end
+
+##
+# Float
+#
+# ISO 15.2.9
+class Float
+ # mruby special - since mruby integers may be upgraded to floats,
+ # floats should be compatible to integers.
+ include Integral
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/range.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/range.rb
new file mode 100644
index 00000000..5bd2521e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/range.rb
@@ -0,0 +1,67 @@
+##
+# Range
+#
+# ISO 15.2.14
+class Range
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element.
+ #
+ # ISO 15.2.14.4.4
+ def each(&block)
+ return to_enum :each unless block
+
+ val = self.first
+ last = self.last
+
+ if val.kind_of?(Fixnum) && last.kind_of?(Fixnum) # fixnums are special
+ lim = last
+ lim += 1 unless exclude_end?
+ i = val
+ while i < lim
+ block.call(i)
+ i += 1
+ end
+ return self
+ end
+
+ if val.kind_of?(String) && last.kind_of?(String) # fixnums are special
+ if val.respond_to? :upto
+ return val.upto(last, exclude_end?, &block)
+ else
+ str_each = true
+ end
+ end
+
+ raise TypeError, "can't iterate" unless val.respond_to? :succ
+
+ return self if (val <=> last) > 0
+
+ while (val <=> last) < 0
+ block.call(val)
+ val = val.succ
+ if str_each
+ break if val.size > last.size
+ end
+ end
+
+ block.call(val) if !exclude_end? && (val <=> last) == 0
+ self
+ end
+
+ # redefine #hash 15.3.1.3.15
+ def hash
+ h = first.hash ^ last.hash
+ h += 1 if self.exclude_end?
+ h
+ end
+end
+
+##
+# Range is enumerable
+#
+# ISO 15.2.14.3
+class Range
+ include Enumerable
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrblib/string.rb b/web/server/h2o/libh2o/deps/mruby/mrblib/string.rb
new file mode 100644
index 00000000..4c6114ec
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrblib/string.rb
@@ -0,0 +1,275 @@
+##
+# String
+#
+# ISO 15.2.10
+class String
+ include Comparable
+ ##
+ # Calls the given block for each line
+ # and pass the respective line.
+ #
+ # ISO 15.2.10.5.15
+ def each_line(rs = "\n", &block)
+ return to_enum(:each_line, rs, &block) unless block
+ return block.call(self) if rs.nil?
+ rs = rs.to_str
+ offset = 0
+ rs_len = rs.length
+ this = dup
+ while pos = this.index(rs, offset)
+ block.call(this[offset, pos + rs_len - offset])
+ offset = pos + rs_len
+ end
+ block.call(this[offset, this.size - offset]) if this.size > offset
+ self
+ end
+
+ # private method for gsub/sub
+ def __sub_replace(pre, m, post)
+ s = ""
+ i = 0
+ while j = index("\\", i)
+ break if j == length-1
+ t = case self[j+1]
+ when "\\"
+ "\\"
+ when "`"
+ pre
+ when "&", "0"
+ m
+ when "'"
+ post
+ when "1", "2", "3", "4", "5", "6", "7", "8", "9"
+ ""
+ else
+ self[j, 2]
+ end
+ s += self[i, j-i] + t
+ i = j + 2
+ end
+ s + self[i, length-i]
+ end
+
+ ##
+ # Replace all matches of +pattern+ with +replacement+.
+ # Call block (if given) for each match and replace
+ # +pattern+ with the value of the block. Return the
+ # final value.
+ #
+ # ISO 15.2.10.5.18
+ def gsub(*args, &block)
+ return to_enum(:gsub, *args) if args.length == 1 && !block
+ raise ArgumentError, "wrong number of arguments" unless (1..2).include?(args.length)
+
+ pattern, replace = *args
+ plen = pattern.length
+ if args.length == 2 && block
+ block = nil
+ end
+ if !replace.nil? || !block
+ replace = replace.to_str
+ end
+ offset = 0
+ result = []
+ while found = index(pattern, offset)
+ result << self[offset, found - offset]
+ offset = found + plen
+ result << if block
+ block.call(pattern).to_s
+ else
+ replace.__sub_replace(self[0, found], pattern, self[offset..-1] || "")
+ end
+ if plen == 0
+ result << self[offset, 1]
+ offset += 1
+ end
+ end
+ result << self[offset..-1] if offset < length
+ result.join
+ end
+
+ ##
+ # Replace all matches of +pattern+ with +replacement+.
+ # Call block (if given) for each match and replace
+ # +pattern+ with the value of the block. Modify
+ # +self+ with the final value.
+ #
+ # ISO 15.2.10.5.19
+ def gsub!(*args, &block)
+ raise RuntimeError, "can't modify frozen String" if frozen?
+ return to_enum(:gsub!, *args) if args.length == 1 && !block
+ str = self.gsub(*args, &block)
+ return nil if str == self
+ self.replace(str)
+ end
+
+ ##
+ # Calls the given block for each match of +pattern+
+ # If no block is given return an array with all
+ # matches of +pattern+.
+ #
+ # ISO 15.2.10.5.32
+ def scan(reg, &block)
+ ### *** TODO *** ###
+ unless Object.const_defined?(:Regexp)
+ raise NotImplementedError, "scan not available (yet)"
+ end
+ end
+
+ ##
+ # Replace only the first match of +pattern+ with
+ # +replacement+. Call block (if given) for each
+ # match and replace +pattern+ with the value of the
+ # block. Return the final value.
+ #
+ # ISO 15.2.10.5.36
+ def sub(*args, &block)
+ unless (1..2).include?(args.length)
+ raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 2)"
+ end
+
+ pattern, replace = *args
+ pattern = pattern.to_str
+ if args.length == 2 && block
+ block = nil
+ end
+ unless block
+ replace = replace.to_str
+ end
+ result = []
+ this = dup
+ found = index(pattern)
+ return this unless found
+ result << this[0, found]
+ offset = found + pattern.length
+ result << if block
+ block.call(pattern).to_s
+ else
+ replace.__sub_replace(this[0, found], pattern, this[offset..-1] || "")
+ end
+ result << this[offset..-1] if offset < length
+ result.join
+ end
+
+ ##
+ # Replace only the first match of +pattern+ with
+ # +replacement+. Call block (if given) for each
+ # match and replace +pattern+ with the value of the
+ # block. Modify +self+ with the final value.
+ #
+ # ISO 15.2.10.5.37
+ def sub!(*args, &block)
+ raise RuntimeError, "can't modify frozen String" if frozen?
+ str = self.sub(*args, &block)
+ return nil if str == self
+ self.replace(str)
+ end
+
+ ##
+ # Call the given block for each character of
+ # +self+.
+ def each_char(&block)
+ pos = 0
+ while pos < self.size
+ block.call(self[pos])
+ pos += 1
+ end
+ self
+ end
+
+ ##
+ # Call the given block for each byte of +self+.
+ def each_byte(&block)
+ bytes = self.bytes
+ pos = 0
+ while pos < bytes.size
+ block.call(bytes[pos])
+ pos += 1
+ end
+ self
+ end
+
+ ##
+ # Modify +self+ by replacing the content of +self+.
+ # The portion of the string affected is determined using the same criteria as +String#[]+.
+ def []=(*args)
+ anum = args.size
+ if anum == 2
+ pos, value = args
+ case pos
+ when String
+ posnum = self.index(pos)
+ if posnum
+ b = self[0, posnum.to_i]
+ a = self[(posnum + pos.length)..-1]
+ self.replace([b, value, a].join(''))
+ else
+ raise IndexError, "string not matched"
+ end
+ when Range
+ head = pos.begin
+ tail = pos.end
+ tail += self.length if tail < 0
+ unless pos.exclude_end?
+ tail += 1
+ end
+ return self[head, tail-head]=value
+ else
+ pos += self.length if pos < 0
+ if pos < 0 || pos > self.length
+ raise IndexError, "index #{args[0]} out of string"
+ end
+ b = self[0, pos.to_i]
+ a = self[pos + 1..-1]
+ self.replace([b, value, a].join(''))
+ end
+ return value
+ elsif anum == 3
+ pos, len, value = args
+ pos += self.length if pos < 0
+ if pos < 0 || pos > self.length
+ raise IndexError, "index #{args[0]} out of string"
+ end
+ if len < 0
+ raise IndexError, "negative length #{len}"
+ end
+ b = self[0, pos.to_i]
+ a = self[pos + len..-1]
+ self.replace([b, value, a].join(''))
+ return value
+ else
+ raise ArgumentError, "wrong number of arguments (#{anum} for 2..3)"
+ end
+ end
+
+ ##
+ # ISO 15.2.10.5.3
+ def =~(re)
+ raise TypeError, "type mismatch: String given" if re.respond_to? :to_str
+ re =~ self
+ end
+
+ ##
+ # ISO 15.2.10.5.27
+ def match(re, &block)
+ if re.respond_to? :to_str
+ if Object.const_defined?(:Regexp)
+ r = Regexp.new(re)
+ r.match(self, &block)
+ else
+ raise NotImplementedError, "String#match needs Regexp class"
+ end
+ else
+ re.match(self, &block)
+ end
+ end
+end
+
+##
+# String is comparable
+#
+# ISO 15.2.10.3
+module Comparable; end
+class String
+ include Comparable
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mruby-source.gemspec b/web/server/h2o/libh2o/deps/mruby/mruby-source.gemspec
new file mode 100644
index 00000000..62d4c0d1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mruby-source.gemspec
@@ -0,0 +1,18 @@
+# coding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'mruby/source'
+
+Gem::Specification.new do |spec|
+ spec.name = "mruby-source"
+ spec.version = MRuby::Source::MRUBY_VERSION
+ spec.authors = [ MRuby::Source::MRUBY_AUTHOR ]
+
+ spec.summary = %q{MRuby source code wrapper.}
+ spec.description = %q{MRuby source code wrapper for use with Ruby libs.}
+ spec.homepage = "http://www.mruby.org/"
+ spec.license = "MIT"
+
+ spec.files = `git ls-files -z`.split("\x0")
+ spec.require_paths = ["lib"]
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/src/array.c b/web/server/h2o/libh2o/deps/mruby/src/array.c
new file mode 100644
index 00000000..8f33defe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/array.c
@@ -0,0 +1,1249 @@
+/*
+** array.c - Array class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/string.h>
+#include <mruby/range.h>
+#include "value_array.h"
+
+#define ARY_DEFAULT_LEN 4
+#define ARY_SHRINK_RATIO 5 /* must be larger than 2 */
+#define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value))
+#define ARY_MAX_SIZE ((mrb_int)((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? ARY_C_MAX_SIZE : MRB_INT_MAX-1))
+
+static struct RArray*
+ary_new_capa(mrb_state *mrb, mrb_int capa)
+{
+ struct RArray *a;
+ size_t blen;
+
+ if (capa > ARY_MAX_SIZE) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
+ blen = capa * sizeof(mrb_value);
+
+ a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
+ if (capa <= MRB_ARY_EMBED_LEN_MAX) {
+ ARY_SET_EMBED_LEN(a, 0);
+ }
+ else {
+ a->as.heap.ptr = (mrb_value *)mrb_malloc(mrb, blen);
+ a->as.heap.aux.capa = capa;
+ a->as.heap.len = 0;
+ }
+
+ return a;
+}
+
+MRB_API mrb_value
+mrb_ary_new_capa(mrb_state *mrb, mrb_int capa)
+{
+ struct RArray *a = ary_new_capa(mrb, capa);
+ return mrb_obj_value(a);
+}
+
+MRB_API mrb_value
+mrb_ary_new(mrb_state *mrb)
+{
+ return mrb_ary_new_capa(mrb, 0);
+}
+
+/*
+ * to copy array, use this instead of memcpy because of portability
+ * * gcc on ARM may fail optimization of memcpy
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3934.html
+ * * gcc on MIPS also fail
+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39755
+ * * memcpy doesn't exist on freestanding environment
+ *
+ * If you optimize for binary size, use memcpy instead of this at your own risk
+ * of above portability issue.
+ *
+ * see also http://togetter.com/li/462898
+ *
+ */
+static inline void
+array_copy(mrb_value *dst, const mrb_value *src, mrb_int size)
+{
+ mrb_int i;
+
+ for (i = 0; i < size; i++) {
+ dst[i] = src[i];
+ }
+}
+
+MRB_API mrb_value
+mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals)
+{
+ struct RArray *a = ary_new_capa(mrb, size);
+
+ array_copy(ARY_PTR(a), vals, size);
+ ARY_SET_LEN(a, size);
+
+ return mrb_obj_value(a);
+}
+
+MRB_API mrb_value
+mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr)
+{
+ struct RArray *a;
+
+ a = ary_new_capa(mrb, 2);
+ ARY_PTR(a)[0] = car;
+ ARY_PTR(a)[1] = cdr;
+ ARY_SET_LEN(a, 2);
+ return mrb_obj_value(a);
+}
+
+static void
+ary_fill_with_nil(mrb_value *ptr, mrb_int size)
+{
+ mrb_value nil = mrb_nil_value();
+
+ while (size--) {
+ *ptr++ = nil;
+ }
+}
+
+static void
+ary_modify_check(mrb_state *mrb, struct RArray *a)
+{
+ if (MRB_FROZEN_P(a)) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array");
+ }
+}
+
+static void
+ary_modify(mrb_state *mrb, struct RArray *a)
+{
+ ary_modify_check(mrb, a);
+
+ if (ARY_SHARED_P(a)) {
+ mrb_shared_array *shared = a->as.heap.aux.shared;
+
+ if (shared->refcnt == 1 && a->as.heap.ptr == shared->ptr) {
+ a->as.heap.ptr = shared->ptr;
+ a->as.heap.aux.capa = a->as.heap.len;
+ mrb_free(mrb, shared);
+ }
+ else {
+ mrb_value *ptr, *p;
+ mrb_int len;
+
+ p = a->as.heap.ptr;
+ len = a->as.heap.len * sizeof(mrb_value);
+ ptr = (mrb_value *)mrb_malloc(mrb, len);
+ if (p) {
+ array_copy(ptr, p, a->as.heap.len);
+ }
+ a->as.heap.ptr = ptr;
+ a->as.heap.aux.capa = a->as.heap.len;
+ mrb_ary_decref(mrb, shared);
+ }
+ ARY_UNSET_SHARED_FLAG(a);
+ }
+}
+
+MRB_API void
+mrb_ary_modify(mrb_state *mrb, struct RArray* a)
+{
+ mrb_write_barrier(mrb, (struct RBasic*)a);
+ ary_modify(mrb, a);
+}
+
+static void
+ary_make_shared(mrb_state *mrb, struct RArray *a)
+{
+ if (!ARY_SHARED_P(a) && !ARY_EMBED_P(a)) {
+ mrb_shared_array *shared = (mrb_shared_array *)mrb_malloc(mrb, sizeof(mrb_shared_array));
+ mrb_value *ptr = a->as.heap.ptr;
+ mrb_int len = a->as.heap.len;
+
+ shared->refcnt = 1;
+ if (a->as.heap.aux.capa > len) {
+ a->as.heap.ptr = shared->ptr = (mrb_value *)mrb_realloc(mrb, ptr, sizeof(mrb_value)*len+1);
+ }
+ else {
+ shared->ptr = ptr;
+ }
+ shared->len = len;
+ a->as.heap.aux.shared = shared;
+ ARY_SET_SHARED_FLAG(a);
+ }
+}
+
+static void
+ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len)
+{
+ mrb_int capa = ARY_CAPA(a);
+
+ if (len > ARY_MAX_SIZE || len < 0) {
+ size_error:
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
+
+ if (capa < ARY_DEFAULT_LEN) {
+ capa = ARY_DEFAULT_LEN;
+ }
+ while (capa < len) {
+ if (capa <= ARY_MAX_SIZE / 2) {
+ capa *= 2;
+ }
+ else {
+ capa = len;
+ }
+ }
+ if (capa < len || capa > ARY_MAX_SIZE) {
+ goto size_error;
+ }
+
+ if (ARY_EMBED_P(a)) {
+ mrb_value *ptr = ARY_EMBED_PTR(a);
+ mrb_int len = ARY_EMBED_LEN(a);
+ mrb_value *expanded_ptr = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*capa);
+
+ ARY_UNSET_EMBED_FLAG(a);
+ array_copy(expanded_ptr, ptr, len);
+ a->as.heap.len = len;
+ a->as.heap.aux.capa = capa;
+ a->as.heap.ptr = expanded_ptr;
+ }
+ else if (capa > a->as.heap.aux.capa) {
+ mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->as.heap.ptr, sizeof(mrb_value)*capa);
+
+ a->as.heap.aux.capa = capa;
+ a->as.heap.ptr = expanded_ptr;
+ }
+}
+
+static void
+ary_shrink_capa(mrb_state *mrb, struct RArray *a)
+{
+
+ mrb_int capa;
+
+ if (ARY_EMBED_P(a)) return;
+
+ capa = a->as.heap.aux.capa;
+ if (capa < ARY_DEFAULT_LEN * 2) return;
+ if (capa <= a->as.heap.len * ARY_SHRINK_RATIO) return;
+
+ do {
+ capa /= 2;
+ if (capa < ARY_DEFAULT_LEN) {
+ capa = ARY_DEFAULT_LEN;
+ break;
+ }
+ } while (capa > a->as.heap.len * ARY_SHRINK_RATIO);
+
+ if (capa > a->as.heap.len && capa < a->as.heap.aux.capa) {
+ a->as.heap.aux.capa = capa;
+ a->as.heap.ptr = (mrb_value *)mrb_realloc(mrb, a->as.heap.ptr, sizeof(mrb_value)*capa);
+ }
+}
+
+MRB_API mrb_value
+mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len)
+{
+ mrb_int old_len;
+ struct RArray *a = mrb_ary_ptr(ary);
+
+ ary_modify(mrb, a);
+ old_len = RARRAY_LEN(ary);
+ if (old_len != new_len) {
+ ARY_SET_LEN(a, new_len);
+ if (new_len < old_len) {
+ ary_shrink_capa(mrb, a);
+ }
+ else {
+ ary_expand_capa(mrb, a, new_len);
+ ary_fill_with_nil(ARY_PTR(a) + old_len, new_len - old_len);
+ }
+ }
+
+ return ary;
+}
+
+static mrb_value
+mrb_ary_s_create(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value ary;
+ mrb_value *vals;
+ mrb_int len;
+ struct RArray *a;
+
+ mrb_get_args(mrb, "*!", &vals, &len);
+ ary = mrb_ary_new_from_values(mrb, len, vals);
+ a = mrb_ary_ptr(ary);
+ a->c = mrb_class_ptr(klass);
+
+ return ary;
+}
+
+static void
+ary_concat(mrb_state *mrb, struct RArray *a, struct RArray *a2)
+{
+ mrb_int len;
+
+ if (ARY_LEN(a2) > ARY_MAX_SIZE - ARY_LEN(a)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
+ len = ARY_LEN(a) + ARY_LEN(a2);
+
+ ary_modify(mrb, a);
+ if (ARY_CAPA(a) < len) {
+ ary_expand_capa(mrb, a, len);
+ }
+ array_copy(ARY_PTR(a)+ARY_LEN(a), ARY_PTR(a2), ARY_LEN(a2));
+ mrb_write_barrier(mrb, (struct RBasic*)a);
+ ARY_SET_LEN(a, len);
+}
+
+MRB_API void
+mrb_ary_concat(mrb_state *mrb, mrb_value self, mrb_value other)
+{
+ struct RArray *a2 = mrb_ary_ptr(other);
+
+ ary_concat(mrb, mrb_ary_ptr(self), a2);
+}
+
+static mrb_value
+mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+
+ mrb_get_args(mrb, "A", &ary);
+ mrb_ary_concat(mrb, self, ary);
+ return self;
+}
+
+static mrb_value
+mrb_ary_plus(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a1 = mrb_ary_ptr(self);
+ struct RArray *a2;
+ mrb_value *ptr;
+ mrb_int blen, len1;
+
+ mrb_get_args(mrb, "a", &ptr, &blen);
+ if (ARY_MAX_SIZE - blen < ARY_LEN(a1)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
+ len1 = ARY_LEN(a1);
+ a2 = ary_new_capa(mrb, len1 + blen);
+ array_copy(ARY_PTR(a2), ARY_PTR(a1), len1);
+ array_copy(ARY_PTR(a2) + len1, ptr, blen);
+ ARY_SET_LEN(a2, len1+blen);
+
+ return mrb_obj_value(a2);
+}
+
+static void
+ary_replace(mrb_state *mrb, struct RArray *a, mrb_value *argv, mrb_int len)
+{
+ ary_modify(mrb, a);
+ if (ARY_CAPA(a) < len)
+ ary_expand_capa(mrb, a, len);
+ array_copy(ARY_PTR(a), argv, len);
+ mrb_write_barrier(mrb, (struct RBasic*)a);
+ ARY_SET_LEN(a, len);
+}
+
+MRB_API void
+mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other)
+{
+ struct RArray *a1 = mrb_ary_ptr(self);
+ struct RArray *a2 = mrb_ary_ptr(other);
+
+ if (a1 != a2) {
+ ary_replace(mrb, a1, ARY_PTR(a2), ARY_LEN(a2));
+ }
+}
+
+static mrb_value
+mrb_ary_replace_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+
+ mrb_get_args(mrb, "A", &other);
+ mrb_ary_replace(mrb, self, other);
+
+ return self;
+}
+
+static mrb_value
+mrb_ary_times(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a1 = mrb_ary_ptr(self);
+ struct RArray *a2;
+ mrb_value *ptr;
+ mrb_int times, len1;
+
+ mrb_get_args(mrb, "i", &times);
+ if (times < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
+ }
+ if (times == 0) return mrb_ary_new(mrb);
+ if (ARY_MAX_SIZE / times < ARY_LEN(a1)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
+ len1 = ARY_LEN(a1);
+ a2 = ary_new_capa(mrb, len1 * times);
+ ARY_SET_LEN(a2, len1 * times);
+ ptr = ARY_PTR(a2);
+ while (times--) {
+ array_copy(ptr, ARY_PTR(a1), len1);
+ ptr += len1;
+ }
+
+ return mrb_obj_value(a2);
+}
+
+static mrb_value
+mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int len = ARY_LEN(a);
+
+ if (len > 1) {
+ mrb_value *p1, *p2;
+
+ ary_modify(mrb, a);
+ p1 = ARY_PTR(a);
+ p2 = p1 + len - 1;
+
+ while (p1 < p2) {
+ mrb_value tmp = *p1;
+ *p1++ = *p2;
+ *p2-- = tmp;
+ }
+ }
+ return self;
+}
+
+static mrb_value
+mrb_ary_reverse(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self), *b = ary_new_capa(mrb, ARY_LEN(a));
+ mrb_int len = ARY_LEN(a);
+
+ if (len > 0) {
+ mrb_value *p1, *p2, *e;
+
+ p1 = ARY_PTR(a);
+ e = p1 + len;
+ p2 = ARY_PTR(b) + len - 1;
+ while (p1 < e) {
+ *p2-- = *p1++;
+ }
+ ARY_SET_LEN(b, len);
+ }
+ return mrb_obj_value(b);
+}
+
+MRB_API void
+mrb_ary_push(mrb_state *mrb, mrb_value ary, mrb_value elem)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ mrb_int len = ARY_LEN(a);
+
+ ary_modify(mrb, a);
+ if (len == ARY_CAPA(a))
+ ary_expand_capa(mrb, a, len + 1);
+ ARY_PTR(a)[len] = elem;
+ ARY_SET_LEN(a, len+1);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, elem);
+}
+
+static mrb_value
+mrb_ary_push_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ mrb_int len, len2, alen;
+ struct RArray *a;
+
+ mrb_get_args(mrb, "*!", &argv, &alen);
+ a = mrb_ary_ptr(self);
+ ary_modify(mrb, a);
+ len = ARY_LEN(a);
+ len2 = len + alen;
+ if (ARY_CAPA(a) < len2) {
+ ary_expand_capa(mrb, a, len2);
+ }
+ array_copy(ARY_PTR(a)+len, argv, alen);
+ ARY_SET_LEN(a, len2);
+ mrb_write_barrier(mrb, (struct RBasic*)a);
+
+ return self;
+}
+
+MRB_API mrb_value
+mrb_ary_pop(mrb_state *mrb, mrb_value ary)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ mrb_int len = ARY_LEN(a);
+
+ ary_modify_check(mrb, a);
+ if (len == 0) return mrb_nil_value();
+ ARY_SET_LEN(a, len-1);
+ return ARY_PTR(a)[len-1];
+}
+
+#define ARY_SHIFT_SHARED_MIN 10
+
+MRB_API mrb_value
+mrb_ary_shift(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int len = ARY_LEN(a);
+ mrb_value val;
+
+ ary_modify_check(mrb, a);
+ if (len == 0) return mrb_nil_value();
+ if (ARY_SHARED_P(a)) {
+ L_SHIFT:
+ val = a->as.heap.ptr[0];
+ a->as.heap.ptr++;
+ a->as.heap.len--;
+ return val;
+ }
+ if (len > ARY_SHIFT_SHARED_MIN) {
+ ary_make_shared(mrb, a);
+ goto L_SHIFT;
+ }
+ else {
+ mrb_value *ptr = ARY_PTR(a);
+ mrb_int size = len;
+
+ val = *ptr;
+ while (--size) {
+ *ptr = *(ptr+1);
+ ++ptr;
+ }
+ ARY_SET_LEN(a, len-1);
+ }
+ return val;
+}
+
+/* self = [1,2,3]
+ item = 0
+ self.unshift item
+ p self #=> [0, 1, 2, 3] */
+MRB_API mrb_value
+mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int len = ARY_LEN(a);
+
+ if (ARY_SHARED_P(a)
+ && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */
+ && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= 1) /* there's room for unshifted item */ {
+ a->as.heap.ptr--;
+ a->as.heap.ptr[0] = item;
+ }
+ else {
+ mrb_value *ptr;
+
+ ary_modify(mrb, a);
+ if (ARY_CAPA(a) < len + 1)
+ ary_expand_capa(mrb, a, len + 1);
+ ptr = ARY_PTR(a);
+ value_move(ptr + 1, ptr, len);
+ ptr[0] = item;
+ }
+ ARY_SET_LEN(a, len+1);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, item);
+
+ return self;
+}
+
+static mrb_value
+mrb_ary_unshift_m(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_value *vals, *ptr;
+ mrb_int alen, len;
+
+ mrb_get_args(mrb, "*!", &vals, &alen);
+ if (alen == 0) {
+ ary_modify_check(mrb, a);
+ return self;
+ }
+ len = ARY_LEN(a);
+ if (alen > ARY_MAX_SIZE - len) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ }
+ if (ARY_SHARED_P(a)
+ && a->as.heap.aux.shared->refcnt == 1 /* shared only referenced from this array */
+ && a->as.heap.ptr - a->as.heap.aux.shared->ptr >= alen) /* there's room for unshifted item */ {
+ ary_modify_check(mrb, a);
+ a->as.heap.ptr -= alen;
+ ptr = a->as.heap.ptr;
+ }
+ else {
+ ary_modify(mrb, a);
+ if (ARY_CAPA(a) < len + alen)
+ ary_expand_capa(mrb, a, len + alen);
+ ptr = ARY_PTR(a);
+ value_move(ptr + alen, ptr, len);
+ }
+ array_copy(ptr, vals, alen);
+ ARY_SET_LEN(a, len+alen);
+ while (alen--) {
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, vals[alen]);
+ }
+
+ return self;
+}
+
+MRB_API mrb_value
+mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ mrb_int len = ARY_LEN(a);
+
+ /* range check */
+ if (n < 0) n += len;
+ if (n < 0 || len <= n) return mrb_nil_value();
+
+ return ARY_PTR(a)[n];
+}
+
+MRB_API void
+mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ mrb_int len = ARY_LEN(a);
+
+ ary_modify(mrb, a);
+ /* range check */
+ if (n < 0) {
+ n += len;
+ if (n < 0) {
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S out of array", mrb_fixnum_value(n - len));
+ }
+ }
+ if (len <= n) {
+ if (ARY_CAPA(a) <= n)
+ ary_expand_capa(mrb, a, n + 1);
+ ary_fill_with_nil(ARY_PTR(a) + len, n + 1 - len);
+ ARY_SET_LEN(a, n+1);
+ }
+
+ ARY_PTR(a)[n] = val;
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)a, val);
+}
+
+static struct RArray*
+ary_dup(mrb_state *mrb, struct RArray *a)
+{
+ mrb_int len = ARY_LEN(a);
+ struct RArray *d = ary_new_capa(mrb, len);
+
+ ary_replace(mrb, d, ARY_PTR(a), len);
+ return d;
+}
+
+MRB_API mrb_value
+mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_value rpl)
+{
+ struct RArray *a = mrb_ary_ptr(ary);
+ mrb_int alen = ARY_LEN(a);
+ const mrb_value *argv;
+ mrb_int argc;
+ mrb_int tail;
+
+ ary_modify(mrb, a);
+
+ /* len check */
+ if (len < 0) mrb_raisef(mrb, E_INDEX_ERROR, "negative length (%S)", mrb_fixnum_value(len));
+
+ /* range check */
+ if (head < 0) {
+ head += alen;
+ if (head < 0) {
+ mrb_raise(mrb, E_INDEX_ERROR, "index is out of array");
+ }
+ }
+ tail = head + len;
+ if (alen < len || alen < tail) {
+ len = alen - head;
+ }
+
+ /* size check */
+ if (mrb_array_p(rpl)) {
+ argc = RARRAY_LEN(rpl);
+ argv = RARRAY_PTR(rpl);
+ if (argv == ARY_PTR(a)) {
+ struct RArray *r;
+
+ if (argc > 32767) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "too big recursive splice");
+ }
+ r = ary_dup(mrb, a);
+ argv = ARY_PTR(r);
+ }
+ }
+ else {
+ argc = 1;
+ argv = &rpl;
+ }
+ if (head >= alen) {
+ if (head > ARY_MAX_SIZE - argc) {
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(head));
+ }
+ len = head + argc;
+ if (len > ARY_CAPA(a)) {
+ ary_expand_capa(mrb, a, head + argc);
+ }
+ ary_fill_with_nil(ARY_PTR(a) + alen, head - alen);
+ if (argc > 0) {
+ array_copy(ARY_PTR(a) + head, argv, argc);
+ }
+ ARY_SET_LEN(a, len);
+ }
+ else {
+ mrb_int newlen;
+
+ if (alen - len > ARY_MAX_SIZE - argc) {
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %S too big", mrb_fixnum_value(alen + argc - len));
+ }
+ newlen = alen + argc - len;
+ if (newlen > ARY_CAPA(a)) {
+ ary_expand_capa(mrb, a, newlen);
+ }
+
+ if (len != argc) {
+ mrb_value *ptr = ARY_PTR(a);
+ tail = head + len;
+ value_move(ptr + head + argc, ptr + tail, alen - tail);
+ ARY_SET_LEN(a, newlen);
+ }
+ if (argc > 0) {
+ value_move(ARY_PTR(a) + head, argv, argc);
+ }
+ }
+ mrb_write_barrier(mrb, (struct RBasic*)a);
+ return ary;
+}
+
+void
+mrb_ary_decref(mrb_state *mrb, mrb_shared_array *shared)
+{
+ shared->refcnt--;
+ if (shared->refcnt == 0) {
+ mrb_free(mrb, shared->ptr);
+ mrb_free(mrb, shared);
+ }
+}
+
+static mrb_value
+ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
+{
+ struct RArray *b;
+
+ if (!ARY_SHARED_P(a) && len <= ARY_SHIFT_SHARED_MIN) {
+ return mrb_ary_new_from_values(mrb, len, ARY_PTR(a)+beg);
+ }
+ ary_make_shared(mrb, a);
+ b = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
+ b->as.heap.ptr = a->as.heap.ptr + beg;
+ b->as.heap.len = len;
+ b->as.heap.aux.shared = a->as.heap.aux.shared;
+ b->as.heap.aux.shared->refcnt++;
+ ARY_SET_SHARED_FLAG(b);
+
+ return mrb_obj_value(b);
+}
+
+static mrb_int
+aget_index(mrb_state *mrb, mrb_value index)
+{
+ if (mrb_fixnum_p(index)) {
+ return mrb_fixnum(index);
+ }
+ else if (mrb_float_p(index)) {
+ return (mrb_int)mrb_float(index);
+ }
+ else {
+ mrb_int i, argc;
+ mrb_value *argv;
+
+ mrb_get_args(mrb, "i*!", &i, &argv, &argc);
+ return i;
+ }
+}
+
+/*
+ * call-seq:
+ * ary[index] -> obj or nil
+ * ary[start, length] -> new_ary or nil
+ * ary[range] -> new_ary or nil
+ * ary.slice(index) -> obj or nil
+ * ary.slice(start, length) -> new_ary or nil
+ * ary.slice(range) -> new_ary or nil
+ *
+ * Element Reference --- Returns the element at +index+, or returns a
+ * subarray starting at the +start+ index and continuing for +length+
+ * elements, or returns a subarray specified by +range+ of indices.
+ *
+ * Negative indices count backward from the end of the array (-1 is the last
+ * element). For +start+ and +range+ cases the starting index is just before
+ * an element. Additionally, an empty array is returned when the starting
+ * index for an element range is at the end of the array.
+ *
+ * Returns +nil+ if the index (or starting index) are out of range.
+ *
+ * a = [ "a", "b", "c", "d", "e" ]
+ * a[1] => "b"
+ * a[1,2] => ["b", "c"]
+ * a[1..-2] => ["b", "c", "d"]
+ *
+ */
+
+static mrb_value
+mrb_ary_aget(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int i, len, alen = ARY_LEN(a);
+ mrb_value index;
+
+ if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
+ switch (mrb_type(index)) {
+ /* a[n..m] */
+ case MRB_TT_RANGE:
+ if (mrb_range_beg_len(mrb, index, &i, &len, alen, TRUE) == 1) {
+ return ary_subseq(mrb, a, i, len);
+ }
+ else {
+ return mrb_nil_value();
+ }
+ case MRB_TT_FIXNUM:
+ return mrb_ary_ref(mrb, self, mrb_fixnum(index));
+ default:
+ return mrb_ary_ref(mrb, self, aget_index(mrb, index));
+ }
+ }
+
+ i = aget_index(mrb, index);
+ if (i < 0) i += alen;
+ if (i < 0 || alen < i) return mrb_nil_value();
+ if (len < 0) return mrb_nil_value();
+ if (alen == i) return mrb_ary_new(mrb);
+ if (len > alen - i) len = alen - i;
+
+ return ary_subseq(mrb, a, i, len);
+}
+
+/*
+ * call-seq:
+ * ary[index] = obj -> obj
+ * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil
+ * ary[range] = obj or other_ary or nil -> obj or other_ary or nil
+ *
+ * Element Assignment --- Sets the element at +index+, or replaces a subarray
+ * from the +start+ index for +length+ elements, or replaces a subarray
+ * specified by the +range+ of indices.
+ *
+ * If indices are greater than the current capacity of the array, the array
+ * grows automatically. Elements are inserted into the array at +start+ if
+ * +length+ is zero.
+ *
+ * Negative indices will count backward from the end of the array. For
+ * +start+ and +range+ cases the starting index is just before an element.
+ *
+ * An IndexError is raised if a negative index points past the beginning of
+ * the array.
+ *
+ * See also Array#push, and Array#unshift.
+ *
+ * a = Array.new
+ * a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
+ * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
+ * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
+ * a[0, 2] = "?" #=> ["?", 2, nil, "4"]
+ * a[0..2] = "A" #=> ["A", "4"]
+ * a[-1] = "Z" #=> ["A", "Z"]
+ * a[1..-1] = nil #=> ["A", nil]
+ * a[1..-1] = [] #=> ["A"]
+ * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"]
+ * a[3, 0] = "B" #=> [1, 2, "A", "B"]
+ */
+
+static mrb_value
+mrb_ary_aset(mrb_state *mrb, mrb_value self)
+{
+ mrb_value v1, v2, v3;
+ mrb_int i, len;
+
+ mrb_ary_modify(mrb, mrb_ary_ptr(self));
+ if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) {
+ /* a[n..m] = v */
+ switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) {
+ case 0: /* not range */
+ mrb_ary_set(mrb, self, aget_index(mrb, v1), v2);
+ break;
+ case 1: /* range */
+ mrb_ary_splice(mrb, self, i, len, v2);
+ break;
+ case 2: /* out of range */
+ mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", v1);
+ break;
+ }
+ return v2;
+ }
+
+ /* a[n,m] = v */
+ mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3);
+ return v3;
+}
+
+static mrb_value
+mrb_ary_delete_at(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int index;
+ mrb_value val;
+ mrb_value *ptr;
+ mrb_int len, alen = ARY_LEN(a);
+
+ mrb_get_args(mrb, "i", &index);
+ if (index < 0) index += alen;
+ if (index < 0 || alen <= index) return mrb_nil_value();
+
+ ary_modify(mrb, a);
+ ptr = ARY_PTR(a);
+ val = ptr[index];
+
+ ptr += index;
+ len = alen - index;
+ while (--len) {
+ *ptr = *(ptr+1);
+ ++ptr;
+ }
+ ARY_SET_LEN(a, alen-1);
+
+ ary_shrink_capa(mrb, a);
+
+ return val;
+}
+
+static mrb_value
+mrb_ary_first(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int size, alen = ARY_LEN(a);
+
+ if (mrb->c->ci->argc == 0) {
+ return (alen > 0)? ARY_PTR(a)[0]: mrb_nil_value();
+ }
+ mrb_get_args(mrb, "|i", &size);
+ if (size < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
+ }
+
+ if (size > alen) size = alen;
+ if (ARY_SHARED_P(a)) {
+ return ary_subseq(mrb, a, 0, size);
+ }
+ return mrb_ary_new_from_values(mrb, size, ARY_PTR(a));
+}
+
+static mrb_value
+mrb_ary_last(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+ mrb_int size, alen = ARY_LEN(a);
+
+ if (mrb_get_args(mrb, "|i", &size) == 0)
+ return (alen > 0)? ARY_PTR(a)[alen - 1]: mrb_nil_value();
+
+ if (size < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size");
+ }
+ if (size > alen) size = alen;
+ if (ARY_SHARED_P(a) || size > ARY_DEFAULT_LEN) {
+ return ary_subseq(mrb, a, alen - size, size);
+ }
+ return mrb_ary_new_from_values(mrb, size, ARY_PTR(a) + alen - size);
+}
+
+static mrb_value
+mrb_ary_index_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value obj;
+ mrb_int i;
+
+ mrb_get_args(mrb, "o", &obj);
+ for (i = 0; i < RARRAY_LEN(self); i++) {
+ if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
+ return mrb_fixnum_value(i);
+ }
+ }
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value obj;
+ mrb_int i, len;
+
+ mrb_get_args(mrb, "o", &obj);
+ for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
+ if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
+ return mrb_fixnum_value(i);
+ }
+ if (i > (len = RARRAY_LEN(self))) {
+ i = len;
+ }
+ }
+ return mrb_nil_value();
+}
+
+MRB_API mrb_value
+mrb_ary_splat(mrb_state *mrb, mrb_value v)
+{
+ mrb_value a, recv_class;
+
+ if (mrb_array_p(v)) {
+ return v;
+ }
+
+ if (!mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) {
+ return mrb_ary_new_from_values(mrb, 1, &v);
+ }
+
+ a = mrb_funcall(mrb, v, "to_a", 0);
+ if (mrb_array_p(a)) {
+ return a;
+ }
+ else if (mrb_nil_p(a)) {
+ return mrb_ary_new_from_values(mrb, 1, &v);
+ }
+ else {
+ recv_class = mrb_obj_value(mrb_obj_class(mrb, v));
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Array (%S#to_a gives %S)",
+ recv_class,
+ recv_class,
+ mrb_obj_value(mrb_obj_class(mrb, a))
+ );
+ /* not reached */
+ return mrb_undef_value();
+ }
+}
+
+static mrb_value
+mrb_ary_size(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+
+ return mrb_fixnum_value(ARY_LEN(a));
+}
+
+MRB_API mrb_value
+mrb_ary_clear(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+
+ ary_modify(mrb, a);
+ if (ARY_SHARED_P(a)) {
+ mrb_ary_decref(mrb, a->as.heap.aux.shared);
+ ARY_UNSET_SHARED_FLAG(a);
+ }
+ else if (!ARY_EMBED_P(a)){
+ mrb_free(mrb, a->as.heap.ptr);
+ }
+ ARY_SET_EMBED_LEN(a, 0);
+
+ return self;
+}
+
+static mrb_value
+mrb_ary_empty_p(mrb_state *mrb, mrb_value self)
+{
+ struct RArray *a = mrb_ary_ptr(self);
+
+ return mrb_bool_value(ARY_LEN(a) == 0);
+}
+
+MRB_API mrb_value
+mrb_check_array_type(mrb_state *mrb, mrb_value ary)
+{
+ return mrb_check_convert_type(mrb, ary, MRB_TT_ARRAY, "Array", "to_ary");
+}
+
+MRB_API mrb_value
+mrb_ary_entry(mrb_value ary, mrb_int offset)
+{
+ if (offset < 0) {
+ offset += RARRAY_LEN(ary);
+ }
+ if (offset < 0 || RARRAY_LEN(ary) <= offset) {
+ return mrb_nil_value();
+ }
+ return RARRAY_PTR(ary)[offset];
+}
+
+static mrb_value
+join_ary(mrb_state *mrb, mrb_value ary, mrb_value sep, mrb_value list)
+{
+ mrb_int i;
+ mrb_value result, val, tmp;
+
+ /* check recursive */
+ for (i=0; i<RARRAY_LEN(list); i++) {
+ if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "recursive array join");
+ }
+ }
+
+ mrb_ary_push(mrb, list, ary);
+
+ result = mrb_str_new_capa(mrb, 64);
+
+ for (i=0; i<RARRAY_LEN(ary); i++) {
+ if (i > 0 && !mrb_nil_p(sep)) {
+ mrb_str_cat_str(mrb, result, sep);
+ }
+
+ val = RARRAY_PTR(ary)[i];
+ switch (mrb_type(val)) {
+ case MRB_TT_ARRAY:
+ ary_join:
+ val = join_ary(mrb, val, sep, list);
+ /* fall through */
+
+ case MRB_TT_STRING:
+ str_join:
+ mrb_str_cat_str(mrb, result, val);
+ break;
+
+ default:
+ if (!mrb_immediate_p(val)) {
+ tmp = mrb_check_string_type(mrb, val);
+ if (!mrb_nil_p(tmp)) {
+ val = tmp;
+ goto str_join;
+ }
+ tmp = mrb_check_convert_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
+ if (!mrb_nil_p(tmp)) {
+ val = tmp;
+ goto ary_join;
+ }
+ }
+ val = mrb_obj_as_string(mrb, val);
+ goto str_join;
+ }
+ }
+
+ mrb_ary_pop(mrb, list);
+
+ return result;
+}
+
+MRB_API mrb_value
+mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep)
+{
+ if (!mrb_nil_p(sep)) {
+ sep = mrb_obj_as_string(mrb, sep);
+ }
+ return join_ary(mrb, ary, sep, mrb_ary_new(mrb));
+}
+
+/*
+ * call-seq:
+ * ary.join(sep="") -> str
+ *
+ * Returns a string created by converting each element of the array to
+ * a string, separated by <i>sep</i>.
+ *
+ * [ "a", "b", "c" ].join #=> "abc"
+ * [ "a", "b", "c" ].join("-") #=> "a-b-c"
+ */
+
+static mrb_value
+mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
+{
+ mrb_value sep = mrb_nil_value();
+
+ mrb_get_args(mrb, "|S!", &sep);
+ return mrb_ary_join(mrb, ary, sep);
+}
+
+static mrb_value
+mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
+{
+ mrb_value ary2;
+
+ mrb_get_args(mrb, "o", &ary2);
+ if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
+ if (!mrb_array_p(ary2)) {
+ return mrb_false_value();
+ }
+ if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value();
+
+ return ary2;
+}
+
+static mrb_value
+mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
+{
+ mrb_value ary2;
+
+ mrb_get_args(mrb, "o", &ary2);
+ if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0);
+ if (!mrb_array_p(ary2)) {
+ return mrb_nil_value();
+ }
+
+ return ary2;
+}
+
+void
+mrb_init_array(mrb_state *mrb)
+{
+ struct RClass *a;
+
+ mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */
+ MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY);
+
+ mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */
+
+ mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1)); /* 15.2.12.5.1 */
+ mrb_define_method(mrb, a, "*", mrb_ary_times, MRB_ARGS_REQ(1)); /* 15.2.12.5.2 */
+ mrb_define_method(mrb, a, "<<", mrb_ary_push_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.3 */
+ mrb_define_method(mrb, a, "[]", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.4 */
+ mrb_define_method(mrb, a, "[]=", mrb_ary_aset, MRB_ARGS_ANY()); /* 15.2.12.5.5 */
+ mrb_define_method(mrb, a, "clear", mrb_ary_clear, MRB_ARGS_NONE()); /* 15.2.12.5.6 */
+ mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.8 */
+ mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, MRB_ARGS_REQ(1)); /* 15.2.12.5.9 */
+ mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, MRB_ARGS_NONE()); /* 15.2.12.5.12 */
+ mrb_define_method(mrb, a, "first", mrb_ary_first, MRB_ARGS_OPT(1)); /* 15.2.12.5.13 */
+ mrb_define_method(mrb, a, "index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.14 */
+ mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.16 */
+ mrb_define_method(mrb, a, "join", mrb_ary_join_m, MRB_ARGS_ANY()); /* 15.2.12.5.17 */
+ mrb_define_method(mrb, a, "last", mrb_ary_last, MRB_ARGS_ANY()); /* 15.2.12.5.18 */
+ mrb_define_method(mrb, a, "length", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.19 */
+ mrb_define_method(mrb, a, "pop", mrb_ary_pop, MRB_ARGS_NONE()); /* 15.2.12.5.21 */
+ mrb_define_method(mrb, a, "push", mrb_ary_push_m, MRB_ARGS_ANY()); /* 15.2.12.5.22 */
+ mrb_define_method(mrb, a, "append", mrb_ary_push_m, MRB_ARGS_ANY());
+ mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */
+ mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, MRB_ARGS_NONE()); /* 15.2.12.5.24 */
+ mrb_define_method(mrb, a, "reverse!", mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */
+ mrb_define_method(mrb, a, "rindex", mrb_ary_rindex_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.26 */
+ mrb_define_method(mrb, a, "shift", mrb_ary_shift, MRB_ARGS_NONE()); /* 15.2.12.5.27 */
+ mrb_define_method(mrb, a, "size", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.28 */
+ mrb_define_method(mrb, a, "slice", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.29 */
+ mrb_define_method(mrb, a, "unshift", mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */
+ mrb_define_method(mrb, a, "prepend", mrb_ary_unshift_m, MRB_ARGS_ANY());
+
+ mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/backtrace.c b/web/server/h2o/libh2o/deps/mruby/src/backtrace.c
new file mode 100644
index 00000000..3e4e1a43
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/backtrace.c
@@ -0,0 +1,281 @@
+/*
+** backtrace.c -
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/variable.h>
+#include <mruby/proc.h>
+#include <mruby/array.h>
+#include <mruby/string.h>
+#include <mruby/class.h>
+#include <mruby/debug.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/data.h>
+
+struct backtrace_location {
+ int lineno;
+ const char *filename;
+ mrb_sym method_id;
+};
+
+typedef void (*each_backtrace_func)(mrb_state*, struct backtrace_location*, void*);
+
+static const mrb_data_type bt_type = { "Backtrace", mrb_free };
+
+static void
+each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, mrb_code *pc0, each_backtrace_func func, void *data)
+{
+ ptrdiff_t i, j;
+
+ if (ciidx >= mrb->c->ciend - mrb->c->cibase)
+ ciidx = 10; /* ciidx is broken... */
+
+ for (i=ciidx, j=0; i >= 0; i--,j++) {
+ struct backtrace_location loc;
+ mrb_callinfo *ci;
+ mrb_irep *irep;
+ mrb_code *pc;
+
+ ci = &mrb->c->cibase[i];
+
+ if (!ci->proc) continue;
+ if (MRB_PROC_CFUNC_P(ci->proc)) continue;
+
+ irep = ci->proc->body.irep;
+ if (!irep) continue;
+
+ if (mrb->c->cibase[i].err) {
+ pc = mrb->c->cibase[i].err;
+ }
+ else if (i+1 <= ciidx) {
+ pc = mrb->c->cibase[i+1].pc - 1;
+ }
+ else {
+ pc = pc0;
+ }
+ loc.filename = mrb_debug_get_filename(irep, pc - irep->iseq);
+ loc.lineno = mrb_debug_get_line(irep, pc - irep->iseq);
+
+ if (loc.lineno == -1) continue;
+
+ if (!loc.filename) {
+ loc.filename = "(unknown)";
+ }
+
+ loc.method_id = ci->mid;
+ func(mrb, &loc, data);
+ }
+}
+
+#ifndef MRB_DISABLE_STDIO
+
+static void
+print_backtrace(mrb_state *mrb, mrb_value backtrace)
+{
+ int i, n;
+ FILE *stream = stderr;
+
+ if (!mrb_array_p(backtrace)) return;
+
+ n = RARRAY_LEN(backtrace) - 1;
+ if (n == 0) return;
+
+ fprintf(stream, "trace:\n");
+ for (i=0; i<n; i++) {
+ mrb_value entry = RARRAY_PTR(backtrace)[n-i-1];
+
+ if (mrb_string_p(entry)) {
+ fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry));
+ }
+ }
+}
+
+static int
+packed_bt_len(struct backtrace_location *bt, int n)
+{
+ int len = 0;
+ int i;
+
+ for (i=0; i<n; i++) {
+ if (!bt[i].filename && !bt[i].lineno && !bt[i].method_id)
+ continue;
+ len++;
+ }
+ return len;
+}
+
+static void
+print_packed_backtrace(mrb_state *mrb, mrb_value packed)
+{
+ FILE *stream = stderr;
+ struct backtrace_location *bt;
+ int n, i;
+ int ai = mrb_gc_arena_save(mrb);
+
+ bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, packed, &bt_type);
+ if (bt == NULL) return;
+ n = (mrb_int)RDATA(packed)->flags;
+
+ if (packed_bt_len(bt, n) == 0) return;
+ fprintf(stream, "trace:\n");
+ for (i = 0; i<n; i++) {
+ struct backtrace_location *entry = &bt[n-i-1];
+ if (entry->filename == NULL) continue;
+ fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno);
+ if (entry->method_id != 0) {
+ const char *method_name;
+
+ method_name = mrb_sym2name(mrb, entry->method_id);
+ fprintf(stream, ":in %s", method_name);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ fprintf(stream, "\n");
+ }
+}
+
+/* mrb_print_backtrace
+
+ function to retrieve backtrace information from the last exception.
+*/
+
+MRB_API void
+mrb_print_backtrace(mrb_state *mrb)
+{
+ mrb_value backtrace;
+
+ if (!mrb->exc) {
+ return;
+ }
+
+ backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace"));
+ if (mrb_nil_p(backtrace)) return;
+ if (mrb_array_p(backtrace)) {
+ print_backtrace(mrb, backtrace);
+ }
+ else {
+ print_packed_backtrace(mrb, backtrace);
+ }
+}
+#else
+
+MRB_API void
+mrb_print_backtrace(mrb_state *mrb)
+{
+}
+
+#endif
+
+static void
+count_backtrace_i(mrb_state *mrb,
+ struct backtrace_location *loc,
+ void *data)
+{
+ int *lenp = (int*)data;
+
+ if (loc->filename == NULL) return;
+ (*lenp)++;
+}
+
+static void
+pack_backtrace_i(mrb_state *mrb,
+ struct backtrace_location *loc,
+ void *data)
+{
+ struct backtrace_location **pptr = (struct backtrace_location**)data;
+ struct backtrace_location *ptr = *pptr;
+
+ if (loc->filename == NULL) return;
+ *ptr = *loc;
+ *pptr = ptr+1;
+}
+
+static mrb_value
+packed_backtrace(mrb_state *mrb)
+{
+ struct RData *backtrace;
+ ptrdiff_t ciidx = mrb->c->ci - mrb->c->cibase;
+ int len = 0;
+ int size;
+ void *ptr;
+
+ each_backtrace(mrb, ciidx, mrb->c->ci->pc, count_backtrace_i, &len);
+ size = len * sizeof(struct backtrace_location);
+ ptr = mrb_malloc(mrb, size);
+ if (ptr) memset(ptr, 0, size);
+ backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
+ backtrace->flags = (unsigned int)len;
+ each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, &ptr);
+ return mrb_obj_value(backtrace);
+}
+
+void
+mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
+{
+ mrb_value backtrace;
+ int ai = mrb_gc_arena_save(mrb);
+
+ backtrace = packed_backtrace(mrb);
+ mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace);
+ mrb_gc_arena_restore(mrb, ai);
+}
+
+mrb_value
+mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
+{
+ struct backtrace_location *bt;
+ mrb_int n, i;
+ int ai;
+
+ if (mrb_nil_p(backtrace)) {
+ empty_backtrace:
+ return mrb_ary_new_capa(mrb, 0);
+ }
+ if (mrb_array_p(backtrace)) return backtrace;
+ bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, backtrace, &bt_type);
+ if (bt == NULL) goto empty_backtrace;
+ n = (mrb_int)RDATA(backtrace)->flags;
+ backtrace = mrb_ary_new_capa(mrb, n);
+ ai = mrb_gc_arena_save(mrb);
+ for (i = 0; i < n; i++) {
+ struct backtrace_location *entry = &bt[i];
+ mrb_value btline;
+
+ if (entry->filename == NULL) continue;
+ btline = mrb_format(mrb, "%S:%S",
+ mrb_str_new_cstr(mrb, entry->filename),
+ mrb_fixnum_value(entry->lineno));
+ if (entry->method_id != 0) {
+ mrb_str_cat_lit(mrb, btline, ":in ");
+ mrb_str_cat_cstr(mrb, btline, mrb_sym2name(mrb, entry->method_id));
+ }
+ mrb_ary_push(mrb, backtrace, btline);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ return backtrace;
+}
+
+MRB_API mrb_value
+mrb_exc_backtrace(mrb_state *mrb, mrb_value exc)
+{
+ mrb_sym attr_name;
+ mrb_value backtrace;
+
+ attr_name = mrb_intern_lit(mrb, "backtrace");
+ backtrace = mrb_iv_get(mrb, exc, attr_name);
+ if (mrb_nil_p(backtrace) || mrb_array_p(backtrace)) {
+ return backtrace;
+ }
+ backtrace = mrb_unpack_backtrace(mrb, backtrace);
+ mrb_iv_set(mrb, exc, attr_name, backtrace);
+ return backtrace;
+}
+
+MRB_API mrb_value
+mrb_get_backtrace(mrb_state *mrb)
+{
+ return mrb_unpack_backtrace(mrb, packed_backtrace(mrb));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/class.c b/web/server/h2o/libh2o/deps/mruby/src/class.c
new file mode 100644
index 00000000..e3888001
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/class.c
@@ -0,0 +1,2474 @@
+/*
+** class.c - Class class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <stdarg.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/numeric.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
+#include <mruby/data.h>
+#include <mruby/istruct.h>
+
+KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
+
+void
+mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
+{
+ khiter_t k;
+ khash_t(mt) *h = c->mt;
+
+ if (!h) return;
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ struct RProc *m = kh_value(h, k);
+ if (m) {
+ mrb_gc_mark(mrb, (struct RBasic*)m);
+ }
+ }
+ }
+}
+
+size_t
+mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c)
+{
+ khash_t(mt) *h = c->mt;
+
+ if (!h) return 0;
+ return kh_size(h);
+}
+
+void
+mrb_gc_free_mt(mrb_state *mrb, struct RClass *c)
+{
+ kh_destroy(mt, mrb, c->mt);
+}
+
+void
+mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
+{
+ mrb_value name;
+ mrb_sym nsym = mrb_intern_lit(mrb, "__classname__");
+
+ if (mrb_obj_iv_defined(mrb, (struct RObject*)c, nsym)) return;
+ if (outer == NULL || outer == mrb->object_class) {
+ name = mrb_symbol_value(id);
+ }
+ else {
+ name = mrb_class_path(mrb, outer);
+ if (mrb_nil_p(name)) { /* unnamed outer class */
+ if (outer != mrb->object_class) {
+ mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
+ mrb_obj_value(outer));
+ }
+ return;
+ }
+ mrb_str_cat_cstr(mrb, name, "::");
+ mrb_str_cat_cstr(mrb, name, mrb_sym2name(mrb, id));
+ }
+ mrb_obj_iv_set(mrb, (struct RObject*)c, nsym, name);
+}
+
+static void
+setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
+{
+ mrb_class_name_class(mrb, outer, c, id);
+ mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c));
+}
+
+#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
+
+static void
+prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
+{
+ struct RClass *sc, *c;
+
+ if (o->c->tt == MRB_TT_SCLASS) return;
+ sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
+ sc->flags |= MRB_FLAG_IS_INHERITED;
+ sc->mt = kh_init(mt, mrb);
+ sc->iv = 0;
+ if (o->tt == MRB_TT_CLASS) {
+ c = (struct RClass*)o;
+ if (!c->super) {
+ sc->super = mrb->class_class;
+ }
+ else {
+ sc->super = c->super->c;
+ }
+ }
+ else if (o->tt == MRB_TT_SCLASS) {
+ c = (struct RClass*)o;
+ while (c->super->tt == MRB_TT_ICLASS)
+ c = c->super;
+ make_metaclass(mrb, c->super);
+ sc->super = c->super->c;
+ }
+ else {
+ sc->super = o->c;
+ prepare_singleton_class(mrb, (struct RBasic*)sc);
+ }
+ o->c = sc;
+ mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
+ mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
+ mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
+}
+
+static struct RClass*
+class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
+{
+ mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
+
+ mrb_check_type(mrb, c, MRB_TT_CLASS);
+ return mrb_class_ptr(c);
+}
+
+static struct RClass*
+module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
+{
+ mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
+
+ mrb_check_type(mrb, c, MRB_TT_MODULE);
+ return mrb_class_ptr(c);
+}
+
+static mrb_bool
+class_ptr_p(mrb_value obj)
+{
+ switch (mrb_type(obj)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_MODULE:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static void
+check_if_class_or_module(mrb_state *mrb, mrb_value obj)
+{
+ if (!class_ptr_p(obj)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj));
+ }
+}
+
+static struct RClass*
+define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
+{
+ struct RClass *m;
+
+ if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
+ return module_from_sym(mrb, outer, name);
+ }
+ m = mrb_module_new(mrb);
+ setup_class(mrb, outer, m, name);
+
+ return m;
+}
+
+MRB_API struct RClass*
+mrb_define_module_id(mrb_state *mrb, mrb_sym name)
+{
+ return define_module(mrb, name, mrb->object_class);
+}
+
+MRB_API struct RClass*
+mrb_define_module(mrb_state *mrb, const char *name)
+{
+ return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
+}
+
+MRB_API struct RClass*
+mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
+{
+ check_if_class_or_module(mrb, outer);
+ if (mrb_const_defined_at(mrb, outer, id)) {
+ mrb_value old = mrb_const_get(mrb, outer, id);
+
+ if (mrb_type(old) != MRB_TT_MODULE) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a module", mrb_inspect(mrb, old));
+ }
+ return mrb_class_ptr(old);
+ }
+ return define_module(mrb, id, mrb_class_ptr(outer));
+}
+
+MRB_API struct RClass*
+mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
+{
+ mrb_sym id = mrb_intern_cstr(mrb, name);
+ struct RClass * c = define_module(mrb, id, outer);
+
+ setup_class(mrb, outer, c, id);
+ return c;
+}
+
+static struct RClass*
+find_origin(struct RClass *c)
+{
+ MRB_CLASS_ORIGIN(c);
+ return c;
+}
+
+static struct RClass*
+define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
+{
+ struct RClass * c;
+
+ if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
+ c = class_from_sym(mrb, outer, name);
+ MRB_CLASS_ORIGIN(c);
+ if (super && mrb_class_real(c->super) != super) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
+ mrb_sym2str(mrb, name),
+ mrb_obj_value(c->super), mrb_obj_value(super));
+ }
+ return c;
+ }
+
+ c = mrb_class_new(mrb, super);
+ setup_class(mrb, outer, c, name);
+
+ return c;
+}
+
+MRB_API struct RClass*
+mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
+{
+ if (!super) {
+ mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name));
+ }
+ return define_class(mrb, name, super, mrb->object_class);
+}
+
+MRB_API struct RClass*
+mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
+{
+ return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super);
+}
+
+static mrb_value mrb_bob_init(mrb_state *mrb, mrb_value);
+#ifdef MRB_METHOD_CACHE
+static void mc_clear_all(mrb_state *mrb);
+static void mc_clear_by_class(mrb_state *mrb, struct RClass*);
+static void mc_clear_by_id(mrb_state *mrb, struct RClass*, mrb_sym);
+#else
+#define mc_clear_all(mrb)
+#define mc_clear_by_class(mrb,c)
+#define mc_clear_by_id(mrb,c,s)
+#endif
+
+static void
+mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
+{
+ mrb_value s;
+ mrb_sym mid;
+
+ if (!super)
+ super = mrb->object_class;
+ super->flags |= MRB_FLAG_IS_INHERITED;
+ s = mrb_obj_value(super);
+ mc_clear_by_class(mrb, klass);
+ mid = mrb_intern_lit(mrb, "inherited");
+ if (!mrb_func_basic_p(mrb, s, mid, mrb_bob_init)) {
+ mrb_value c = mrb_obj_value(klass);
+ mrb_funcall_argv(mrb, s, mid, 1, &c);
+ }
+}
+
+MRB_API struct RClass*
+mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
+{
+ struct RClass *s;
+ struct RClass *c;
+
+ if (!mrb_nil_p(super)) {
+ if (mrb_type(super) != MRB_TT_CLASS) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)",
+ mrb_inspect(mrb, super));
+ }
+ s = mrb_class_ptr(super);
+ }
+ else {
+ s = 0;
+ }
+ check_if_class_or_module(mrb, outer);
+ if (mrb_const_defined_at(mrb, outer, id)) {
+ mrb_value old = mrb_const_get(mrb, outer, id);
+
+ if (mrb_type(old) != MRB_TT_CLASS) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class", mrb_inspect(mrb, old));
+ }
+ c = mrb_class_ptr(old);
+ if (s) {
+ /* check super class */
+ if (mrb_class_real(c->super) != s) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", old);
+ }
+ }
+ return c;
+ }
+ c = define_class(mrb, id, s, mrb_class_ptr(outer));
+ mrb_class_inherited(mrb, mrb_class_real(c->super), c);
+
+ return c;
+}
+
+MRB_API mrb_bool
+mrb_class_defined(mrb_state *mrb, const char *name)
+{
+ mrb_value sym = mrb_check_intern_cstr(mrb, name);
+ if (mrb_nil_p(sym)) {
+ return FALSE;
+ }
+ return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym));
+}
+
+MRB_API mrb_bool
+mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name)
+{
+ mrb_value sym = mrb_check_intern_cstr(mrb, name);
+ if (mrb_nil_p(sym)) {
+ return FALSE;
+ }
+ return mrb_const_defined_at(mrb, mrb_obj_value(outer), mrb_symbol(sym));
+}
+
+MRB_API struct RClass*
+mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
+{
+ return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
+}
+
+MRB_API struct RClass*
+mrb_class_get(mrb_state *mrb, const char *name)
+{
+ return mrb_class_get_under(mrb, mrb->object_class, name);
+}
+
+MRB_API struct RClass*
+mrb_exc_get(mrb_state *mrb, const char *name)
+{
+ struct RClass *exc, *e;
+ mrb_value c = mrb_const_get(mrb, mrb_obj_value(mrb->object_class),
+ mrb_intern_cstr(mrb, name));
+
+ if (mrb_type(c) != MRB_TT_CLASS) {
+ mrb_raise(mrb, mrb->eException_class, "exception corrupted");
+ }
+ exc = e = mrb_class_ptr(c);
+
+ while (e) {
+ if (e == mrb->eException_class)
+ return exc;
+ e = e->super;
+ }
+ return mrb->eException_class;
+}
+
+MRB_API struct RClass*
+mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
+{
+ return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
+}
+
+MRB_API struct RClass*
+mrb_module_get(mrb_state *mrb, const char *name)
+{
+ return mrb_module_get_under(mrb, mrb->object_class, name);
+}
+
+/*!
+ * Defines a class under the namespace of \a outer.
+ * \param outer a class which contains the new class.
+ * \param id name of the new class
+ * \param super a class from which the new class will derive.
+ * NULL means \c Object class.
+ * \return the created class
+ * \throw TypeError if the constant name \a name is already taken but
+ * the constant is not a \c Class.
+ * \throw NameError if the class is already defined but the class can not
+ * be reopened because its superclass is not \a super.
+ * \post top-level constant named \a name refers the returned class.
+ *
+ * \note if a class named \a name is already defined and its superclass is
+ * \a super, the function just returns the defined class.
+ */
+MRB_API struct RClass*
+mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
+{
+ mrb_sym id = mrb_intern_cstr(mrb, name);
+ struct RClass * c;
+
+#if 0
+ if (!super) {
+ mrb_warn(mrb, "no super class for '%S::%S', Object assumed",
+ mrb_obj_value(outer), mrb_sym2str(mrb, id));
+ }
+#endif
+ c = define_class(mrb, id, super, outer);
+ setup_class(mrb, outer, c, id);
+ return c;
+}
+
+MRB_API void
+mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
+{
+ khash_t(mt) *h;
+ khiter_t k;
+ MRB_CLASS_ORIGIN(c);
+ h = c->mt;
+
+ if (MRB_FROZEN_P(c)) {
+ if (c->tt == MRB_TT_MODULE)
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen module");
+ else
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen class");
+ }
+ if (!h) h = c->mt = kh_init(mt, mrb);
+ k = kh_put(mt, mrb, h, mid);
+ kh_value(h, k) = p;
+ if (p) {
+ p->c = NULL;
+ mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
+ }
+ mc_clear_by_id(mrb, c, mid);
+}
+
+MRB_API void
+mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec)
+{
+ struct RProc *p;
+ int ai = mrb_gc_arena_save(mrb);
+
+ p = mrb_proc_new_cfunc(mrb, func);
+ p->target_class = c;
+ mrb_define_method_raw(mrb, c, mid, p);
+ mrb_gc_arena_restore(mrb, ai);
+}
+
+MRB_API void
+mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
+{
+ mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec);
+}
+
+/* a function to raise NotImplementedError with current method name */
+MRB_API void
+mrb_notimplement(mrb_state *mrb)
+{
+ const char *str;
+ mrb_int len;
+ mrb_callinfo *ci = mrb->c->ci;
+
+ if (ci->mid) {
+ str = mrb_sym2name_len(mrb, ci->mid, &len);
+ mrb_raisef(mrb, E_NOTIMP_ERROR,
+ "%S() function is unimplemented on this machine",
+ mrb_str_new_static(mrb, str, (size_t)len));
+ }
+}
+
+/* a function to be replacement of unimplemented method */
+MRB_API mrb_value
+mrb_notimplement_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_notimplement(mrb);
+ /* not reached */
+ return mrb_nil_value();
+}
+
+static mrb_value
+check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m)
+{
+ mrb_value tmp;
+
+ tmp = mrb_check_convert_type(mrb, val, t, c, m);
+ if (mrb_nil_p(tmp)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_cstr(mrb, c));
+ }
+ return tmp;
+}
+
+static mrb_value
+to_str(mrb_state *mrb, mrb_value val)
+{
+ return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
+}
+
+static mrb_value
+to_ary(mrb_state *mrb, mrb_value val)
+{
+ return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
+}
+
+static mrb_value
+to_hash(mrb_state *mrb, mrb_value val)
+{
+ return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
+}
+
+static mrb_sym
+to_sym(mrb_state *mrb, mrb_value ss)
+{
+ if (mrb_type(ss) == MRB_TT_SYMBOL) {
+ return mrb_symbol(ss);
+ }
+ else if (mrb_string_p(ss)) {
+ return mrb_intern_str(mrb, to_str(mrb, ss));
+ }
+ else {
+ mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
+ /* not reached */
+ return 0;
+ }
+}
+
+/*
+ retrieve arguments from mrb_state.
+
+ mrb_get_args(mrb, format, ...)
+
+ returns number of arguments parsed.
+
+ format specifiers:
+
+ string mruby type C type note
+ ----------------------------------------------------------------------------------------------
+ o: Object [mrb_value]
+ C: class/module [mrb_value]
+ S: String [mrb_value] when ! follows, the value may be nil
+ A: Array [mrb_value] when ! follows, the value may be nil
+ H: Hash [mrb_value] when ! follows, the value may be nil
+ s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
+ z: String [char*] NUL terminated string; z! gives NULL for nil
+ a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil
+ f: Float [mrb_float]
+ i: Integer [mrb_int]
+ b: Boolean [mrb_bool]
+ n: Symbol [mrb_sym]
+ d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified
+ I: Inline struct [void*]
+ &: Block [mrb_value]
+ *: rest argument [mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack
+ |: optional Following arguments are optional
+ ?: optional given [mrb_bool] true if preceding argument (optional) is given
+ */
+MRB_API mrb_int
+mrb_get_args(mrb_state *mrb, const char *format, ...)
+{
+ const char *fmt = format;
+ char c;
+ int i = 0;
+ va_list ap;
+ int argc = mrb->c->ci->argc;
+ int arg_i = 0;
+ mrb_value *array_argv;
+ mrb_bool opt = FALSE;
+ mrb_bool opt_skip = TRUE;
+ mrb_bool given = TRUE;
+
+ va_start(ap, format);
+ if (argc < 0) {
+ struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]);
+
+ argc = ARY_LEN(a);
+ array_argv = ARY_PTR(a);
+ }
+ else {
+ array_argv = NULL;
+ }
+
+#define ARGV \
+ (array_argv ? array_argv : (mrb->c->stack + 1))
+
+ while ((c = *fmt++)) {
+ switch (c) {
+ case '|':
+ opt = TRUE;
+ break;
+ case '*':
+ opt_skip = FALSE;
+ goto check_exit;
+ case '!':
+ break;
+ case '&': case '?':
+ if (opt) opt_skip = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ check_exit:
+ opt = FALSE;
+ i = 0;
+ while ((c = *format++)) {
+ switch (c) {
+ case '|': case '*': case '&': case '?':
+ break;
+ default:
+ if (argc <= i) {
+ if (opt) {
+ given = FALSE;
+ }
+ else {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ }
+ }
+ break;
+ }
+
+ switch (c) {
+ case 'o':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ if (i < argc) {
+ *p = ARGV[arg_i++];
+ i++;
+ }
+ }
+ break;
+ case 'C':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ if (i < argc) {
+ mrb_value ss;
+
+ ss = ARGV[arg_i++];
+ if (!class_ptr_p(ss)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss);
+ }
+ *p = ss;
+ i++;
+ }
+ }
+ break;
+ case 'S':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *p = ARGV[arg_i++];
+ i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ *p = to_str(mrb, ARGV[arg_i++]);
+ i++;
+ }
+ }
+ break;
+ case 'A':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *p = ARGV[arg_i++];
+ i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ *p = to_ary(mrb, ARGV[arg_i++]);
+ i++;
+ }
+ }
+ break;
+ case 'H':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *p = ARGV[arg_i++];
+ i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ *p = to_hash(mrb, ARGV[arg_i++]);
+ i++;
+ }
+ }
+ break;
+ case 's':
+ {
+ mrb_value ss;
+ char **ps = 0;
+ mrb_int *pl = 0;
+
+ ps = va_arg(ap, char**);
+ pl = va_arg(ap, mrb_int*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *ps = NULL;
+ *pl = 0;
+ i++; arg_i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ ss = to_str(mrb, ARGV[arg_i++]);
+ *ps = RSTRING_PTR(ss);
+ *pl = RSTRING_LEN(ss);
+ i++;
+ }
+ }
+ break;
+ case 'z':
+ {
+ mrb_value ss;
+ const char **ps;
+
+ ps = va_arg(ap, const char**);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *ps = NULL;
+ i++; arg_i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ ss = to_str(mrb, ARGV[arg_i++]);
+ *ps = mrb_string_value_cstr(mrb, &ss);
+ i++;
+ }
+ }
+ break;
+ case 'a':
+ {
+ mrb_value aa;
+ struct RArray *a;
+ mrb_value **pb;
+ mrb_int *pl;
+
+ pb = va_arg(ap, mrb_value**);
+ pl = va_arg(ap, mrb_int*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *pb = 0;
+ *pl = 0;
+ i++; arg_i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ aa = to_ary(mrb, ARGV[arg_i++]);
+ a = mrb_ary_ptr(aa);
+ *pb = ARY_PTR(a);
+ *pl = ARY_LEN(a);
+ i++;
+ }
+ }
+ break;
+ case 'I':
+ {
+ void* *p;
+ mrb_value ss;
+
+ p = va_arg(ap, void**);
+ if (i < argc) {
+ ss = ARGV[arg_i];
+ if (mrb_type(ss) != MRB_TT_ISTRUCT)
+ {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss);
+ }
+ *p = mrb_istruct_ptr(ss);
+ arg_i++;
+ i++;
+ }
+ }
+ break;
+ case 'f':
+ {
+ mrb_float *p;
+
+ p = va_arg(ap, mrb_float*);
+ if (i < argc) {
+ *p = mrb_to_flo(mrb, ARGV[arg_i]);
+ arg_i++;
+ i++;
+ }
+ }
+ break;
+ case 'i':
+ {
+ mrb_int *p;
+
+ p = va_arg(ap, mrb_int*);
+ if (i < argc) {
+ switch (mrb_type(ARGV[arg_i])) {
+ case MRB_TT_FIXNUM:
+ *p = mrb_fixnum(ARGV[arg_i]);
+ break;
+ case MRB_TT_FLOAT:
+ {
+ mrb_float f = mrb_float(ARGV[arg_i]);
+
+ if (!FIXABLE_FLOAT(f)) {
+ mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
+ }
+ *p = (mrb_int)f;
+ }
+ break;
+ case MRB_TT_STRING:
+ mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
+ break;
+ default:
+ *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i]));
+ break;
+ }
+ arg_i++;
+ i++;
+ }
+ }
+ break;
+ case 'b':
+ {
+ mrb_bool *boolp = va_arg(ap, mrb_bool*);
+
+ if (i < argc) {
+ mrb_value b = ARGV[arg_i++];
+ *boolp = mrb_test(b);
+ i++;
+ }
+ }
+ break;
+ case 'n':
+ {
+ mrb_sym *symp;
+
+ symp = va_arg(ap, mrb_sym*);
+ if (i < argc) {
+ mrb_value ss;
+
+ ss = ARGV[arg_i++];
+ *symp = to_sym(mrb, ss);
+ i++;
+ }
+ }
+ break;
+ case 'd':
+ {
+ void** datap;
+ struct mrb_data_type const* type;
+
+ datap = va_arg(ap, void**);
+ type = va_arg(ap, struct mrb_data_type const*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(ARGV[arg_i])) {
+ *datap = 0;
+ i++; arg_i++;
+ break;
+ }
+ }
+ if (i < argc) {
+ *datap = mrb_data_get_ptr(mrb, ARGV[arg_i++], type);
+ ++i;
+ }
+ }
+ break;
+
+ case '&':
+ {
+ mrb_value *p, *bp;
+
+ p = va_arg(ap, mrb_value*);
+ if (mrb->c->ci->argc < 0) {
+ bp = mrb->c->stack + 2;
+ }
+ else {
+ bp = mrb->c->stack + mrb->c->ci->argc + 1;
+ }
+ *p = *bp;
+ }
+ break;
+ case '|':
+ if (opt_skip && i == argc) return argc;
+ opt = TRUE;
+ break;
+ case '?':
+ {
+ mrb_bool *p;
+
+ p = va_arg(ap, mrb_bool*);
+ *p = given;
+ }
+ break;
+
+ case '*':
+ {
+ mrb_value **var;
+ mrb_int *pl;
+ mrb_bool nocopy = array_argv ? TRUE : FALSE;
+
+ if (*format == '!') {
+ format++;
+ nocopy = TRUE;
+ }
+ var = va_arg(ap, mrb_value**);
+ pl = va_arg(ap, mrb_int*);
+ if (argc > i) {
+ *pl = argc-i;
+ if (*pl > 0) {
+ if (nocopy) {
+ *var = ARGV+arg_i;
+ }
+ else {
+ mrb_value args = mrb_ary_new_from_values(mrb, *pl, ARGV+arg_i);
+ RARRAY(args)->c = NULL;
+ *var = RARRAY_PTR(args);
+ }
+ }
+ i = argc;
+ arg_i += *pl;
+ }
+ else {
+ *pl = 0;
+ *var = NULL;
+ }
+ }
+ break;
+ default:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
+ break;
+ }
+ }
+
+#undef ARGV
+
+ if (!c && argc > i) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ }
+ va_end(ap);
+ return i;
+}
+
+static struct RClass*
+boot_defclass(mrb_state *mrb, struct RClass *super)
+{
+ struct RClass *c;
+
+ c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class);
+ if (super) {
+ c->super = super;
+ mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
+ }
+ else {
+ c->super = mrb->object_class;
+ }
+ c->mt = kh_init(mt, mrb);
+ return c;
+}
+
+static void
+boot_initmod(mrb_state *mrb, struct RClass *mod)
+{
+ if (!mod->mt) {
+ mod->mt = kh_init(mt, mrb);
+ }
+}
+
+static struct RClass*
+include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super)
+{
+ struct RClass *ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
+ if (m->tt == MRB_TT_ICLASS) {
+ m = m->c;
+ }
+ MRB_CLASS_ORIGIN(m);
+ ic->iv = m->iv;
+ ic->mt = m->mt;
+ ic->super = super;
+ if (m->tt == MRB_TT_ICLASS) {
+ ic->c = m->c;
+ }
+ else {
+ ic->c = m;
+ }
+ return ic;
+}
+
+static int
+include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super)
+{
+ struct RClass *p, *ic;
+ void *klass_mt = find_origin(c)->mt;
+
+ while (m) {
+ int superclass_seen = 0;
+
+ if (m->flags & MRB_FLAG_IS_PREPENDED)
+ goto skip;
+
+ if (klass_mt && klass_mt == m->mt)
+ return -1;
+
+ p = c->super;
+ while (p) {
+ if (p->tt == MRB_TT_ICLASS) {
+ if (p->mt == m->mt) {
+ if (!superclass_seen) {
+ ins_pos = p; /* move insert point */
+ }
+ goto skip;
+ }
+ } else if (p->tt == MRB_TT_CLASS) {
+ if (!search_super) break;
+ superclass_seen = 1;
+ }
+ p = p->super;
+ }
+
+ ic = include_class_new(mrb, m, ins_pos->super);
+ m->flags |= MRB_FLAG_IS_INHERITED;
+ ins_pos->super = ic;
+ mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
+ mc_clear_by_class(mrb, ins_pos);
+ ins_pos = ic;
+ skip:
+ m = m->super;
+ }
+ mc_clear_all(mrb);
+ return 0;
+}
+
+MRB_API void
+mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
+{
+ int changed = include_module_at(mrb, c, find_origin(c), m, 1);
+ if (changed < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
+ }
+}
+
+MRB_API void
+mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
+{
+ struct RClass *origin;
+ int changed = 0;
+
+ if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
+ origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
+ origin->flags |= MRB_FLAG_IS_ORIGIN | MRB_FLAG_IS_INHERITED;
+ origin->super = c->super;
+ c->super = origin;
+ origin->mt = c->mt;
+ c->mt = kh_init(mt, mrb);
+ mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin);
+ c->flags |= MRB_FLAG_IS_PREPENDED;
+ }
+ changed = include_module_at(mrb, c, c, m, 0);
+ if (changed < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic prepend detected");
+ }
+}
+
+static mrb_value
+mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value klass;
+
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
+ mrb_get_args(mrb, "C", &klass);
+ mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
+ return mod;
+}
+
+static mrb_value
+mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value klass;
+
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
+ mrb_get_args(mrb, "C", &klass);
+ mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
+ return mod;
+}
+
+/* 15.2.2.4.28 */
+/*
+ * call-seq:
+ * mod.include?(module) -> true or false
+ *
+ * Returns <code>true</code> if <i>module</i> is included in
+ * <i>mod</i> or one of <i>mod</i>'s ancestors.
+ *
+ * module A
+ * end
+ * class B
+ * include A
+ * end
+ * class C < B
+ * end
+ * B.include?(A) #=> true
+ * C.include?(A) #=> true
+ * A.include?(A) #=> false
+ */
+static mrb_value
+mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value mod2;
+ struct RClass *c = mrb_class_ptr(mod);
+
+ mrb_get_args(mrb, "C", &mod2);
+ mrb_check_type(mrb, mod2, MRB_TT_MODULE);
+
+ while (c) {
+ if (c->tt == MRB_TT_ICLASS) {
+ if (c->c == mrb_class_ptr(mod2)) return mrb_true_value();
+ }
+ c = c->super;
+ }
+ return mrb_false_value();
+}
+
+static mrb_value
+mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ struct RClass *c = mrb_class_ptr(self);
+ result = mrb_ary_new(mrb);
+ while (c) {
+ if (c->tt == MRB_TT_ICLASS) {
+ mrb_ary_push(mrb, result, mrb_obj_value(c->c));
+ }
+ else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
+ mrb_ary_push(mrb, result, mrb_obj_value(c));
+ }
+ c = c->super;
+ }
+
+ return result;
+}
+
+static mrb_value
+mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value obj;
+
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
+ mrb_get_args(mrb, "o", &obj);
+ mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
+ return mod;
+}
+
+static mrb_value
+mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ struct RClass *c = mrb_class_ptr(self);
+ struct RClass *origin = c;
+
+ MRB_CLASS_ORIGIN(origin);
+ result = mrb_ary_new(mrb);
+ while (c) {
+ if (c != origin && c->tt == MRB_TT_ICLASS) {
+ if (c->c->tt == MRB_TT_MODULE) {
+ mrb_ary_push(mrb, result, mrb_obj_value(c->c));
+ }
+ }
+ c = c->super;
+ }
+
+ return result;
+}
+
+static mrb_value
+mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value b;
+ struct RClass *m = mrb_class_ptr(mod);
+ boot_initmod(mrb, m); /* bootstrap a newly initialized module */
+ mrb_get_args(mrb, "|&", &b);
+ if (!mrb_nil_p(b)) {
+ mrb_yield_with_class(mrb, b, 1, &mod, mod, m);
+ }
+ return mod;
+}
+
+mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int);
+
+/* 15.2.2.4.33 */
+/*
+ * call-seq:
+ * mod.instance_methods(include_super=true) -> array
+ *
+ * Returns an array containing the names of the public and protected instance
+ * methods in the receiver. For a module, these are the public and protected methods;
+ * for a class, they are the instance (not singleton) methods. With no
+ * argument, or with an argument that is <code>false</code>, the
+ * instance methods in <i>mod</i> are returned, otherwise the methods
+ * in <i>mod</i> and <i>mod</i>'s superclasses are returned.
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * def method2() end
+ * end
+ * class C < B
+ * def method3() end
+ * end
+ *
+ * A.instance_methods #=> [:method1]
+ * B.instance_methods(false) #=> [:method2]
+ * C.instance_methods(false) #=> [:method3]
+ * C.instance_methods(true).length #=> 43
+ */
+
+static mrb_value
+mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
+{
+ struct RClass *c = mrb_class_ptr(mod);
+ mrb_bool recur = TRUE;
+ mrb_get_args(mrb, "|b", &recur);
+ return mrb_class_instance_method_list(mrb, recur, c, 0);
+}
+
+/* implementation of module_eval/class_eval */
+mrb_value mrb_mod_module_eval(mrb_state*, mrb_value);
+
+static mrb_value
+mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
+{
+ return mod;
+}
+
+MRB_API mrb_value
+mrb_singleton_class(mrb_state *mrb, mrb_value v)
+{
+ struct RBasic *obj;
+
+ switch (mrb_type(v)) {
+ case MRB_TT_FALSE:
+ if (mrb_nil_p(v))
+ return mrb_obj_value(mrb->nil_class);
+ return mrb_obj_value(mrb->false_class);
+ case MRB_TT_TRUE:
+ return mrb_obj_value(mrb->true_class);
+ case MRB_TT_CPTR:
+ return mrb_obj_value(mrb->object_class);
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
+ return mrb_nil_value(); /* not reached */
+ default:
+ break;
+ }
+ obj = mrb_basic_ptr(v);
+ prepare_singleton_class(mrb, obj);
+ return mrb_obj_value(obj->c);
+}
+
+MRB_API void
+mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec)
+{
+ prepare_singleton_class(mrb, (struct RBasic*)o);
+ mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec);
+}
+
+MRB_API void
+mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
+{
+ mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec);
+}
+
+MRB_API void
+mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec)
+{
+ mrb_define_class_method(mrb, c, name, func, aspec);
+ mrb_define_method(mrb, c, name, func, aspec);
+}
+
+#ifdef MRB_METHOD_CACHE
+static void
+mc_clear_all(mrb_state *mrb)
+{
+ struct mrb_cache_entry *mc = mrb->cache;
+ int i;
+
+ for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
+ mc[i].c = 0;
+ }
+}
+
+static void
+mc_clear_by_class(mrb_state *mrb, struct RClass *c)
+{
+ struct mrb_cache_entry *mc = mrb->cache;
+ int i;
+
+ if (c->flags & MRB_FLAG_IS_INHERITED) {
+ mc_clear_all(mrb);
+ c->flags &= ~MRB_FLAG_IS_INHERITED;
+ return;
+ }
+ for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
+ if (mc[i].c == c) mc[i].c = 0;
+ }
+}
+
+static void
+mc_clear_by_id(mrb_state *mrb, struct RClass *c, mrb_sym mid)
+{
+ struct mrb_cache_entry *mc = mrb->cache;
+ int i;
+
+ if (c->flags & MRB_FLAG_IS_INHERITED) {
+ mc_clear_all(mrb);
+ c->flags &= ~MRB_FLAG_IS_INHERITED;
+ return;
+ }
+ for (i=0; i<MRB_METHOD_CACHE_SIZE; i++) {
+ if (mc[i].c == c || mc[i].mid == mid)
+ mc[i].c = 0;
+ }
+}
+#endif
+
+MRB_API struct RProc*
+mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
+{
+ khiter_t k;
+ struct RProc *m;
+ struct RClass *c = *cp;
+#ifdef MRB_METHOD_CACHE
+ struct RClass *oc = c;
+ int h = kh_int_hash_func(mrb, ((intptr_t)oc) ^ mid) & (MRB_METHOD_CACHE_SIZE-1);
+ struct mrb_cache_entry *mc = &mrb->cache[h];
+
+ if (mc->c == c && mc->mid == mid) {
+ return mc->m;
+ }
+#endif
+
+ while (c) {
+ khash_t(mt) *h = c->mt;
+
+ if (h) {
+ k = kh_get(mt, mrb, h, mid);
+ if (k != kh_end(h)) {
+ m = kh_value(h, k);
+ if (!m) break;
+ *cp = c;
+#ifdef MRB_METHOD_CACHE
+ mc->c = oc;
+ mc->mid = mid;
+ mc->m = m;
+#endif
+ return m;
+ }
+ }
+ c = c->super;
+ }
+ return NULL; /* no method */
+}
+
+MRB_API struct RProc*
+mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
+{
+ struct RProc *m;
+
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (!m) {
+ mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
+ if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) {
+ inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
+ }
+ mrb_name_error(mrb, mid, "undefined method '%S' for class %S",
+ mrb_sym2str(mrb, mid), inspect);
+ }
+ return m;
+}
+
+static mrb_value
+attr_reader(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
+ return mrb_iv_get(mrb, obj, to_sym(mrb, name));
+}
+
+static mrb_value
+mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
+{
+ struct RClass *c = mrb_class_ptr(mod);
+ mrb_value *argv;
+ mrb_int argc, i;
+ int ai;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ ai = mrb_gc_arena_save(mrb);
+ for (i=0; i<argc; i++) {
+ mrb_value name, str;
+ mrb_sym method, sym;
+
+ method = to_sym(mrb, argv[i]);
+ name = mrb_sym2str(mrb, method);
+ str = mrb_str_new_capa(mrb, RSTRING_LEN(name)+1);
+ mrb_str_cat_lit(mrb, str, "@");
+ mrb_str_cat_str(mrb, str, name);
+ sym = mrb_intern_str(mrb, str);
+ mrb_iv_check(mrb, sym);
+ name = mrb_symbol_value(sym);
+ mrb_define_method_raw(mrb, c, method,
+ mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ return mrb_nil_value();
+}
+
+static mrb_value
+attr_writer(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
+ mrb_value val;
+
+ mrb_get_args(mrb, "o", &val);
+ mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
+ return val;
+}
+
+static mrb_value
+mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
+{
+ struct RClass *c = mrb_class_ptr(mod);
+ mrb_value *argv;
+ mrb_int argc, i;
+ int ai;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ ai = mrb_gc_arena_save(mrb);
+ for (i=0; i<argc; i++) {
+ mrb_value name, str, attr;
+ mrb_sym method, sym;
+
+ method = to_sym(mrb, argv[i]);
+
+ /* prepare iv name (@name) */
+ name = mrb_sym2str(mrb, method);
+ str = mrb_str_new_capa(mrb, RSTRING_LEN(name)+1);
+ mrb_str_cat_lit(mrb, str, "@");
+ mrb_str_cat_str(mrb, str, name);
+ sym = mrb_intern_str(mrb, str);
+ mrb_iv_check(mrb, sym);
+ attr = mrb_symbol_value(sym);
+
+ /* prepare method name (name=) */
+ str = mrb_str_new_capa(mrb, RSTRING_LEN(str));
+ mrb_str_cat_str(mrb, str, name);
+ mrb_str_cat_lit(mrb, str, "=");
+ method = mrb_intern_str(mrb, str);
+
+ mrb_define_method_raw(mrb, c, method,
+ mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
+{
+ struct RClass *c = mrb_class_ptr(cv);
+ struct RObject *o;
+ enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
+
+ if (c->tt == MRB_TT_SCLASS)
+ mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");
+
+ if (ttype == 0) ttype = MRB_TT_OBJECT;
+ if (ttype <= MRB_TT_CPTR) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv);
+ }
+ o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
+ return mrb_obj_value(o);
+}
+
+/*
+ * call-seq:
+ * class.new(args, ...) -> obj
+ *
+ * Creates a new object of <i>class</i>'s class, then
+ * invokes that object's <code>initialize</code> method,
+ * passing it <i>args</i>. This is the method that ends
+ * up getting called whenever an object is constructed using
+ * `.new`.
+ *
+ */
+
+MRB_API mrb_value
+mrb_instance_new(mrb_state *mrb, mrb_value cv)
+{
+ mrb_value obj, blk;
+ mrb_value *argv;
+ mrb_int argc;
+ mrb_sym init;
+
+ mrb_get_args(mrb, "*&", &argv, &argc, &blk);
+ obj = mrb_instance_alloc(mrb, cv);
+ init = mrb_intern_lit(mrb, "initialize");
+ if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) {
+ mrb_funcall_with_block(mrb, obj, init, argc, argv, blk);
+ }
+
+ return obj;
+}
+
+MRB_API mrb_value
+mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv)
+{
+ mrb_value obj;
+ mrb_sym mid;
+
+ obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
+ mid = mrb_intern_lit(mrb, "initialize");
+ if (!mrb_func_basic_p(mrb, obj, mid, mrb_bob_init)) {
+ mrb_funcall_argv(mrb, obj, mid, argc, argv);
+ }
+ return obj;
+}
+
+static mrb_value
+mrb_class_initialize(mrb_state *mrb, mrb_value c)
+{
+ mrb_value a, b;
+
+ mrb_get_args(mrb, "|C&", &a, &b);
+ if (!mrb_nil_p(b)) {
+ mrb_yield_with_class(mrb, b, 1, &c, c, mrb_class_ptr(c));
+ }
+ return c;
+}
+
+static mrb_value
+mrb_class_new_class(mrb_state *mrb, mrb_value cv)
+{
+ mrb_int n;
+ mrb_value super, blk;
+ mrb_value new_class;
+ mrb_sym mid;
+
+ n = mrb_get_args(mrb, "|C&", &super, &blk);
+ if (n == 0) {
+ super = mrb_obj_value(mrb->object_class);
+ }
+ new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
+ mid = mrb_intern_lit(mrb, "initialize");
+ if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) {
+ mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
+ }
+ mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
+ return new_class;
+}
+
+static mrb_value
+mrb_class_superclass(mrb_state *mrb, mrb_value klass)
+{
+ struct RClass *c;
+
+ c = mrb_class_ptr(klass);
+ c = find_origin(c)->super;
+ while (c && c->tt == MRB_TT_ICLASS) {
+ c = find_origin(c)->super;
+ }
+ if (!c) return mrb_nil_value();
+ return mrb_obj_value(c);
+}
+
+static mrb_value
+mrb_bob_init(mrb_state *mrb, mrb_value cv)
+{
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_bob_not(mrb_state *mrb, mrb_value cv)
+{
+ return mrb_bool_value(!mrb_test(cv));
+}
+
+/* 15.3.1.3.1 */
+/* 15.3.1.3.10 */
+/* 15.3.1.3.11 */
+/*
+ * call-seq:
+ * obj == other -> true or false
+ * obj.equal?(other) -> true or false
+ * obj.eql?(other) -> true or false
+ *
+ * Equality---At the <code>Object</code> level, <code>==</code> returns
+ * <code>true</code> only if <i>obj</i> and <i>other</i> are the
+ * same object. Typically, this method is overridden in descendant
+ * classes to provide class-specific meaning.
+ *
+ * Unlike <code>==</code>, the <code>equal?</code> method should never be
+ * overridden by subclasses: it is used to determine object identity
+ * (that is, <code>a.equal?(b)</code> iff <code>a</code> is the same
+ * object as <code>b</code>).
+ *
+ * The <code>eql?</code> method returns <code>true</code> if
+ * <i>obj</i> and <i>anObject</i> have the same value. Used by
+ * <code>Hash</code> to test members for equality. For objects of
+ * class <code>Object</code>, <code>eql?</code> is synonymous with
+ * <code>==</code>. Subclasses normally continue this tradition, but
+ * there are exceptions. <code>Numeric</code> types, for example,
+ * perform type conversion across <code>==</code>, but not across
+ * <code>eql?</code>, so:
+ *
+ * 1 == 1.0 #=> true
+ * 1.eql? 1.0 #=> false
+ */
+mrb_value
+mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
+}
+
+static mrb_value
+mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ return mrb_bool_value(!mrb_equal(mrb, self, arg));
+}
+
+MRB_API mrb_bool
+mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
+{
+ struct RProc *m;
+
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (!m) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+MRB_API mrb_bool
+mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid)
+{
+ return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid);
+}
+
+MRB_API mrb_value
+mrb_class_path(mrb_state *mrb, struct RClass *c)
+{
+ mrb_value path;
+ mrb_sym nsym = mrb_intern_lit(mrb, "__classname__");
+
+ path = mrb_obj_iv_get(mrb, (struct RObject*)c, nsym);
+ if (mrb_nil_p(path)) {
+ /* no name (yet) */
+ return mrb_class_find_path(mrb, c);
+ }
+ else if (mrb_symbol_p(path)) {
+ /* topleve class/module */
+ const char *str;
+ mrb_int len;
+
+ str = mrb_sym2name_len(mrb, mrb_symbol(path), &len);
+ return mrb_str_new(mrb, str, len);
+ }
+ return mrb_str_dup(mrb, path);
+}
+
+MRB_API struct RClass*
+mrb_class_real(struct RClass* cl)
+{
+ if (cl == 0)
+ return NULL;
+ while ((cl->tt == MRB_TT_SCLASS) || (cl->tt == MRB_TT_ICLASS)) {
+ cl = cl->super;
+ }
+ return cl;
+}
+
+MRB_API const char*
+mrb_class_name(mrb_state *mrb, struct RClass* c)
+{
+ mrb_value path = mrb_class_path(mrb, c);
+ if (mrb_nil_p(path)) {
+ path = mrb_str_new_lit(mrb, "#<Class:");
+ mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
+ mrb_str_cat_lit(mrb, path, ">");
+ }
+ return RSTRING_PTR(path);
+}
+
+MRB_API const char*
+mrb_obj_classname(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_class_name(mrb, mrb_obj_class(mrb, obj));
+}
+
+/*!
+ * Ensures a class can be derived from super.
+ *
+ * \param super a reference to an object.
+ * \exception TypeError if \a super is not a Class or \a super is a singleton class.
+ */
+static void
+mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
+{
+ if (super->tt != MRB_TT_CLASS) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
+ }
+ if (super->tt == MRB_TT_SCLASS) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
+ }
+ if (super == mrb->class_class) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of Class");
+ }
+}
+
+/*!
+ * Creates a new class.
+ * \param super a class from which the new class derives.
+ * \exception TypeError \a super is not inheritable.
+ * \exception TypeError \a super is the Class class.
+ */
+MRB_API struct RClass*
+mrb_class_new(mrb_state *mrb, struct RClass *super)
+{
+ struct RClass *c;
+
+ if (super) {
+ mrb_check_inheritable(mrb, super);
+ }
+ c = boot_defclass(mrb, super);
+ if (super) {
+ MRB_SET_INSTANCE_TT(c, MRB_INSTANCE_TT(super));
+ }
+ make_metaclass(mrb, c);
+
+ return c;
+}
+
+/*!
+ * Creates a new module.
+ */
+MRB_API struct RClass*
+mrb_module_new(mrb_state *mrb)
+{
+ struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
+ boot_initmod(mrb, m);
+ return m;
+}
+
+/*
+ * call-seq:
+ * obj.class => class
+ *
+ * Returns the class of <i>obj</i>, now preferred over
+ * <code>Object#type</code>, as an object's type in Ruby is only
+ * loosely tied to that object's class. This method must always be
+ * called with an explicit receiver, as <code>class</code> is also a
+ * reserved word in Ruby.
+ *
+ * 1.class #=> Fixnum
+ * self.class #=> Object
+ */
+
+MRB_API struct RClass*
+mrb_obj_class(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_class_real(mrb_class(mrb, obj));
+}
+
+MRB_API void
+mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
+{
+ struct RProc *m = mrb_method_search(mrb, c, b);
+
+ mrb_define_method_raw(mrb, c, a, m);
+}
+
+/*!
+ * Defines an alias of a method.
+ * \param klass the class which the original method belongs to
+ * \param name1 a new name for the method
+ * \param name2 the original name of the method
+ */
+MRB_API void
+mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2)
+{
+ mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2));
+}
+
+/*
+ * call-seq:
+ * mod.to_s -> string
+ *
+ * Return a string representing this module or class. For basic
+ * classes and modules, this is the name. For singletons, we
+ * show information on the thing we're attached to as well.
+ */
+
+static mrb_value
+mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value str;
+
+ if (mrb_type(klass) == MRB_TT_SCLASS) {
+ mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
+
+ str = mrb_str_new_lit(mrb, "#<Class:");
+
+ if (class_ptr_p(v)) {
+ mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v));
+ }
+ else {
+ mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v));
+ }
+ return mrb_str_cat_lit(mrb, str, ">");
+ }
+ else {
+ struct RClass *c;
+ mrb_value path;
+
+ str = mrb_str_new_capa(mrb, 32);
+ c = mrb_class_ptr(klass);
+ path = mrb_class_path(mrb, c);
+
+ if (mrb_nil_p(path)) {
+ switch (mrb_type(klass)) {
+ case MRB_TT_CLASS:
+ mrb_str_cat_lit(mrb, str, "#<Class:");
+ break;
+
+ case MRB_TT_MODULE:
+ mrb_str_cat_lit(mrb, str, "#<Module:");
+ break;
+
+ default:
+ /* Shouldn't be happened? */
+ mrb_str_cat_lit(mrb, str, "#<??????:");
+ break;
+ }
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
+ return mrb_str_cat_lit(mrb, str, ">");
+ }
+ else {
+ return path;
+ }
+ }
+}
+
+static mrb_value
+mrb_mod_alias(mrb_state *mrb, mrb_value mod)
+{
+ struct RClass *c = mrb_class_ptr(mod);
+ mrb_sym new_name, old_name;
+
+ mrb_get_args(mrb, "nn", &new_name, &old_name);
+ mrb_alias_method(mrb, c, new_name, old_name);
+ return mrb_nil_value();
+}
+
+static void
+undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
+{
+ if (!mrb_obj_respond_to(mrb, c, a)) {
+ mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
+ }
+ else {
+ mrb_define_method_raw(mrb, c, a, NULL);
+ }
+}
+
+MRB_API void
+mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
+{
+ undef_method(mrb, c, mrb_intern_cstr(mrb, name));
+}
+
+MRB_API void
+mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name)
+{
+ mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name);
+}
+
+static mrb_value
+mrb_mod_undef(mrb_state *mrb, mrb_value mod)
+{
+ struct RClass *c = mrb_class_ptr(mod);
+ mrb_int argc;
+ mrb_value *argv;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ while (argc--) {
+ undef_method(mrb, c, to_sym(mrb, *argv));
+ argv++;
+ }
+ return mrb_nil_value();
+}
+
+static mrb_value
+mod_define_method(mrb_state *mrb, mrb_value self)
+{
+ struct RClass *c = mrb_class_ptr(self);
+ struct RProc *p;
+ mrb_sym mid;
+ mrb_value proc = mrb_undef_value();
+ mrb_value blk;
+
+ mrb_get_args(mrb, "n|o&", &mid, &proc, &blk);
+ switch (mrb_type(proc)) {
+ case MRB_TT_PROC:
+ blk = proc;
+ break;
+ case MRB_TT_UNDEF:
+ /* ignored */
+ break;
+ default:
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc)));
+ break;
+ }
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ mrb_proc_copy(p, mrb_proc_ptr(blk));
+ p->flags |= MRB_PROC_STRICT;
+ mrb_define_method_raw(mrb, c, mid, p);
+ return mrb_symbol_value(mid);
+}
+
+static void
+check_cv_name_str(mrb_state *mrb, mrb_value str)
+{
+ const char *s = RSTRING_PTR(str);
+ mrb_int len = RSTRING_LEN(str);
+
+ if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
+ mrb_name_error(mrb, mrb_intern_str(mrb, str), "'%S' is not allowed as a class variable name", str);
+ }
+}
+
+static void
+check_cv_name_sym(mrb_state *mrb, mrb_sym id)
+{
+ check_cv_name_str(mrb, mrb_sym2str(mrb, id));
+}
+
+/* 15.2.2.4.16 */
+/*
+ * call-seq:
+ * obj.class_variable_defined?(symbol) -> true or false
+ *
+ * Returns <code>true</code> if the given class variable is defined
+ * in <i>obj</i>.
+ *
+ * class Fred
+ * @@foo = 99
+ * end
+ * Fred.class_variable_defined?(:@@foo) #=> true
+ * Fred.class_variable_defined?(:@@bar) #=> false
+ */
+
+static mrb_value
+mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym id;
+
+ mrb_get_args(mrb, "n", &id);
+ check_cv_name_sym(mrb, id);
+ return mrb_bool_value(mrb_cv_defined(mrb, mod, id));
+}
+
+/* 15.2.2.4.17 */
+/*
+ * call-seq:
+ * mod.class_variable_get(symbol) -> obj
+ *
+ * Returns the value of the given class variable (or throws a
+ * <code>NameError</code> exception). The <code>@@</code> part of the
+ * variable name should be included for regular class variables
+ *
+ * class Fred
+ * @@foo = 99
+ * end
+ * Fred.class_variable_get(:@@foo) #=> 99
+ */
+
+static mrb_value
+mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym id;
+
+ mrb_get_args(mrb, "n", &id);
+ check_cv_name_sym(mrb, id);
+ return mrb_cv_get(mrb, mod, id);
+}
+
+/* 15.2.2.4.18 */
+/*
+ * call-seq:
+ * obj.class_variable_set(symbol, obj) -> obj
+ *
+ * Sets the class variable names by <i>symbol</i> to
+ * <i>object</i>.
+ *
+ * class Fred
+ * @@foo = 99
+ * def foo
+ * @@foo
+ * end
+ * end
+ * Fred.class_variable_set(:@@foo, 101) #=> 101
+ * Fred.new.foo #=> 101
+ */
+
+static mrb_value
+mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value value;
+ mrb_sym id;
+
+ mrb_get_args(mrb, "no", &id, &value);
+ check_cv_name_sym(mrb, id);
+ mrb_cv_set(mrb, mod, id, value);
+ return value;
+}
+
+/* 15.2.2.4.39 */
+/*
+ * call-seq:
+ * remove_class_variable(sym) -> obj
+ *
+ * Removes the definition of the <i>sym</i>, returning that
+ * constant's value.
+ *
+ * class Dummy
+ * @@var = 99
+ * puts @@var
+ * p class_variables
+ * remove_class_variable(:@@var)
+ * p class_variables
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * 99
+ * [:@@var]
+ * []
+ */
+
+static mrb_value
+mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value val;
+ mrb_sym id;
+
+ mrb_get_args(mrb, "n", &id);
+ check_cv_name_sym(mrb, id);
+
+ val = mrb_iv_remove(mrb, mod, id);
+ if (!mrb_undef_p(val)) return val;
+
+ if (mrb_cv_defined(mrb, mod, id)) {
+ mrb_name_error(mrb, id, "cannot remove %S for %S",
+ mrb_sym2str(mrb, id), mod);
+ }
+
+ mrb_name_error(mrb, id, "class variable %S not defined for %S",
+ mrb_sym2str(mrb, id), mod);
+
+ /* not reached */
+ return mrb_nil_value();
+}
+
+/* 15.2.2.4.34 */
+/*
+ * call-seq:
+ * mod.method_defined?(symbol) -> true or false
+ *
+ * Returns +true+ if the named method is defined by
+ * _mod_ (or its included modules and, if _mod_ is a class,
+ * its ancestors). Public and protected methods are matched.
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * def method2() end
+ * end
+ * class C < B
+ * include A
+ * def method3() end
+ * end
+ *
+ * A.method_defined? :method1 #=> true
+ * C.method_defined? "method1" #=> true
+ * C.method_defined? "method2" #=> true
+ * C.method_defined? "method3" #=> true
+ * C.method_defined? "method4" #=> false
+ */
+
+static mrb_value
+mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym id;
+
+ mrb_get_args(mrb, "n", &id);
+ return mrb_bool_value(mrb_obj_respond_to(mrb, mrb_class_ptr(mod), id));
+}
+
+static void
+remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
+{
+ struct RClass *c = mrb_class_ptr(mod);
+ khash_t(mt) *h = find_origin(c)->mt;
+ khiter_t k;
+
+ if (h) {
+ k = kh_get(mt, mrb, h, mid);
+ if (k != kh_end(h)) {
+ kh_del(mt, mrb, h, k);
+ mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid));
+ return;
+ }
+ }
+
+ mrb_name_error(mrb, mid, "method '%S' not defined in %S",
+ mrb_sym2str(mrb, mid), mod);
+}
+
+/* 15.2.2.4.41 */
+/*
+ * call-seq:
+ * remove_method(symbol) -> self
+ *
+ * Removes the method identified by _symbol_ from the current
+ * class. For an example, see <code>Module.undef_method</code>.
+ */
+
+static mrb_value
+mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
+{
+ mrb_int argc;
+ mrb_value *argv;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ while (argc--) {
+ remove_method(mrb, mod, to_sym(mrb, *argv));
+ argv++;
+ }
+ return mod;
+}
+
+
+
+static void
+check_const_name_str(mrb_state *mrb, mrb_value str)
+{
+ if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) {
+ mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str);
+ }
+}
+
+static void
+check_const_name_sym(mrb_state *mrb, mrb_sym id)
+{
+ check_const_name_str(mrb, mrb_sym2str(mrb, id));
+}
+
+static mrb_value
+const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool inherit)
+{
+ if (inherit) {
+ return mrb_bool_value(mrb_const_defined(mrb, mod, id));
+ }
+ return mrb_bool_value(mrb_const_defined_at(mrb, mod, id));
+}
+
+static mrb_value
+mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym id;
+ mrb_bool inherit = TRUE;
+
+ mrb_get_args(mrb, "n|b", &id, &inherit);
+ check_const_name_sym(mrb, id);
+ return const_defined(mrb, mod, id, inherit);
+}
+
+static mrb_value
+mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
+{
+ check_const_name_sym(mrb, id);
+ return mrb_const_get(mrb, mod, id);
+}
+
+static mrb_value
+mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value path;
+ mrb_sym id;
+ char *ptr;
+ mrb_int off, end, len;
+
+ mrb_get_args(mrb, "o", &path);
+
+ if (mrb_symbol_p(path)) {
+ /* const get with symbol */
+ id = mrb_symbol(path);
+ return mrb_const_get_sym(mrb, mod, id);
+ }
+
+ /* const get with class path string */
+ path = mrb_string_type(mrb, path);
+ ptr = RSTRING_PTR(path);
+ len = RSTRING_LEN(path);
+ off = 0;
+
+ while (off < len) {
+ end = mrb_str_index_lit(mrb, path, "::", off);
+ end = (end == -1) ? len : end;
+ id = mrb_intern(mrb, ptr+off, end-off);
+ mod = mrb_const_get_sym(mrb, mod, id);
+ off = (end == len) ? end : end+2;
+ }
+
+ return mod;
+}
+
+static mrb_value
+mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym id;
+ mrb_value value;
+
+ mrb_get_args(mrb, "no", &id, &value);
+ check_const_name_sym(mrb, id);
+ mrb_const_set(mrb, mod, id, value);
+ return value;
+}
+
+static mrb_value
+mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym id;
+ mrb_value val;
+
+ mrb_get_args(mrb, "n", &id);
+ check_const_name_sym(mrb, id);
+ val = mrb_iv_remove(mrb, mod, id);
+ if (mrb_undef_p(val)) {
+ mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
+ }
+ return val;
+}
+
+static mrb_value
+mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym sym;
+
+ mrb_get_args(mrb, "n", &sym);
+
+ if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
+ mrb_name_error(mrb, sym, "uninitialized constant %S::%S",
+ mod,
+ mrb_sym2str(mrb, sym));
+ }
+ else {
+ mrb_name_error(mrb, sym, "uninitialized constant %S",
+ mrb_sym2str(mrb, sym));
+ }
+ /* not reached */
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
+{
+ mrb_raise(mrb, E_NOTIMP_ERROR, "Module.constants not implemented");
+ return mrb_nil_value(); /* not reached */
+}
+
+static mrb_value
+mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value obj;
+ mrb_bool eqq;
+
+ mrb_get_args(mrb, "o", &obj);
+ eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
+
+ return mrb_bool_value(eqq);
+}
+
+MRB_API mrb_value
+mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value *argv;
+ mrb_int argc, i;
+ mrb_sym mid;
+ struct RProc *method_rproc;
+ struct RClass *rclass;
+ int ai;
+
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ if (argc == 0) {
+ /* set MODFUNC SCOPE if implemented */
+ return mod;
+ }
+
+ /* set PRIVATE method visibility if implemented */
+ /* mrb_mod_dummy_visibility(mrb, mod); */
+
+ for (i=0; i<argc; i++) {
+ mrb_check_type(mrb, argv[i], MRB_TT_SYMBOL);
+
+ mid = mrb_symbol(argv[i]);
+ rclass = mrb_class_ptr(mod);
+ method_rproc = mrb_method_search(mrb, rclass, mid);
+
+ prepare_singleton_class(mrb, (struct RBasic*)rclass);
+ ai = mrb_gc_arena_save(mrb);
+ mrb_define_method_raw(mrb, rclass->c, mid, method_rproc);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ return mod;
+}
+
+/* implementation of __id__ */
+mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self);
+/* implementation of instance_eval */
+mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value);
+/* implementation of Module.nesting */
+mrb_value mrb_mod_s_nesting(mrb_state*, mrb_value);
+
+void
+mrb_init_class(mrb_state *mrb)
+{
+ struct RClass *bob; /* BasicObject */
+ struct RClass *obj; /* Object */
+ struct RClass *mod; /* Module */
+ struct RClass *cls; /* Class */
+
+ /* boot class hierarchy */
+ bob = boot_defclass(mrb, 0);
+ obj = boot_defclass(mrb, bob); mrb->object_class = obj;
+ mod = boot_defclass(mrb, obj); mrb->module_class = mod;/* obj -> mod */
+ cls = boot_defclass(mrb, mod); mrb->class_class = cls; /* obj -> cls */
+ /* fix-up loose ends */
+ bob->c = obj->c = mod->c = cls->c = cls;
+ make_metaclass(mrb, bob);
+ make_metaclass(mrb, obj);
+ make_metaclass(mrb, mod);
+ make_metaclass(mrb, cls);
+
+ /* name basic classes */
+ mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
+ mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
+ mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj));
+ mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod));
+ mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
+
+ /* name each classes */
+ mrb_class_name_class(mrb, NULL, bob, mrb_intern_lit(mrb, "BasicObject"));
+ mrb_class_name_class(mrb, NULL, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */
+ mrb_class_name_class(mrb, NULL, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
+ mrb_class_name_class(mrb, NULL, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */
+
+ mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */
+ MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC);
+
+ MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
+ mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE());
+ mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE());
+ mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */
+ mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */
+ mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */
+ mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */
+
+ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1));
+ mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */
+ mrb_define_method(mrb, cls, "new", mrb_instance_new, MRB_ARGS_ANY()); /* 15.2.3.3.3 */
+ mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
+ mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1));
+
+ MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
+ mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.16 */
+ mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.17 */
+ mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
+ mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
+ mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
+ mrb_define_method(mrb, mod, "prepended", mrb_bob_init, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "prepend_features", mrb_mod_prepend_features, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
+ mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
+ mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */
+ mrb_define_method(mrb, mod, "included", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */
+ mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, MRB_ARGS_NONE()); /* 15.2.2.4.30 */
+ mrb_define_method(mrb, mod, "initialize", mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */
+ mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */
+ mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
+ mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */
+ mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY());
+ mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */
+ mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */
+ mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */
+ mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
+ mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
+ mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */
+ mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */
+ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */
+ mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, MRB_ARGS_NONE()); /* 15.2.2.4.9 */
+ mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
+ mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */
+ mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */
+ mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */
+ mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_OPT(1)); /* 15.2.2.4.24 */
+ mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
+ mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,1));
+ mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */
+ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */
+ mrb_define_class_method(mrb, mod, "nesting", mrb_mod_s_nesting, MRB_ARGS_REQ(0)); /* 15.2.2.3.2 */
+
+ mrb_undef_method(mrb, cls, "append_features");
+ mrb_undef_method(mrb, cls, "extend_object");
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/codedump.c b/web/server/h2o/libh2o/deps/mruby/src/codedump.c
new file mode 100644
index 00000000..e3a33419
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/codedump.c
@@ -0,0 +1,474 @@
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
+#include <mruby/opcode.h>
+#include <mruby/string.h>
+#include <mruby/proc.h>
+
+#ifndef MRB_DISABLE_STDIO
+static int
+print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre)
+{
+ size_t i;
+
+ if (n == 0) return 0;
+
+ for (i=0; i+1<irep->nlocals; i++) {
+ if (irep->lv[i].r == n) {
+ mrb_sym sym = irep->lv[i].name;
+ if (pre) printf(" ");
+ printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#define RA 1
+#define RB 2
+#define RAB 3
+
+static void
+print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r)
+{
+ int pre = 0;
+
+ if (!irep->lv
+ || ((!(r & RA) || GETARG_A(c) >= irep->nlocals)
+ && (!(r & RB) || GETARG_B(c) >= irep->nlocals))) {
+ printf("\n");
+ return;
+ }
+ printf("\t; ");
+ if (r & RA) {
+ pre = print_r(mrb, irep, GETARG_A(c), 0);
+ }
+ if (r & RB) {
+ print_r(mrb, irep, GETARG_B(c), pre);
+ }
+ printf("\n");
+}
+#endif
+
+static void
+codedump(mrb_state *mrb, mrb_irep *irep)
+{
+#ifndef MRB_DISABLE_STDIO
+ int i;
+ int ai;
+ mrb_code c;
+ const char *file = NULL, *next_file;
+ int32_t line;
+
+ if (!irep) return;
+ printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep,
+ irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
+
+ for (i = 0; i < (int)irep->ilen; i++) {
+ ai = mrb_gc_arena_save(mrb);
+
+ next_file = mrb_debug_get_filename(irep, i);
+ if (next_file && file != next_file) {
+ printf("file: %s\n", next_file);
+ file = next_file;
+ }
+ line = mrb_debug_get_line(irep, i);
+ if (line < 0) {
+ printf(" ");
+ }
+ else {
+ printf("%5d ", line);
+ }
+
+ printf("%03d ", i);
+ c = irep->iseq[i];
+ switch (GET_OPCODE(c)) {
+ case OP_NOP:
+ printf("OP_NOP\n");
+ break;
+ case OP_MOVE:
+ printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_LOADL:
+ {
+ mrb_value v = irep->pool[GETARG_Bx(c)];
+ mrb_value s = mrb_inspect(mrb, v);
+ printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
+ }
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_LOADI:
+ printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_LOADSYM:
+ printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_LOADNIL:
+ printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_LOADSELF:
+ printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_LOADT:
+ printf("OP_LOADT\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_LOADF:
+ printf("OP_LOADF\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_GETGLOBAL:
+ printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_SETGLOBAL:
+ printf("OP_SETGLOBAL\t:%s\tR%d\t",
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
+ GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_GETCONST:
+ printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_SETCONST:
+ printf("OP_SETCONST\t:%s\tR%d\t",
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
+ GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_GETMCNST:
+ printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_SETMCNST:
+ printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1,
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
+ GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_GETIV:
+ printf("OP_GETIV\tR%d\t%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_SETIV:
+ printf("OP_SETIV\t%s\tR%d",
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
+ GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_GETUPVAR:
+ printf("OP_GETUPVAR\tR%d\t%d\t%d",
+ GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_SETUPVAR:
+ printf("OP_SETUPVAR\tR%d\t%d\t%d",
+ GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_GETCV:
+ printf("OP_GETCV\tR%d\t%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_SETCV:
+ printf("OP_SETCV\t%s\tR%d",
+ mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
+ GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_JMP:
+ printf("OP_JMP\t%03d\n", i+GETARG_sBx(c));
+ break;
+ case OP_JMPIF:
+ printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
+ break;
+ case OP_JMPNOT:
+ printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
+ break;
+ case OP_SEND:
+ printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_SENDB:
+ printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_TAILCALL:
+ printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_SUPER:
+ printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
+ GETARG_C(c));
+ break;
+ case OP_ARGARY:
+ printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c),
+ (GETARG_Bx(c)>>10)&0x3f,
+ (GETARG_Bx(c)>>9)&0x1,
+ (GETARG_Bx(c)>>4)&0x1f,
+ (GETARG_Bx(c)>>0)&0xf);
+ print_lv(mrb, irep, c, RA);
+ break;
+
+ case OP_ENTER:
+ printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
+ (GETARG_Ax(c)>>18)&0x1f,
+ (GETARG_Ax(c)>>13)&0x1f,
+ (GETARG_Ax(c)>>12)&0x1,
+ (GETARG_Ax(c)>>7)&0x1f,
+ (GETARG_Ax(c)>>2)&0x1f,
+ (GETARG_Ax(c)>>1)&0x1,
+ GETARG_Ax(c) & 0x1);
+ break;
+ case OP_RETURN:
+ printf("OP_RETURN\tR%d", GETARG_A(c));
+ switch (GETARG_B(c)) {
+ case OP_R_NORMAL:
+ printf("\tnormal\t"); break;
+ case OP_R_RETURN:
+ printf("\treturn\t"); break;
+ case OP_R_BREAK:
+ printf("\tbreak\t"); break;
+ default:
+ printf("\tbroken\t"); break;
+ }
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_BLKPUSH:
+ printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c),
+ (GETARG_Bx(c)>>10)&0x3f,
+ (GETARG_Bx(c)>>9)&0x1,
+ (GETARG_Bx(c)>>4)&0x1f,
+ (GETARG_Bx(c)>>0)&0xf);
+ print_lv(mrb, irep, c, RA);
+ break;
+
+ case OP_LAMBDA:
+ printf("OP_LAMBDA\tR%d\tI(%+d)\t", GETARG_A(c), GETARG_b(c)+1);
+ switch (GETARG_c(c)) {
+ case OP_L_METHOD:
+ printf("method"); break;
+ case OP_L_BLOCK:
+ printf("block"); break;
+ case OP_L_LAMBDA:
+ printf("lambda"); break;
+ }
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_RANGE:
+ printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_METHOD:
+ printf("OP_METHOD\tR%d\t:%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+
+ case OP_ADD:
+ printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_ADDI:
+ printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_SUB:
+ printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_SUBI:
+ printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_MUL:
+ printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_DIV:
+ printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_LT:
+ printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_LE:
+ printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_GT:
+ printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_GE:
+ printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_EQ:
+ printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+
+ case OP_STOP:
+ printf("OP_STOP\n");
+ break;
+
+ case OP_ARRAY:
+ printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_ARYCAT:
+ printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_ARYPUSH:
+ printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_AREF:
+ printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_APOST:
+ printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_STRING:
+ {
+ mrb_value v = irep->pool[GETARG_Bx(c)];
+ mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
+ printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s));
+ }
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_STRCAT:
+ printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_HASH:
+ printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+
+ case OP_OCLASS:
+ printf("OP_OCLASS\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_CLASS:
+ printf("OP_CLASS\tR%d\t:%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_MODULE:
+ printf("OP_MODULE\tR%d\t:%s", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_EXEC:
+ printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1);
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_SCLASS:
+ printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c));
+ print_lv(mrb, irep, c, RAB);
+ break;
+ case OP_TCLASS:
+ printf("OP_TCLASS\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_ERR:
+ {
+ mrb_value v = irep->pool[GETARG_Bx(c)];
+ mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
+ printf("OP_ERR\t%s\n", RSTRING_PTR(s));
+ }
+ break;
+ case OP_EPUSH:
+ printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
+ break;
+ case OP_ONERR:
+ printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
+ break;
+ case OP_RESCUE:
+ {
+ int a = GETARG_A(c);
+ int b = GETARG_B(c);
+ int cnt = GETARG_C(c);
+
+ if (b == 0) {
+ printf("OP_RESCUE\tR%d\t\t%s", a, cnt ? "cont" : "");
+ print_lv(mrb, irep, c, RA);
+ break;
+ }
+ else {
+ printf("OP_RESCUE\tR%d\tR%d\t%s", a, b, cnt ? "cont" : "");
+ print_lv(mrb, irep, c, RAB);
+ break;
+ }
+ }
+ break;
+ case OP_RAISE:
+ printf("OP_RAISE\tR%d\t\t", GETARG_A(c));
+ print_lv(mrb, irep, c, RA);
+ break;
+ case OP_POPERR:
+ printf("OP_POPERR\t%d\t\t\n", GETARG_A(c));
+ break;
+ case OP_EPOP:
+ printf("OP_EPOP\t%d\n", GETARG_A(c));
+ break;
+
+ default:
+ printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
+ GETARG_A(c), GETARG_B(c), GETARG_C(c));
+ break;
+ }
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ printf("\n");
+#endif
+}
+
+static void
+codedump_recur(mrb_state *mrb, mrb_irep *irep)
+{
+ int i;
+
+ codedump(mrb, irep);
+ for (i=0; i<irep->rlen; i++) {
+ codedump_recur(mrb, irep->reps[i]);
+ }
+}
+
+void
+mrb_codedump_all(mrb_state *mrb, struct RProc *proc)
+{
+ codedump_recur(mrb, proc->body.irep);
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/compar.c b/web/server/h2o/libh2o/deps/mruby/src/compar.c
new file mode 100644
index 00000000..0032fc85
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/compar.c
@@ -0,0 +1,13 @@
+/*
+** compar.c - Comparable module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+
+void
+mrb_init_comparable(mrb_state *mrb)
+{
+ mrb_define_module(mrb, "Comparable"); /* 15.3.3 */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/crc.c b/web/server/h2o/libh2o/deps/mruby/src/crc.c
new file mode 100644
index 00000000..290b2ca0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/crc.c
@@ -0,0 +1,39 @@
+/*
+** crc.c - calculate CRC
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <limits.h>
+#include <stdint.h>
+#include <stddef.h>
+
+/* Calculate CRC (CRC-16-CCITT)
+**
+** 0000_0000_0000_0000_0000_0000_0000_0000
+** ^|------- CRC -------|- work --|
+** carry
+*/
+#define CRC_16_CCITT 0x11021ul /* x^16+x^12+x^5+1 */
+#define CRC_XOR_PATTERN (CRC_16_CCITT << 8)
+#define CRC_CARRY_BIT (0x01000000)
+
+uint16_t
+calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc)
+{
+ size_t ibyte;
+ uint32_t ibit;
+ uint32_t crcwk = crc << 8;
+
+ for (ibyte = 0; ibyte < nbytes; ibyte++) {
+ crcwk |= *src++;
+ for (ibit = 0; ibit < CHAR_BIT; ibit++) {
+ crcwk <<= 1;
+ if (crcwk & CRC_CARRY_BIT) {
+ crcwk ^= CRC_XOR_PATTERN;
+ }
+ }
+ }
+ return (uint16_t)(crcwk >> 8);
+}
+
diff --git a/web/server/h2o/libh2o/deps/mruby/src/debug.c b/web/server/h2o/libh2o/deps/mruby/src/debug.c
new file mode 100644
index 00000000..e55f11d4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/debug.c
@@ -0,0 +1,217 @@
+#include <string.h>
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
+
+static mrb_irep_debug_info_file*
+get_file(mrb_irep_debug_info *info, uint32_t pc)
+{
+ mrb_irep_debug_info_file **ret;
+ int32_t count;
+
+ if (pc >= info->pc_count) { return NULL; }
+ /* get upper bound */
+ ret = info->files;
+ count = info->flen;
+ while (count > 0) {
+ int32_t step = count / 2;
+ mrb_irep_debug_info_file **it = ret + step;
+ if (!(pc < (*it)->start_pos)) {
+ ret = it + 1;
+ count -= step + 1;
+ }
+ else { count = step; }
+ }
+
+ --ret;
+
+ /* check returning file exists inside debug info */
+ mrb_assert(info->files <= ret && ret < (info->files + info->flen));
+ /* check pc is within the range of returning file */
+ mrb_assert((*ret)->start_pos <= pc &&
+ pc < (((ret + 1 - info->files) < info->flen)
+ ? (*(ret+1))->start_pos : info->pc_count));
+
+ return *ret;
+}
+
+static mrb_debug_line_type
+select_line_type(const uint16_t *lines, size_t lines_len)
+{
+ size_t line_count = 0;
+ int prev_line = -1;
+ size_t i;
+ for (i = 0; i < lines_len; ++i) {
+ if (lines[i] != prev_line) {
+ ++line_count;
+ }
+ }
+ return (sizeof(uint16_t) * lines_len) <= (sizeof(mrb_irep_debug_info_line) * line_count)
+ ? mrb_debug_line_ary : mrb_debug_line_flat_map;
+}
+
+MRB_API char const*
+mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc)
+{
+ if (irep && pc >= 0 && pc < irep->ilen) {
+ mrb_irep_debug_info_file* f = NULL;
+ if (!irep->debug_info) { return irep->filename; }
+ else if ((f = get_file(irep->debug_info, (uint32_t)pc))) {
+ return f->filename;
+ }
+ }
+ return NULL;
+}
+
+MRB_API int32_t
+mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc)
+{
+ if (irep && pc >= 0 && pc < irep->ilen) {
+ mrb_irep_debug_info_file* f = NULL;
+ if (!irep->debug_info) {
+ return irep->lines? irep->lines[pc] : -1;
+ }
+ else if ((f = get_file(irep->debug_info, (uint32_t)pc))) {
+ switch (f->line_type) {
+ case mrb_debug_line_ary:
+ mrb_assert(f->start_pos <= pc && pc < (f->start_pos + f->line_entry_count));
+ return f->lines.ary[pc - f->start_pos];
+
+ case mrb_debug_line_flat_map: {
+ /* get upper bound */
+ mrb_irep_debug_info_line *ret = f->lines.flat_map;
+ uint32_t count = f->line_entry_count;
+ while (count > 0) {
+ int32_t step = count / 2;
+ mrb_irep_debug_info_line *it = ret + step;
+ if (!(pc < it->start_pos)) {
+ ret = it + 1;
+ count -= step + 1;
+ }
+ else { count = step; }
+ }
+
+ --ret;
+
+ /* check line entry pointer range */
+ mrb_assert(f->lines.flat_map <= ret && ret < (f->lines.flat_map + f->line_entry_count));
+ /* check pc range */
+ mrb_assert(ret->start_pos <= pc &&
+ pc < (((uint32_t)(ret + 1 - f->lines.flat_map) < f->line_entry_count)
+ ? (ret+1)->start_pos : irep->debug_info->pc_count));
+
+ return ret->line;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+MRB_API mrb_irep_debug_info*
+mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep)
+{
+ static const mrb_irep_debug_info initial = { 0, 0, NULL };
+ mrb_irep_debug_info *ret;
+
+ mrb_assert(!irep->debug_info);
+ ret = (mrb_irep_debug_info *)mrb_malloc(mrb, sizeof(*ret));
+ *ret = initial;
+ irep->debug_info = ret;
+ return ret;
+}
+
+MRB_API mrb_irep_debug_info_file*
+mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
+ uint32_t start_pos, uint32_t end_pos)
+{
+ mrb_irep_debug_info *info;
+ mrb_irep_debug_info_file *ret;
+ uint32_t file_pc_count;
+ size_t fn_len;
+ mrb_int len;
+ uint32_t i;
+
+ if (!irep->debug_info) { return NULL; }
+
+ mrb_assert(irep->filename);
+ mrb_assert(irep->lines);
+
+ info = irep->debug_info;
+
+ if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) {
+ return NULL;
+ }
+
+ ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret));
+ info->files =
+ (mrb_irep_debug_info_file**)(
+ info->files
+ ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
+ : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*)));
+ info->files[info->flen++] = ret;
+
+ file_pc_count = end_pos - start_pos;
+
+ ret->start_pos = start_pos;
+ info->pc_count = end_pos;
+
+ fn_len = strlen(irep->filename);
+ ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len);
+ len = 0;
+ ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len);
+
+ ret->line_type = select_line_type(irep->lines + start_pos, end_pos - start_pos);
+ ret->lines.ptr = NULL;
+
+ switch (ret->line_type) {
+ case mrb_debug_line_ary:
+ ret->line_entry_count = file_pc_count;
+ ret->lines.ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
+ for (i = 0; i < file_pc_count; ++i) {
+ ret->lines.ary[i] = irep->lines[start_pos + i];
+ }
+ break;
+
+ case mrb_debug_line_flat_map: {
+ uint16_t prev_line = 0;
+ mrb_irep_debug_info_line m;
+ ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
+ ret->line_entry_count = 0;
+ for (i = 0; i < file_pc_count; ++i) {
+ if (irep->lines[start_pos + i] == prev_line) { continue; }
+
+ ret->lines.flat_map = (mrb_irep_debug_info_line*)mrb_realloc(
+ mrb, ret->lines.flat_map,
+ sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
+ m.start_pos = start_pos + i;
+ m.line = irep->lines[start_pos + i];
+ ret->lines.flat_map[ret->line_entry_count] = m;
+
+ /* update */
+ ++ret->line_entry_count;
+ prev_line = irep->lines[start_pos + i];
+ }
+ } break;
+
+ default: mrb_assert(0); break;
+ }
+
+ return ret;
+}
+
+MRB_API void
+mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)
+{
+ uint32_t i;
+
+ if (!d) { return; }
+
+ for (i = 0; i < d->flen; ++i) {
+ mrb_assert(d->files[i]);
+ mrb_free(mrb, d->files[i]->lines.ptr);
+ mrb_free(mrb, d->files[i]);
+ }
+ mrb_free(mrb, d->files);
+ mrb_free(mrb, d);
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/dump.c b/web/server/h2o/libh2o/deps/mruby/src/dump.c
new file mode 100644
index 00000000..d479a1a4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/dump.c
@@ -0,0 +1,1100 @@
+/*
+** dump.c - mruby binary dumper (mrbc binary format)
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <string.h>
+#include <limits.h>
+#include <mruby/dump.h>
+#include <mruby/string.h>
+#include <mruby/irep.h>
+#include <mruby/numeric.h>
+#include <mruby/debug.h>
+
+#define FLAG_BYTEORDER_NATIVE 2
+#define FLAG_BYTEORDER_NONATIVE 0
+
+#ifdef MRB_USE_FLOAT
+#define MRB_FLOAT_FMT "%.8e"
+#else
+#define MRB_FLOAT_FMT "%.16e"
+#endif
+
+static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep);
+
+#if UINT32_MAX > SIZE_MAX
+# error This code cannot be built on your environment.
+#endif
+
+static size_t
+write_padding(uint8_t *buf)
+{
+ const size_t align = MRB_DUMP_ALIGNMENT;
+ size_t pad_len = -(intptr_t)buf & (align-1);
+ if (pad_len > 0) {
+ memset(buf, 0, pad_len);
+ }
+ return pad_len;
+}
+
+static size_t
+get_irep_header_size(mrb_state *mrb)
+{
+ size_t size = 0;
+
+ size += sizeof(uint32_t) * 1;
+ size += sizeof(uint16_t) * 3;
+
+ return size;
+}
+
+static ptrdiff_t
+write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
+{
+ uint8_t *cur = buf;
+
+ cur += uint32_to_bin((uint32_t)get_irep_record_size_1(mrb, irep), cur); /* record size */
+ cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */
+ cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */
+ cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */
+
+ return cur - buf;
+}
+
+
+static size_t
+get_iseq_block_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+
+ size += sizeof(uint32_t); /* ilen */
+ size += sizeof(uint32_t); /* max padding */
+ size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */
+
+ return size;
+}
+
+static ptrdiff_t
+write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags)
+{
+ uint8_t *cur = buf;
+ int iseq_no;
+
+ cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */
+ cur += write_padding(cur);
+ switch (flags & DUMP_ENDIAN_NAT) {
+ case DUMP_ENDIAN_BIG:
+ if (bigendian_p()) goto native;
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */
+ }
+ break;
+ case DUMP_ENDIAN_LIL:
+ if (!bigendian_p()) goto native;
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint32l_to_bin(irep->iseq[iseq_no], cur); /* opcode */
+ }
+ break;
+
+ native:
+ case DUMP_ENDIAN_NAT:
+ memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code));
+ cur += irep->ilen * sizeof(mrb_code);
+ break;
+ }
+
+ return cur - buf;
+}
+
+
+static size_t
+get_pool_block_size(mrb_state *mrb, mrb_irep *irep)
+{
+ int pool_no;
+ size_t size = 0;
+ mrb_value str;
+
+ size += sizeof(uint32_t); /* plen */
+ size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */
+
+ for (pool_no = 0; pool_no < irep->plen; pool_no++) {
+ int ai = mrb_gc_arena_save(mrb);
+
+ switch (mrb_type(irep->pool[pool_no])) {
+ case MRB_TT_FIXNUM:
+ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ {
+ mrb_int len = RSTRING_LEN(str);
+ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
+ size += (size_t)len;
+ }
+ break;
+
+ case MRB_TT_FLOAT:
+ str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT);
+ {
+ mrb_int len = RSTRING_LEN(str);
+ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
+ size += (size_t)len;
+ }
+ break;
+
+ case MRB_TT_STRING:
+ {
+ mrb_int len = RSTRING_LEN(irep->pool[pool_no]);
+ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
+ size += (size_t)len;
+ }
+ break;
+
+ default:
+ break;
+ }
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ return size;
+}
+
+static ptrdiff_t
+write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
+{
+ int pool_no;
+ uint8_t *cur = buf;
+ uint16_t len;
+ mrb_value str;
+ const char *char_ptr;
+
+ cur += uint32_to_bin(irep->plen, cur); /* number of pool */
+
+ for (pool_no = 0; pool_no < irep->plen; pool_no++) {
+ int ai = mrb_gc_arena_save(mrb);
+
+ switch (mrb_type(irep->pool[pool_no])) {
+ case MRB_TT_FIXNUM:
+ cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */
+ str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10);
+ break;
+
+ case MRB_TT_FLOAT:
+ cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */
+ str = mrb_float_to_str(mrb, irep->pool[pool_no], MRB_FLOAT_FMT);
+ break;
+
+ case MRB_TT_STRING:
+ cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */
+ str = irep->pool[pool_no];
+ break;
+
+ default:
+ continue;
+ }
+
+ char_ptr = RSTRING_PTR(str);
+ {
+ mrb_int tlen = RSTRING_LEN(str);
+ mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX);
+ len = (uint16_t)tlen;
+ }
+
+ cur += uint16_to_bin(len, cur); /* data length */
+ memcpy(cur, char_ptr, (size_t)len);
+ cur += len;
+
+ mrb_gc_arena_restore(mrb, ai);
+ }
+
+ return cur - buf;
+}
+
+
+static size_t
+get_syms_block_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+ int sym_no;
+ mrb_int len;
+
+ size += sizeof(uint32_t); /* slen */
+ for (sym_no = 0; sym_no < irep->slen; sym_no++) {
+ size += sizeof(uint16_t); /* snl(n) */
+ if (irep->syms[sym_no] != 0) {
+ mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
+ size += len + 1; /* sn(n) + null char */
+ }
+ }
+
+ return size;
+}
+
+static ptrdiff_t
+write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf)
+{
+ int sym_no;
+ uint8_t *cur = buf;
+ const char *name;
+
+ cur += uint32_to_bin(irep->slen, cur); /* number of symbol */
+
+ for (sym_no = 0; sym_no < irep->slen; sym_no++) {
+ if (irep->syms[sym_no] != 0) {
+ mrb_int len;
+
+ name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len);
+
+ mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX);
+ cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */
+ memcpy(cur, name, len); /* symbol name */
+ cur += (uint16_t)len;
+ *cur++ = '\0';
+ }
+ else {
+ cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */
+ }
+ }
+
+ return cur - buf;
+}
+
+static size_t
+get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+
+ size += get_irep_header_size(mrb);
+ size += get_iseq_block_size(mrb, irep);
+ size += get_pool_block_size(mrb, irep);
+ size += get_syms_block_size(mrb, irep);
+ return size;
+}
+
+static size_t
+get_irep_record_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+ int irep_no;
+
+ size = get_irep_record_size_1(mrb, irep);
+ for (irep_no = 0; irep_no < irep->rlen; irep_no++) {
+ size += get_irep_record_size(mrb, irep->reps[irep_no]);
+ }
+ return size;
+}
+
+static int
+write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags)
+{
+ int i;
+ uint8_t *src = bin;
+
+ if (irep == NULL) {
+ return MRB_DUMP_INVALID_IREP;
+ }
+
+ *irep_record_size = get_irep_record_size_1(mrb, irep);
+ if (*irep_record_size == 0) {
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
+
+ bin += write_irep_header(mrb, irep, bin);
+ bin += write_iseq_block(mrb, irep, bin, flags);
+ bin += write_pool_block(mrb, irep, bin);
+ bin += write_syms_block(mrb, irep, bin);
+
+ for (i = 0; i < irep->rlen; i++) {
+ int result;
+ size_t rsize;
+
+ result = write_irep_record(mrb, irep->reps[i], bin, &rsize, flags);
+ if (result != MRB_DUMP_OK) {
+ return result;
+ }
+ bin += rsize;
+ }
+ *irep_record_size = bin - src;
+ return MRB_DUMP_OK;
+}
+
+static uint32_t
+write_footer(mrb_state *mrb, uint8_t *bin)
+{
+ struct rite_binary_footer footer;
+
+ memcpy(footer.section_ident, RITE_BINARY_EOF, sizeof(footer.section_ident));
+ uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size);
+ memcpy(bin, &footer, sizeof(struct rite_binary_footer));
+
+ return sizeof(struct rite_binary_footer);
+}
+
+
+static int
+write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
+{
+ struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin;
+
+ memcpy(header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(header->section_ident));
+
+ mrb_assert_int_fit(size_t, section_size, uint32_t, UINT32_MAX);
+ uint32_to_bin((uint32_t)section_size, header->section_size);
+ memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version));
+
+ return MRB_DUMP_OK;
+}
+
+static int
+write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags)
+{
+ int result;
+ size_t rsize = 0;
+ uint8_t *cur = bin;
+
+ if (mrb == NULL || bin == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ cur += sizeof(struct rite_section_irep_header);
+
+ result = write_irep_record(mrb, irep, cur, &rsize, flags);
+ if (result != MRB_DUMP_OK) {
+ return result;
+ }
+ *len_p = cur - bin + rsize;
+ write_section_irep_header(mrb, *len_p, bin);
+
+ return MRB_DUMP_OK;
+}
+
+static int
+write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
+{
+ struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
+
+ memcpy(header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(header->section_ident));
+ uint32_to_bin((uint32_t)section_size, header->section_size);
+
+ return MRB_DUMP_OK;
+}
+
+static size_t
+get_lineno_record_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t size = 0;
+
+ size += sizeof(uint32_t); /* record size */
+ size += sizeof(uint16_t); /* filename size */
+ if (irep->filename) {
+ size += strlen(irep->filename); /* filename */
+ }
+ size += sizeof(uint32_t); /* niseq */
+ if (irep->lines) {
+ size += sizeof(uint16_t) * irep->ilen; /* lineno */
+ }
+
+ return size;
+}
+
+static size_t
+write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
+{
+ uint8_t *cur = bin;
+ int iseq_no;
+ size_t filename_len;
+ ptrdiff_t diff;
+
+ cur += sizeof(uint32_t); /* record size */
+
+ if (irep->filename) {
+ filename_len = strlen(irep->filename);
+ }
+ else {
+ filename_len = 0;
+ }
+ mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX);
+ cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */
+
+ if (filename_len) {
+ memcpy(cur, irep->filename, filename_len);
+ cur += filename_len; /* filename */
+ }
+
+ if (irep->lines) {
+ mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX);
+ cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */
+ for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
+ cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */
+ }
+ }
+ else {
+ cur += uint32_to_bin(0, cur); /* niseq */
+ }
+
+ diff = cur - bin;
+ mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX);
+
+ uint32_to_bin((uint32_t)diff, bin); /* record size */
+
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ return (size_t)diff;
+}
+
+static size_t
+write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin)
+{
+ size_t rlen, size = 0;
+ int i;
+
+ rlen = write_lineno_record_1(mrb, irep, bin);
+ bin += rlen;
+ size += rlen;
+ for (i=0; i<irep->rlen; i++) {
+ rlen = write_lineno_record(mrb, irep, bin);
+ bin += rlen;
+ size += rlen;
+ }
+ return size;
+}
+
+static int
+write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin)
+{
+ size_t section_size = 0;
+ size_t rlen = 0; /* size of irep record */
+ uint8_t *cur = bin;
+
+ if (mrb == NULL || bin == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ cur += sizeof(struct rite_section_lineno_header);
+ section_size += sizeof(struct rite_section_lineno_header);
+
+ rlen = write_lineno_record(mrb, irep, cur);
+ section_size += rlen;
+
+ write_section_lineno_header(mrb, section_size, bin);
+
+ return MRB_DUMP_OK;
+}
+
+static size_t
+get_debug_record_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t ret = 0;
+ uint16_t f_idx;
+ int i;
+
+ ret += sizeof(uint32_t); /* record size */
+ ret += sizeof(uint16_t); /* file count */
+
+ for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
+ mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx];
+
+ ret += sizeof(uint32_t); /* position */
+ ret += sizeof(uint16_t); /* filename index */
+
+ /* lines */
+ ret += sizeof(uint32_t); /* entry count */
+ ret += sizeof(uint8_t); /* line type */
+ switch (file->line_type) {
+ case mrb_debug_line_ary:
+ ret += sizeof(uint16_t) * (size_t)(file->line_entry_count);
+ break;
+
+ case mrb_debug_line_flat_map:
+ ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count);
+ break;
+
+ default: mrb_assert(0); break;
+ }
+ }
+ for (i=0; i<irep->rlen; i++) {
+ ret += get_debug_record_size(mrb, irep->reps[i]);
+ }
+
+ return ret;
+}
+
+static int
+find_filename_index(const mrb_sym *ary, int ary_len, mrb_sym s)
+{
+ int i;
+
+ for (i = 0; i < ary_len; ++i) {
+ if (ary[i] == s) { return i; }
+ }
+ return -1;
+}
+
+static size_t
+get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp)
+{
+ mrb_sym *filenames = *fp;
+ size_t size = 0;
+ mrb_irep_debug_info *di = irep->debug_info;
+ int i;
+
+ mrb_assert(lp);
+ for (i = 0; i < di->flen; ++i) {
+ mrb_irep_debug_info_file *file;
+ mrb_int filename_len;
+
+ file = di->files[i];
+ if (find_filename_index(filenames, *lp, file->filename_sym) == -1) {
+ /* register filename */
+ *lp += 1;
+ *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp));
+ filenames[*lp - 1] = file->filename_sym;
+
+ /* filename */
+ mrb_sym2name_len(mrb, file->filename_sym, &filename_len);
+ size += sizeof(uint16_t) + (size_t)filename_len;
+ }
+ }
+ for (i=0; i<irep->rlen; i++) {
+ size += get_filename_table_size(mrb, irep->reps[i], fp, lp);
+ }
+ return size;
+}
+
+static size_t
+write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len)
+{
+ uint8_t *cur;
+ uint16_t f_idx;
+ ptrdiff_t ret;
+
+ cur = bin + sizeof(uint32_t); /* skip record size */
+ cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */
+
+ for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
+ int filename_idx;
+ const mrb_irep_debug_info_file *file = irep->debug_info->files[f_idx];
+
+ /* position */
+ cur += uint32_to_bin(file->start_pos, cur);
+
+ /* filename index */
+ filename_idx = find_filename_index(filenames, filenames_len,
+ file->filename_sym);
+ mrb_assert_int_fit(int, filename_idx, uint16_t, UINT16_MAX);
+ cur += uint16_to_bin((uint16_t)filename_idx, cur);
+
+ /* lines */
+ cur += uint32_to_bin(file->line_entry_count, cur);
+ cur += uint8_to_bin(file->line_type, cur);
+ switch (file->line_type) {
+ case mrb_debug_line_ary: {
+ uint32_t l;
+ for (l = 0; l < file->line_entry_count; ++l) {
+ cur += uint16_to_bin(file->lines.ary[l], cur);
+ }
+ } break;
+
+ case mrb_debug_line_flat_map: {
+ uint32_t line;
+ for (line = 0; line < file->line_entry_count; ++line) {
+ cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur);
+ cur += uint16_to_bin(file->lines.flat_map[line].line, cur);
+ }
+ } break;
+
+ default: mrb_assert(0); break;
+ }
+ }
+
+ ret = cur - bin;
+ mrb_assert_int_fit(ptrdiff_t, ret, uint32_t, UINT32_MAX);
+ uint32_to_bin((uint32_t)ret, bin);
+
+ mrb_assert_int_fit(ptrdiff_t, ret, size_t, SIZE_MAX);
+ return (size_t)ret;
+}
+
+static size_t
+write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len)
+{
+ size_t size, len;
+ int irep_no;
+
+ size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len);
+ bin += len;
+ for (irep_no = 0; irep_no < irep->rlen; irep_no++) {
+ len = write_debug_record(mrb, irep->reps[irep_no], bin, filenames, filenames_len);
+ bin += len;
+ size += len;
+ }
+
+ mrb_assert(size == get_debug_record_size(mrb, irep));
+ return size;
+}
+
+static int
+write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len)
+{
+ size_t section_size = 0;
+ const uint8_t *bin = cur;
+ struct rite_section_debug_header *header;
+ size_t dlen;
+ uint16_t i;
+ char const *sym; mrb_int sym_len;
+
+ if (mrb == NULL || cur == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ header = (struct rite_section_debug_header *)bin;
+ cur += sizeof(struct rite_section_debug_header);
+ section_size += sizeof(struct rite_section_debug_header);
+
+ /* filename table */
+ cur += uint16_to_bin(filenames_len, cur);
+ section_size += sizeof(uint16_t);
+ for (i = 0; i < filenames_len; ++i) {
+ sym = mrb_sym2name_len(mrb, filenames[i], &sym_len);
+ mrb_assert(sym);
+ cur += uint16_to_bin(sym_len, cur);
+ memcpy(cur, sym, sym_len);
+ cur += sym_len;
+ section_size += sizeof(uint16_t) + sym_len;
+ }
+
+ /* debug records */
+ dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len);
+ section_size += dlen;
+
+ memcpy(header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(header->section_ident));
+ mrb_assert(section_size <= INT32_MAX);
+ uint32_to_bin((uint32_t)section_size, header->section_size);
+
+ return MRB_DUMP_OK;
+}
+
+static void
+create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32_t *syms_len)
+{
+ int i;
+
+ if (*syms == NULL) {
+ *syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * 1);
+ }
+
+ for (i = 0; i + 1 < irep->nlocals; ++i) {
+ mrb_sym const name = irep->lv[i].name;
+ if (name == 0) continue;
+ if (find_filename_index(*syms, *syms_len, name) != -1) continue;
+
+ ++(*syms_len);
+ *syms = (mrb_sym*)mrb_realloc(mrb, *syms, sizeof(mrb_sym) * (*syms_len));
+ (*syms)[*syms_len - 1] = name;
+ }
+
+ for (i = 0; i < irep->rlen; ++i) {
+ create_lv_sym_table(mrb, irep->reps[i], syms, syms_len);
+ }
+}
+
+static int
+write_lv_sym_table(mrb_state *mrb, uint8_t **start, mrb_sym const *syms, uint32_t syms_len)
+{
+ uint8_t *cur = *start;
+ uint32_t i;
+ const char *str;
+ mrb_int str_len;
+
+ cur += uint32_to_bin(syms_len, cur);
+
+ for (i = 0; i < syms_len; ++i) {
+ str = mrb_sym2name_len(mrb, syms[i], &str_len);
+ cur += uint16_to_bin(str_len, cur);
+ memcpy(cur, str, str_len);
+ cur += str_len;
+ }
+
+ *start = cur;
+
+ return MRB_DUMP_OK;
+}
+
+static int
+write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym const *syms, uint32_t syms_len)
+{
+ uint8_t *cur = *start;
+ int i;
+
+ for (i = 0; i + 1 < irep->nlocals; ++i) {
+ if (irep->lv[i].name == 0) {
+ cur += uint16_to_bin(RITE_LV_NULL_MARK, cur);
+ cur += uint16_to_bin(0, cur);
+ }
+ else {
+ int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i].name);
+ mrb_assert(sym_idx != -1); /* local variable name must be in syms */
+
+ cur += uint16_to_bin(sym_idx, cur);
+ cur += uint16_to_bin(irep->lv[i].r, cur);
+ }
+ }
+
+ for (i = 0; i < irep->rlen; ++i) {
+ write_lv_record(mrb, irep->reps[i], &cur, syms, syms_len);
+ }
+
+ *start = cur;
+
+ return MRB_DUMP_OK;
+}
+
+static size_t
+get_lv_record_size(mrb_state *mrb, mrb_irep *irep)
+{
+ size_t ret = 0;
+ int i;
+
+ ret += (sizeof(uint16_t) + sizeof(uint16_t)) * (irep->nlocals - 1);
+
+ for (i = 0; i < irep->rlen; ++i) {
+ ret += get_lv_record_size(mrb, irep->reps[i]);
+ }
+
+ return ret;
+}
+
+static size_t
+get_lv_section_size(mrb_state *mrb, mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len)
+{
+ size_t ret = 0, i;
+
+ ret += sizeof(uint32_t); /* syms_len */
+ ret += sizeof(uint16_t) * syms_len; /* symbol name lengths */
+ for (i = 0; i < syms_len; ++i) {
+ mrb_int str_len;
+ mrb_sym2name_len(mrb, syms[i], &str_len);
+ ret += str_len;
+ }
+
+ ret += get_lv_record_size(mrb, irep);
+
+ return ret;
+}
+
+static int
+write_section_lv(mrb_state *mrb, mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len)
+{
+ uint8_t *cur = start;
+ struct rite_section_lv_header *header;
+ ptrdiff_t diff;
+ int result = MRB_DUMP_OK;
+
+ if (mrb == NULL || cur == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ header = (struct rite_section_lv_header*)cur;
+ cur += sizeof(struct rite_section_lv_header);
+
+ result = write_lv_sym_table(mrb, &cur, syms, syms_len);
+ if (result != MRB_DUMP_OK) {
+ goto lv_section_exit;
+ }
+
+ result = write_lv_record(mrb, irep, &cur, syms, syms_len);
+ if (result != MRB_DUMP_OK) {
+ goto lv_section_exit;
+ }
+
+ memcpy(header->section_ident, RITE_SECTION_LV_IDENT, sizeof(header->section_ident));
+
+ diff = cur - start;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ uint32_to_bin((uint32_t)diff, header->section_size);
+
+lv_section_exit:
+ return result;
+}
+
+static int
+write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8_t flags)
+{
+ struct rite_binary_header *header = (struct rite_binary_header *)bin;
+ uint16_t crc;
+ uint32_t offset;
+
+ switch (flags & DUMP_ENDIAN_NAT) {
+ endian_big:
+ case DUMP_ENDIAN_BIG:
+ memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
+ break;
+ endian_little:
+ case DUMP_ENDIAN_LIL:
+ memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident));
+ break;
+
+ case DUMP_ENDIAN_NAT:
+ if (bigendian_p()) goto endian_big;
+ goto endian_little;
+ break;
+ }
+
+ memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
+ memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
+ memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
+ mrb_assert(binary_size <= UINT32_MAX);
+ uint32_to_bin((uint32_t)binary_size, header->binary_size);
+
+ offset = (uint32_t)((&(header->binary_crc[0]) - bin) + sizeof(uint16_t));
+ crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0);
+ uint16_to_bin(crc, header->binary_crc);
+
+ return MRB_DUMP_OK;
+}
+
+static mrb_bool
+is_debug_info_defined(mrb_irep *irep)
+{
+ int i;
+
+ if (!irep->debug_info) return FALSE;
+ for (i=0; i<irep->rlen; i++) {
+ if (!is_debug_info_defined(irep->reps[i])) return FALSE;
+ }
+ return TRUE;
+}
+
+static mrb_bool
+is_lv_defined(mrb_irep *irep)
+{
+ int i;
+
+ if (irep->lv) { return TRUE; }
+
+ for (i = 0; i < irep->rlen; ++i) {
+ if (is_lv_defined(irep->reps[i])) { return TRUE; }
+ }
+
+ return FALSE;
+}
+
+static uint8_t
+dump_flags(uint8_t flags, uint8_t native)
+{
+ if (native == FLAG_BYTEORDER_NATIVE) {
+ if ((flags & DUMP_ENDIAN_NAT) == 0) {
+ return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT;
+ }
+ return flags;
+ }
+ if ((flags & DUMP_ENDIAN_NAT) == 0) {
+ return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG;
+ }
+ return flags;
+}
+
+static int
+dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
+{
+ int result = MRB_DUMP_GENERAL_FAILURE;
+ size_t malloc_size;
+ size_t section_irep_size;
+ size_t section_lineno_size = 0, section_lv_size = 0;
+ uint8_t *cur = NULL;
+ mrb_bool const debug_info_defined = is_debug_info_defined(irep), lv_defined = is_lv_defined(irep);
+ mrb_sym *lv_syms = NULL; uint32_t lv_syms_len = 0;
+ mrb_sym *filenames = NULL; uint16_t filenames_len = 0;
+
+ if (mrb == NULL) {
+ *bin = NULL;
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
+
+ section_irep_size = sizeof(struct rite_section_irep_header);
+ section_irep_size += get_irep_record_size(mrb, irep);
+
+ /* DEBUG section size */
+ if (flags & DUMP_DEBUG_INFO) {
+ if (debug_info_defined) {
+ section_lineno_size += sizeof(struct rite_section_debug_header);
+ /* filename table */
+ filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) + 1);
+
+ /* filename table size */
+ section_lineno_size += sizeof(uint16_t);
+ section_lineno_size += get_filename_table_size(mrb, irep, &filenames, &filenames_len);
+
+ section_lineno_size += get_debug_record_size(mrb, irep);
+ }
+ else {
+ section_lineno_size += sizeof(struct rite_section_lineno_header);
+ section_lineno_size += get_lineno_record_size(mrb, irep);
+ }
+ }
+
+ if (lv_defined) {
+ section_lv_size += sizeof(struct rite_section_lv_header);
+ create_lv_sym_table(mrb, irep, &lv_syms, &lv_syms_len);
+ section_lv_size += get_lv_section_size(mrb, irep, lv_syms, lv_syms_len);
+ }
+
+ malloc_size = sizeof(struct rite_binary_header) +
+ section_irep_size + section_lineno_size + section_lv_size +
+ sizeof(struct rite_binary_footer);
+ cur = *bin = (uint8_t*)mrb_malloc(mrb, malloc_size);
+ cur += sizeof(struct rite_binary_header);
+
+ result = write_section_irep(mrb, irep, cur, &section_irep_size, flags);
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+ cur += section_irep_size;
+ *bin_size = sizeof(struct rite_binary_header) +
+ section_irep_size + section_lineno_size + section_lv_size +
+ sizeof(struct rite_binary_footer);
+
+ /* write DEBUG section */
+ if (flags & DUMP_DEBUG_INFO) {
+ if (debug_info_defined) {
+ result = write_section_debug(mrb, irep, cur, filenames, filenames_len);
+ }
+ else {
+ result = write_section_lineno(mrb, irep, cur);
+ }
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+ cur += section_lineno_size;
+ }
+
+ if (lv_defined) {
+ result = write_section_lv(mrb, irep, cur, lv_syms, lv_syms_len);
+ if (result != MRB_DUMP_OK) {
+ goto error_exit;
+ }
+ cur += section_lv_size;
+ }
+
+ write_footer(mrb, cur);
+ write_rite_binary_header(mrb, *bin_size, *bin, flags);
+
+error_exit:
+ if (result != MRB_DUMP_OK) {
+ mrb_free(mrb, *bin);
+ *bin = NULL;
+ }
+ mrb_free(mrb, lv_syms);
+ mrb_free(mrb, filenames);
+ return result;
+}
+
+int
+mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
+{
+ return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size);
+}
+
+#ifndef MRB_DISABLE_STDIO
+
+int
+mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
+{
+ uint8_t *bin = NULL;
+ size_t bin_size = 0;
+ int result;
+
+ if (fp == NULL) {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+
+ result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size);
+ if (result == MRB_DUMP_OK) {
+ if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
+ result = MRB_DUMP_WRITE_FAULT;
+ }
+ }
+
+ mrb_free(mrb, bin);
+ return result;
+}
+
+static mrb_bool
+dump_bigendian_p(uint8_t flags)
+{
+ switch (flags & DUMP_ENDIAN_NAT) {
+ case DUMP_ENDIAN_BIG:
+ return TRUE;
+ case DUMP_ENDIAN_LIL:
+ return FALSE;
+ default:
+ case DUMP_ENDIAN_NAT:
+ return bigendian_p();
+ }
+}
+
+int
+mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname)
+{
+ uint8_t *bin = NULL;
+ size_t bin_size = 0, bin_idx = 0;
+ int result;
+
+ if (fp == NULL || initname == NULL || initname[0] == '\0') {
+ return MRB_DUMP_INVALID_ARGUMENT;
+ }
+ flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE);
+ result = dump_irep(mrb, irep, flags, &bin, &bin_size);
+ if (result == MRB_DUMP_OK) {
+ if (!dump_bigendian_p(flags)) {
+ if (fprintf(fp, "/* dumped in little endian order.\n"
+ " use `mrbc -E` option for big endian CPU. */\n") < 0) {
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ }
+ else {
+ if (fprintf(fp, "/* dumped in big endian order.\n"
+ " use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) {
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ }
+ if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ if (fprintf(fp,
+ "extern const uint8_t %s[];\n"
+ "const uint8_t\n"
+ "#if defined __GNUC__\n"
+ "__attribute__((aligned(%u)))\n"
+ "#elif defined _MSC_VER\n"
+ "__declspec(align(%u))\n"
+ "#endif\n"
+ "%s[] = {",
+ initname,
+ (uint16_t)MRB_DUMP_ALIGNMENT, (uint16_t)MRB_DUMP_ALIGNMENT, initname) < 0) {
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ while (bin_idx < bin_size) {
+ if (bin_idx % 16 == 0) {
+ if (fputs("\n", fp) == EOF) {
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ }
+ if (fprintf(fp, "0x%02x,", bin[bin_idx++]) < 0) {
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ }
+ if (fputs("\n};\n", fp) == EOF) {
+ mrb_free(mrb, bin);
+ return MRB_DUMP_WRITE_FAULT;
+ }
+ }
+
+ mrb_free(mrb, bin);
+ return result;
+}
+
+#endif /* MRB_DISABLE_STDIO */
diff --git a/web/server/h2o/libh2o/deps/mruby/src/enum.c b/web/server/h2o/libh2o/deps/mruby/src/enum.c
new file mode 100644
index 00000000..adb815bf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/enum.c
@@ -0,0 +1,14 @@
+/*
+** enum.c - Enumerable module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+
+void
+mrb_init_enumerable(mrb_state *mrb)
+{
+ mrb_define_module(mrb, "Enumerable"); /* 15.3.2 */
+}
+
diff --git a/web/server/h2o/libh2o/deps/mruby/src/error.c b/web/server/h2o/libh2o/deps/mruby/src/error.c
new file mode 100644
index 00000000..2c4fd1a4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/error.c
@@ -0,0 +1,503 @@
+/*
+** error.c - Exception class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/irep.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/debug.h>
+#include <mruby/error.h>
+#include <mruby/class.h>
+#include <mruby/throw.h>
+
+MRB_API mrb_value
+mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len)
+{
+ mrb_value arg = mrb_str_new(mrb, ptr, len);
+ return mrb_obj_new(mrb, c, 1, &arg);
+}
+
+MRB_API mrb_value
+mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str)
+{
+ str = mrb_str_to_str(mrb, str);
+ return mrb_obj_new(mrb, c, 1, &str);
+}
+
+/*
+ * call-seq:
+ * Exception.new(msg = nil) -> exception
+ *
+ * Construct a new Exception object, optionally passing in
+ * a message.
+ */
+
+static mrb_value
+exc_initialize(mrb_state *mrb, mrb_value exc)
+{
+ mrb_value mesg;
+ mrb_int argc;
+ mrb_value *argv;
+
+ if (mrb_get_args(mrb, "|o*!", &mesg, &argv, &argc) >= 1) {
+ mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg);
+ }
+ return exc;
+}
+
+/*
+ * Document-method: exception
+ *
+ * call-seq:
+ * exc.exception(string) -> an_exception or exc
+ *
+ * With no argument, or if the argument is the same as the receiver,
+ * return the receiver. Otherwise, create a new
+ * exception object of the same class as the receiver, but with a
+ * message equal to <code>string</code>.
+ *
+ */
+
+static mrb_value
+exc_exception(mrb_state *mrb, mrb_value self)
+{
+ mrb_value exc;
+ mrb_value a;
+ int argc;
+
+ argc = mrb_get_args(mrb, "|o", &a);
+ if (argc == 0) return self;
+ if (mrb_obj_equal(mrb, self, a)) return self;
+ exc = mrb_obj_clone(mrb, self);
+ mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), a);
+
+ return exc;
+}
+
+/*
+ * call-seq:
+ * exception.to_s -> string
+ *
+ * Returns exception's message (or the name of the exception if
+ * no message is set).
+ */
+
+static mrb_value
+exc_to_s(mrb_state *mrb, mrb_value exc)
+{
+ mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
+ struct RObject *p;
+
+ if (!mrb_string_p(mesg)) {
+ return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc));
+ }
+ p = mrb_obj_ptr(mesg);
+ if (!p->c) {
+ p->c = mrb->string_class;
+ }
+ return mesg;
+}
+
+/*
+ * call-seq:
+ * exception.message -> string
+ *
+ * Returns the result of invoking <code>exception.to_s</code>.
+ * Normally this returns the exception's message or name.
+ */
+
+static mrb_value
+exc_message(mrb_state *mrb, mrb_value exc)
+{
+ return mrb_funcall(mrb, exc, "to_s", 0);
+}
+
+/*
+ * call-seq:
+ * exception.inspect -> string
+ *
+ * Returns this exception's file name, line number,
+ * message and class name.
+ * If file name or line number is not set,
+ * returns message and class name.
+ */
+
+static mrb_value
+exc_inspect(mrb_state *mrb, mrb_value exc)
+{
+ mrb_value str, mesg, file, line;
+ mrb_bool append_mesg;
+ const char *cname;
+
+ mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
+ file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file"));
+ line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line"));
+
+ append_mesg = !mrb_nil_p(mesg);
+ if (append_mesg) {
+ mesg = mrb_obj_as_string(mrb, mesg);
+ append_mesg = RSTRING_LEN(mesg) > 0;
+ }
+
+ cname = mrb_obj_classname(mrb, exc);
+ str = mrb_str_new_cstr(mrb, cname);
+ if (mrb_string_p(file) && mrb_fixnum_p(line)) {
+ if (append_mesg) {
+ str = mrb_format(mrb, "%S:%S: %S (%S)", file, line, mesg, str);
+ }
+ else {
+ str = mrb_format(mrb, "%S:%S: %S", file, line, str);
+ }
+ }
+ else if (append_mesg) {
+ str = mrb_format(mrb, "%S: %S", str, mesg);
+ }
+ return str;
+}
+
+void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc);
+
+static void
+set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
+{
+ if (!mrb_array_p(backtrace)) {
+ type_err:
+ mrb_raise(mrb, E_TYPE_ERROR, "backtrace must be Array of String");
+ }
+ else {
+ const mrb_value *p = RARRAY_PTR(backtrace);
+ const mrb_value *pend = p + RARRAY_LEN(backtrace);
+
+ while (p < pend) {
+ if (!mrb_string_p(*p)) goto type_err;
+ p++;
+ }
+ }
+ mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace);
+}
+
+static mrb_value
+exc_set_backtrace(mrb_state *mrb, mrb_value exc)
+{
+ mrb_value backtrace;
+
+ mrb_get_args(mrb, "o", &backtrace);
+ set_backtrace(mrb, exc, backtrace);
+ return backtrace;
+}
+
+static void
+exc_debug_info(mrb_state *mrb, struct RObject *exc)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+ mrb_code *pc = ci->pc;
+
+ while (ci >= mrb->c->cibase) {
+ mrb_code *err = ci->err;
+
+ if (!err && pc) err = pc - 1;
+ if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
+ mrb_irep *irep = ci->proc->body.irep;
+
+ int32_t const line = mrb_debug_get_line(irep, err - irep->iseq);
+ char const* file = mrb_debug_get_filename(irep, err - irep->iseq);
+ if (line != -1 && file) {
+ mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file));
+ mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line));
+ return;
+ }
+ }
+ pc = ci->pc;
+ ci--;
+ }
+}
+
+void
+mrb_exc_set(mrb_state *mrb, mrb_value exc)
+{
+ if (mrb_nil_p(exc)) {
+ mrb->exc = 0;
+ }
+ else {
+ mrb->exc = mrb_obj_ptr(exc);
+ if (!mrb->gc.out_of_memory) {
+ exc_debug_info(mrb, mrb->exc);
+ mrb_keep_backtrace(mrb, exc);
+ }
+ }
+}
+
+MRB_API mrb_noreturn void
+mrb_exc_raise(mrb_state *mrb, mrb_value exc)
+{
+ if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "exception object expected");
+ }
+ mrb_exc_set(mrb, exc);
+ if (!mrb->jmp) {
+ mrb_p(mrb, exc);
+ abort();
+ }
+ MRB_THROW(mrb->jmp);
+}
+
+MRB_API mrb_noreturn void
+mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg)
+{
+ mrb_exc_raise(mrb, mrb_exc_new_str(mrb, c, mrb_str_new_cstr(mrb, msg)));
+}
+
+MRB_API mrb_value
+mrb_vformat(mrb_state *mrb, const char *format, va_list ap)
+{
+ const char *p = format;
+ const char *b = p;
+ ptrdiff_t size;
+ mrb_value ary = mrb_ary_new_capa(mrb, 4);
+ int ai = mrb_gc_arena_save(mrb);
+
+ while (*p) {
+ const char c = *p++;
+
+ if (c == '%') {
+ if (*p == 'S') {
+ mrb_value val;
+
+ size = p - b - 1;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ val = va_arg(ap, mrb_value);
+ mrb_ary_push(mrb, ary, mrb_obj_as_string(mrb, val));
+ b = p + 1;
+ }
+ }
+ else if (c == '\\') {
+ if (*p) {
+ size = p - b - 1;
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, p, 1));
+ b = ++p;
+ }
+ else {
+ break;
+ }
+ }
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ if (b == format) {
+ return mrb_str_new_cstr(mrb, format);
+ }
+ else {
+ size = p - b;
+ if (size > 0) {
+ mrb_ary_push(mrb, ary, mrb_str_new(mrb, b, size));
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ return mrb_ary_join(mrb, ary, mrb_nil_value());
+ }
+}
+
+MRB_API mrb_value
+mrb_format(mrb_state *mrb, const char *format, ...)
+{
+ va_list ap;
+ mrb_value str;
+
+ va_start(ap, format);
+ str = mrb_vformat(mrb, format, ap);
+ va_end(ap);
+
+ return str;
+}
+
+static mrb_noreturn void
+raise_va(mrb_state *mrb, struct RClass *c, const char *fmt, va_list ap, int argc, mrb_value *argv)
+{
+ mrb_value mesg;
+
+ mesg = mrb_vformat(mrb, fmt, ap);
+ if (argv == NULL) {
+ argv = &mesg;
+ }
+ else {
+ argv[0] = mesg;
+ }
+ mrb_exc_raise(mrb, mrb_obj_new(mrb, c, argc+1, argv));
+}
+
+MRB_API mrb_noreturn void
+mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ raise_va(mrb, c, fmt, args, 0, NULL);
+ va_end(args);
+}
+
+MRB_API mrb_noreturn void
+mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...)
+{
+ mrb_value argv[2];
+ va_list args;
+
+ va_start(args, fmt);
+ argv[1] = mrb_symbol_value(id);
+ raise_va(mrb, E_NAME_ERROR, fmt, args, 1, argv);
+ va_end(args);
+}
+
+MRB_API void
+mrb_warn(mrb_state *mrb, const char *fmt, ...)
+{
+#ifndef MRB_DISABLE_STDIO
+ va_list ap;
+ mrb_value str;
+
+ va_start(ap, fmt);
+ str = mrb_vformat(mrb, fmt, ap);
+ fputs("warning: ", stderr);
+ fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr);
+ va_end(ap);
+#endif
+}
+
+MRB_API mrb_noreturn void
+mrb_bug(mrb_state *mrb, const char *fmt, ...)
+{
+#ifndef MRB_DISABLE_STDIO
+ va_list ap;
+ mrb_value str;
+
+ va_start(ap, fmt);
+ str = mrb_vformat(mrb, fmt, ap);
+ fputs("bug: ", stderr);
+ fwrite(RSTRING_PTR(str), RSTRING_LEN(str), 1, stderr);
+ va_end(ap);
+#endif
+ exit(EXIT_FAILURE);
+}
+
+MRB_API mrb_value
+mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv)
+{
+ mrb_value mesg;
+ int n;
+
+ mesg = mrb_nil_value();
+ switch (argc) {
+ case 0:
+ break;
+ case 1:
+ if (mrb_nil_p(argv[0]))
+ break;
+ if (mrb_string_p(argv[0])) {
+ mesg = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, argv[0]);
+ break;
+ }
+ n = 0;
+ goto exception_call;
+
+ case 2:
+ case 3:
+ n = 1;
+exception_call:
+ {
+ mrb_sym exc = mrb_intern_lit(mrb, "exception");
+ if (mrb_respond_to(mrb, argv[0], exc)) {
+ mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1);
+ }
+ else {
+ /* undef */
+ mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected");
+ }
+ }
+
+ break;
+ default:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc));
+ break;
+ }
+ if (argc > 0) {
+ if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class))
+ mrb_raise(mrb, mrb->eException_class, "exception object expected");
+ if (argc > 2)
+ set_backtrace(mrb, mesg, argv[2]);
+ }
+
+ return mesg;
+}
+
+MRB_API void
+mrb_sys_fail(mrb_state *mrb, const char *mesg)
+{
+ struct RClass *sce;
+ mrb_int no;
+
+ no = (mrb_int)errno;
+ if (mrb_class_defined(mrb, "SystemCallError")) {
+ sce = mrb_class_get(mrb, "SystemCallError");
+ if (mesg != NULL) {
+ mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg));
+ }
+ else {
+ mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no));
+ }
+ }
+ else {
+ mrb_raise(mrb, E_RUNTIME_ERROR, mesg);
+ }
+}
+
+MRB_API mrb_noreturn void
+mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...)
+{
+ mrb_value exc;
+ mrb_value argv[3];
+ va_list ap;
+
+ va_start(ap, fmt);
+ argv[0] = mrb_vformat(mrb, fmt, ap);
+ argv[1] = mrb_symbol_value(id);
+ argv[2] = args;
+ va_end(ap);
+ exc = mrb_obj_new(mrb, E_NOMETHOD_ERROR, 3, argv);
+ mrb_exc_raise(mrb, exc);
+}
+
+void
+mrb_init_exception(mrb_state *mrb)
+{
+ struct RClass *exception, *script_error, *stack_error, *nomem_error;
+
+ mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */
+ MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION);
+ mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_ANY());
+ mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_ANY());
+ mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_ANY());
+ mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE());
+ mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1));
+
+ mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */
+ mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */
+ script_error = mrb_define_class(mrb, "ScriptError", mrb->eException_class); /* 15.2.37 */
+ mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */
+ stack_error = mrb_define_class(mrb, "SystemStackError", exception);
+ mrb->stack_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, stack_error, "stack level too deep"));
+
+ nomem_error = mrb_define_class(mrb, "NoMemoryError", exception);
+ mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, nomem_error, "Out of memory"));
+#ifdef MRB_GC_FIXED_ARENA
+ mrb->arena_err = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, nomem_error, "arena overflow error"));
+#endif
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/error.h b/web/server/h2o/libh2o/deps/mruby/src/error.h
new file mode 100644
index 00000000..eb755ec7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/error.h
@@ -0,0 +1,3 @@
+/* this header file is to be removed soon.
+ added for compatibility purpose (1.0.0) */
+#include <mruby/error.h>
diff --git a/web/server/h2o/libh2o/deps/mruby/src/etc.c b/web/server/h2o/libh2o/deps/mruby/src/etc.c
new file mode 100644
index 00000000..9475ae30
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/etc.c
@@ -0,0 +1,234 @@
+/*
+** etc.c -
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/string.h>
+#include <mruby/data.h>
+#include <mruby/class.h>
+#include <mruby/re.h>
+#include <mruby/irep.h>
+
+MRB_API struct RData*
+mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type)
+{
+ struct RData *data;
+
+ data = (struct RData*)mrb_obj_alloc(mrb, MRB_TT_DATA, klass);
+ data->data = ptr;
+ data->type = type;
+
+ return data;
+}
+
+MRB_API void
+mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
+{
+ if (mrb_type(obj) != MRB_TT_DATA) {
+ mrb_check_type(mrb, obj, MRB_TT_DATA);
+ }
+ if (DATA_TYPE(obj) != type) {
+ const mrb_data_type *t2 = DATA_TYPE(obj);
+
+ if (t2) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
+ mrb_str_new_cstr(mrb, t2->struct_name), mrb_str_new_cstr(mrb, type->struct_name));
+ }
+ else {
+ struct RClass *c = mrb_class(mrb, obj);
+
+ mrb_raisef(mrb, E_TYPE_ERROR, "uninitialized %S (expected %S)",
+ mrb_obj_value(c), mrb_str_new_cstr(mrb, type->struct_name));
+ }
+ }
+}
+
+MRB_API void*
+mrb_data_check_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
+{
+ if (mrb_type(obj) != MRB_TT_DATA) {
+ return NULL;
+ }
+ if (DATA_TYPE(obj) != type) {
+ return NULL;
+ }
+ return DATA_PTR(obj);
+}
+
+MRB_API void*
+mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
+{
+ mrb_data_check_type(mrb, obj, type);
+ return DATA_PTR(obj);
+}
+
+MRB_API mrb_sym
+mrb_obj_to_sym(mrb_state *mrb, mrb_value name)
+{
+ mrb_sym id;
+
+ switch (mrb_type(name)) {
+ default:
+ name = mrb_check_string_type(mrb, name);
+ if (mrb_nil_p(name)) {
+ name = mrb_inspect(mrb, name);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", name);
+ }
+ /* fall through */
+ case MRB_TT_STRING:
+ name = mrb_str_intern(mrb, name);
+ /* fall through */
+ case MRB_TT_SYMBOL:
+ id = mrb_symbol(name);
+ }
+ return id;
+}
+
+MRB_API mrb_int
+mrb_float_id(mrb_float f)
+{
+ const char *p = (const char*)&f;
+ int len = sizeof(f);
+ mrb_int id = 0;
+
+ /* normalize -0.0 to 0.0 */
+ if (f == 0) f = 0.0;
+ while (len--) {
+ id = id*65599 + *p;
+ p++;
+ }
+ id = id + (id>>5);
+
+ return id;
+}
+
+MRB_API mrb_int
+mrb_obj_id(mrb_value obj)
+{
+ mrb_int tt = mrb_type(obj);
+
+#define MakeID2(p,t) (mrb_int)(((intptr_t)(p))^(t))
+#define MakeID(p) MakeID2(p,tt)
+
+ switch (tt) {
+ case MRB_TT_FREE:
+ case MRB_TT_UNDEF:
+ return MakeID(0); /* not define */
+ case MRB_TT_FALSE:
+ if (mrb_nil_p(obj))
+ return MakeID(1);
+ return MakeID(0);
+ case MRB_TT_TRUE:
+ return MakeID(1);
+ case MRB_TT_SYMBOL:
+ return MakeID(mrb_symbol(obj));
+ case MRB_TT_FIXNUM:
+ return MakeID2(mrb_float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT);
+ case MRB_TT_FLOAT:
+ return MakeID(mrb_float_id(mrb_float(obj)));
+ case MRB_TT_STRING:
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_ICLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_PROC:
+ case MRB_TT_ARRAY:
+ case MRB_TT_HASH:
+ case MRB_TT_RANGE:
+ case MRB_TT_EXCEPTION:
+ case MRB_TT_FILE:
+ case MRB_TT_DATA:
+ case MRB_TT_ISTRUCT:
+ default:
+ return MakeID(mrb_ptr(obj));
+ }
+}
+
+#ifdef MRB_WORD_BOXING
+MRB_API mrb_value
+mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
+{
+ mrb_value v;
+
+ v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class);
+ v.value.fp->f = f;
+ return v;
+}
+
+MRB_API mrb_value
+mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
+{
+ struct RFloat *nf = (struct RFloat *)mrb_malloc(mrb, sizeof(struct RFloat));
+ nf->tt = MRB_TT_FLOAT;
+ nf->c = mrb->float_class;
+ nf->f = f;
+ return mrb_obj_value(nf);
+}
+
+MRB_API mrb_value
+mrb_word_boxing_cptr_value(mrb_state *mrb, void *p)
+{
+ mrb_value v;
+
+ v.value.p = mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
+ v.value.vp->p = p;
+ return v;
+}
+#endif /* MRB_WORD_BOXING */
+
+MRB_API mrb_bool
+mrb_regexp_p(mrb_state *mrb, mrb_value v)
+{
+ if (mrb->flags & MRB_STATE_NO_REGEXP) {
+ return FALSE;
+ }
+ if ((mrb->flags & MRB_STATE_REGEXP) || mrb_class_defined(mrb, REGEXP_CLASS)) {
+ mrb->flags |= MRB_STATE_REGEXP;
+ return mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS));
+ }
+ else {
+ mrb->flags |= MRB_STATE_REGEXP;
+ mrb->flags |= MRB_STATE_NO_REGEXP;
+ }
+ return FALSE;
+}
+
+#if defined _MSC_VER && _MSC_VER < 1900
+
+#ifndef va_copy
+static void
+mrb_msvc_va_copy(va_list *dest, va_list src)
+{
+ *dest = src;
+}
+#define va_copy(dest, src) mrb_msvc_va_copy(&(dest), src)
+#endif
+
+MRB_API int
+mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg)
+{
+ int cnt;
+ va_list argcp;
+ va_copy(argcp, arg);
+ if (n == 0 || (cnt = _vsnprintf_s(s, n, _TRUNCATE, format, argcp)) < 0) {
+ cnt = _vscprintf(format, arg);
+ }
+ va_end(argcp);
+ return cnt;
+}
+
+MRB_API int
+mrb_msvc_snprintf(char *s, size_t n, const char *format, ...)
+{
+ va_list arg;
+ int ret;
+ va_start(arg, format);
+ ret = mrb_msvc_vsnprintf(s, n, format, arg);
+ va_end(arg);
+ return ret;
+}
+
+#endif /* defined _MSC_VER && _MSC_VER < 1900 */
diff --git a/web/server/h2o/libh2o/deps/mruby/src/ext/.gitkeep b/web/server/h2o/libh2o/deps/mruby/src/ext/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/ext/.gitkeep
diff --git a/web/server/h2o/libh2o/deps/mruby/src/fmt_fp.c b/web/server/h2o/libh2o/deps/mruby/src/fmt_fp.c
new file mode 100644
index 00000000..0a8b22b4
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/fmt_fp.c
@@ -0,0 +1,372 @@
+/*
+
+Most code in this file originates from musl (src/stdio/vfprintf.c)
+which, just like mruby itself, is licensed under the MIT license.
+
+Copyright (c) 2005-2014 Rich Felker, et al.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <limits.h>
+#include <string.h>
+#include <stdint.h>
+#include <math.h>
+#include <float.h>
+#include <ctype.h>
+
+#include <mruby.h>
+#include <mruby/string.h>
+
+struct fmt_args {
+ mrb_state *mrb;
+ mrb_value str;
+};
+
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+
+/* Convenient bit representation for modifier flags, which all fall
+ * within 31 codepoints of the space character. */
+
+#define ALT_FORM (1U<<('#'-' '))
+#define ZERO_PAD (1U<<('0'-' '))
+#define LEFT_ADJ (1U<<('-'-' '))
+#define PAD_POS (1U<<(' '-' '))
+#define MARK_POS (1U<<('+'-' '))
+
+static void
+out(struct fmt_args *f, const char *s, size_t l)
+{
+ mrb_str_cat(f->mrb, f->str, s, l);
+}
+
+#define PAD_SIZE 256
+static void
+pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint8_t fl)
+{
+ char pad[PAD_SIZE];
+ if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
+ l = w - l;
+ memset(pad, c, l>PAD_SIZE ? PAD_SIZE : l);
+ for (; l >= PAD_SIZE; l -= PAD_SIZE)
+ out(f, pad, PAD_SIZE);
+ out(f, pad, l);
+}
+
+static const char xdigits[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+static char*
+fmt_u(uint32_t x, char *s)
+{
+ for (; x; x /= 10) *--s = '0' + x % 10;
+ return s;
+}
+
+/* Do not override this check. The floating point printing code below
+ * depends on the float.h constants being right. If they are wrong, it
+ * may overflow the stack. */
+#if LDBL_MANT_DIG == 53
+typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
+#endif
+
+static int
+fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
+{
+ uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
+ + (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
+ uint32_t *a, *d, *r, *z;
+ uint32_t i;
+ int e2=0, e, j;
+ ptrdiff_t l;
+ char buf[9+LDBL_MANT_DIG/4], *s;
+ const char *prefix="-0X+0X 0X-0x+0x 0x";
+ ptrdiff_t pl;
+ char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
+
+ pl=1;
+ if (signbit(y)) {
+ y=-y;
+ } else if (fl & MARK_POS) {
+ prefix+=3;
+ } else if (fl & PAD_POS) {
+ prefix+=6;
+ } else prefix++, pl=0;
+
+ if (!isfinite(y)) {
+ const char *ss = (t&32)?"inf":"INF";
+ if (y!=y) ss=(t&32)?"nan":"NAN";
+ pad(f, ' ', 0, 3+pl, fl&~ZERO_PAD);
+ out(f, prefix, pl);
+ out(f, ss, 3);
+ pad(f, ' ', 0, 3+pl, fl^LEFT_ADJ);
+ return 3+(int)pl;
+ }
+
+ y = frexp((double)y, &e2) * 2;
+ if (y) e2--;
+
+ if ((t|32)=='a') {
+ long double round = 8.0;
+ ptrdiff_t re;
+
+ if (t&32) prefix += 9;
+ pl += 2;
+
+ if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0;
+ else re=LDBL_MANT_DIG/4-1-p;
+
+ if (re) {
+ while (re--) round*=16;
+ if (*prefix=='-') {
+ y=-y;
+ y-=round;
+ y+=round;
+ y=-y;
+ }
+ else {
+ y+=round;
+ y-=round;
+ }
+ }
+
+ estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
+ if (estr==ebuf) *--estr='0';
+ *--estr = (e2<0 ? '-' : '+');
+ *--estr = t+('p'-'a');
+
+ s=buf;
+ do {
+ int x=(int)y;
+ *s++=xdigits[x]|(t&32);
+ y=16*(y-x);
+ if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
+ } while (y);
+
+ if (p && s-buf-2 < p)
+ l = (p+2) + (ebuf-estr);
+ else
+ l = (s-buf) + (ebuf-estr);
+
+ pad(f, ' ', 0, pl+l, fl);
+ out(f, prefix, pl);
+ pad(f, '0', 0, pl+l, fl^ZERO_PAD);
+ out(f, buf, s-buf);
+ pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
+ out(f, estr, ebuf-estr);
+ pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
+ return (int)pl+(int)l;
+ }
+ if (p<0) p=6;
+
+ if (y) y *= 268435456.0, e2-=28;
+
+ if (e2<0) a=r=z=big;
+ else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
+
+ do {
+ *z = (uint32_t)y;
+ y = 1000000000*(y-*z++);
+ } while (y);
+
+ while (e2>0) {
+ uint32_t carry=0;
+ int sh=MIN(29,e2);
+ for (d=z-1; d>=a; d--) {
+ uint64_t x = ((uint64_t)*d<<sh)+carry;
+ *d = x % 1000000000;
+ carry = (uint32_t)(x / 1000000000);
+ }
+ if (carry) *--a = carry;
+ while (z>a && !z[-1]) z--;
+ e2-=sh;
+ }
+ while (e2<0) {
+ uint32_t carry=0, *b;
+ int sh=MIN(9,-e2), need=1+((int)p+LDBL_MANT_DIG/3+8)/9;
+ for (d=a; d<z; d++) {
+ uint32_t rm = *d & ((1<<sh)-1);
+ *d = (*d>>sh) + carry;
+ carry = (1000000000>>sh) * rm;
+ }
+ if (!*a) a++;
+ if (carry) *z++ = carry;
+ /* Avoid (slow!) computation past requested precision */
+ b = (t|32)=='f' ? r : a;
+ if (z-b > need) z = b+need;
+ e2+=sh;
+ }
+
+ if (a<z) for (i=10, e=9*(int)(r-a); *a>=i; i*=10, e++);
+ else e=0;
+
+ /* Perform rounding: j is precision after the radix (possibly neg) */
+ j = (int)p - ((t|32)!='f')*e - ((t|32)=='g' && p);
+ if (j < 9*(z-r-1)) {
+ uint32_t x;
+ /* We avoid C's broken division of negative numbers */
+ d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP);
+ j += 9*LDBL_MAX_EXP;
+ j %= 9;
+ for (i=10, j++; j<9; i*=10, j++);
+ x = *d % i;
+ /* Are there any significant digits past j? */
+ if (x || d+1!=z) {
+ long double round = 2/LDBL_EPSILON;
+ long double small;
+ if (*d/i & 1) round += 2;
+ if (x<i/2) small=0.5;
+ else if (x==i/2 && d+1==z) small=1.0;
+ else small=1.5;
+ if (pl && *prefix=='-') round*=-1, small*=-1;
+ *d -= x;
+ /* Decide whether to round by probing round+small */
+ if (round+small != round) {
+ *d = *d + i;
+ while (*d > 999999999) {
+ *d--=0;
+ if (d<a) *--a=0;
+ (*d)++;
+ }
+ for (i=10, e=9*(int)(r-a); *a>=i; i*=10, e++);
+ }
+ }
+ if (z>d+1) z=d+1;
+ }
+ for (; z>a && !z[-1]; z--);
+
+ if ((t|32)=='g') {
+ if (!p) p++;
+ if (p>e && e>=-4) {
+ t--;
+ p-=e+1;
+ }
+ else {
+ t-=2;
+ p--;
+ }
+ if (!(fl&ALT_FORM)) {
+ /* Count trailing zeros in last place */
+ if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
+ else j=9;
+ if ((t|32)=='f')
+ p = MIN(p,MAX(0,9*(z-r-1)-j));
+ else
+ p = MIN(p,MAX(0,9*(z-r-1)+e-j));
+ }
+ }
+ l = 1 + p + (p || (fl&ALT_FORM));
+ if ((t|32)=='f') {
+ if (e>0) l+=e;
+ }
+ else {
+ estr=fmt_u(e<0 ? -e : e, ebuf);
+ while(ebuf-estr<2) *--estr='0';
+ *--estr = (e<0 ? '-' : '+');
+ *--estr = t;
+ l += ebuf-estr;
+ }
+
+ pad(f, ' ', 0, pl+l, fl);
+ out(f, prefix, pl);
+ pad(f, '0', 0, pl+l, fl^ZERO_PAD);
+
+ if ((t|32)=='f') {
+ if (a>r) a=r;
+ for (d=a; d<=r; d++) {
+ char *ss = fmt_u(*d, buf+9);
+ if (d!=a) while (ss>buf) *--ss='0';
+ else if (ss==buf+9) *--ss='0';
+ out(f, ss, buf+9-ss);
+ }
+ if (p || (fl&ALT_FORM)) out(f, ".", 1);
+ for (; d<z && p>0; d++, p-=9) {
+ char *ss = fmt_u(*d, buf+9);
+ while (ss>buf) *--ss='0';
+ out(f, ss, MIN(9,p));
+ }
+ pad(f, '0', p+9, 9, 0);
+ }
+ else {
+ if (z<=a) z=a+1;
+ for (d=a; d<z && p>=0; d++) {
+ char *ss = fmt_u(*d, buf+9);
+ if (ss==buf+9) *--ss='0';
+ if (d!=a) while (ss>buf) *--ss='0';
+ else {
+ out(f, ss++, 1);
+ if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
+ }
+ out(f, ss, MIN(buf+9-ss, p));
+ p -= (int)(buf+9-ss);
+ }
+ pad(f, '0', p+18, 18, 0);
+ out(f, estr, ebuf-estr);
+ }
+
+ pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
+
+ return (int)pl+(int)l;
+}
+
+static int
+fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
+{
+ ptrdiff_t p;
+
+ if (*fmt != '%') {
+ return -1;
+ }
+ ++fmt;
+
+ if (*fmt == '.') {
+ ++fmt;
+ for (p = 0; ISDIGIT(*fmt); ++fmt) {
+ p = 10 * p + (*fmt - '0');
+ }
+ }
+ else {
+ p = -1;
+ }
+
+ switch (*fmt) {
+ case 'e': case 'f': case 'g': case 'a':
+ case 'E': case 'F': case 'G': case 'A':
+ return fmt_fp(f, flo, p, 0, *fmt);
+ default:
+ return -1;
+ }
+}
+
+mrb_value
+mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
+{
+ struct fmt_args f;
+
+ f.mrb = mrb;
+ f.str = mrb_str_new_capa(mrb, 24);
+ if (fmt_core(&f, fmt, mrb_float(flo)) < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
+ }
+ return f.str;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/gc.c b/web/server/h2o/libh2o/deps/mruby/src/gc.c
new file mode 100644
index 00000000..d602bfb7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/gc.c
@@ -0,0 +1,1824 @@
+/*
+** gc.c - garbage collector for mruby
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/data.h>
+#include <mruby/hash.h>
+#include <mruby/proc.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/gc.h>
+#include <mruby/error.h>
+#include <mruby/throw.h>
+
+/*
+ = Tri-color Incremental Garbage Collection
+
+ mruby's GC is Tri-color Incremental GC with Mark & Sweep.
+ Algorithm details are omitted.
+ Instead, the implementation part is described below.
+
+ == Object's Color
+
+ Each object can be painted in three colors:
+
+ * White - Unmarked.
+ * Gray - Marked, But the child objects are unmarked.
+ * Black - Marked, the child objects are also marked.
+
+ == Two White Types
+
+ There're two white color types in a flip-flop fashion: White-A and White-B,
+ which respectively represent the Current White color (the newly allocated
+ objects in the current GC cycle) and the Sweep Target White color (the
+ dead objects to be swept).
+
+ A and B will be switched just at the beginning of the next GC cycle. At
+ that time, all the dead objects have been swept, while the newly created
+ objects in the current GC cycle which finally remains White are now
+ regarded as dead objects. Instead of traversing all the White-A objects and
+ painting them as White-B, just switch the meaning of White-A and White-B as
+ this will be much cheaper.
+
+ As a result, the objects we sweep in the current GC cycle are always
+ left from the previous GC cycle. This allows us to sweep objects
+ incrementally, without the disturbance of the newly created objects.
+
+ == Execution Timing
+
+ GC Execution Time and Each step interval are decided by live objects count.
+ List of Adjustment API:
+
+ * gc_interval_ratio_set
+ * gc_step_ratio_set
+
+ For details, see the comments for each function.
+
+ == Write Barrier
+
+ mruby implementer and C extension library writer must insert a write
+ barrier when updating a reference from a field of an object.
+ When updating a reference from a field of object A to object B,
+ two different types of write barrier are available:
+
+ * mrb_field_write_barrier - target B object for a mark.
+ * mrb_write_barrier - target A object for a mark.
+
+ == Generational Mode
+
+ mruby's GC offers an Generational Mode while re-using the tri-color GC
+ infrastructure. It will treat the Black objects as Old objects after each
+ sweep phase, instead of painting them White. The key ideas are still the same
+ as traditional generational GC:
+
+ * Minor GC - just traverse the Young objects (Gray objects) in the mark
+ phase, then only sweep the newly created objects, and leave
+ the Old objects live.
+
+ * Major GC - same as a full regular GC cycle.
+
+ The difference from "traditional" generational GC is, that the major GC
+ in mruby is triggered incrementally in a tri-color manner.
+
+
+ For details, see the comments for each function.
+
+*/
+
+struct free_obj {
+ MRB_OBJECT_HEADER;
+ struct RBasic *next;
+};
+
+typedef struct {
+ union {
+ struct free_obj free;
+ struct RBasic basic;
+ struct RObject object;
+ struct RClass klass;
+ struct RString string;
+ struct RArray array;
+ struct RHash hash;
+ struct RRange range;
+ struct RData data;
+ struct RProc proc;
+ struct REnv env;
+ struct RException exc;
+ struct RBreak brk;
+#ifdef MRB_WORD_BOXING
+ struct RFloat floatv;
+ struct RCptr cptr;
+#endif
+ } as;
+} RVALUE;
+
+#ifdef GC_PROFILE
+#include <stdio.h>
+#include <sys/time.h>
+
+static double program_invoke_time = 0;
+static double gc_time = 0;
+static double gc_total_time = 0;
+
+static double
+gettimeofday_time(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec + tv.tv_usec * 1e-6;
+}
+
+#define GC_INVOKE_TIME_REPORT(with) do {\
+ fprintf(stderr, "%s\n", with);\
+ fprintf(stderr, "gc_invoke: %19.3f\n", gettimeofday_time() - program_invoke_time);\
+ fprintf(stderr, "is_generational: %d\n", is_generational(gc));\
+ fprintf(stderr, "is_major_gc: %d\n", is_major_gc(gc));\
+} while(0)
+
+#define GC_TIME_START do {\
+ gc_time = gettimeofday_time();\
+} while(0)
+
+#define GC_TIME_STOP_AND_REPORT do {\
+ gc_time = gettimeofday_time() - gc_time;\
+ gc_total_time += gc_time;\
+ fprintf(stderr, "gc_state: %d\n", gc->state);\
+ fprintf(stderr, "live: %zu\n", gc->live);\
+ fprintf(stderr, "majorgc_old_threshold: %zu\n", gc->majorgc_old_threshold);\
+ fprintf(stderr, "gc_threshold: %zu\n", gc->threshold);\
+ fprintf(stderr, "gc_time: %30.20f\n", gc_time);\
+ fprintf(stderr, "gc_total_time: %30.20f\n\n", gc_total_time);\
+} while(0)
+#else
+#define GC_INVOKE_TIME_REPORT(s)
+#define GC_TIME_START
+#define GC_TIME_STOP_AND_REPORT
+#endif
+
+#ifdef GC_DEBUG
+#define DEBUG(x) (x)
+#else
+#define DEBUG(x)
+#endif
+
+#ifndef MRB_HEAP_PAGE_SIZE
+#define MRB_HEAP_PAGE_SIZE 1024
+#endif
+
+#define GC_STEP_SIZE 1024
+
+/* white: 011, black: 100, gray: 000 */
+#define GC_GRAY 0
+#define GC_WHITE_A 1
+#define GC_WHITE_B (1 << 1)
+#define GC_BLACK (1 << 2)
+#define GC_WHITES (GC_WHITE_A | GC_WHITE_B)
+#define GC_COLOR_MASK 7
+
+#define paint_gray(o) ((o)->color = GC_GRAY)
+#define paint_black(o) ((o)->color = GC_BLACK)
+#define paint_white(o) ((o)->color = GC_WHITES)
+#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part)
+#define is_gray(o) ((o)->color == GC_GRAY)
+#define is_white(o) ((o)->color & GC_WHITES)
+#define is_black(o) ((o)->color & GC_BLACK)
+#define flip_white_part(s) ((s)->current_white_part = other_white_part(s))
+#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES)
+#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE)
+
+#define objects(p) ((RVALUE *)p->objects)
+
+MRB_API void*
+mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
+{
+ void *p2;
+
+ p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud);
+ if (!p2 && len > 0 && mrb->gc.heaps) {
+ mrb_full_gc(mrb);
+ p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud);
+ }
+
+ return p2;
+}
+
+MRB_API void*
+mrb_realloc(mrb_state *mrb, void *p, size_t len)
+{
+ void *p2;
+
+ p2 = mrb_realloc_simple(mrb, p, len);
+ if (len == 0) return p2;
+ if (p2 == NULL) {
+ if (mrb->gc.out_of_memory) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
+ /* mrb_panic(mrb); */
+ }
+ else {
+ mrb->gc.out_of_memory = TRUE;
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
+ }
+ }
+ else {
+ mrb->gc.out_of_memory = FALSE;
+ }
+
+ return p2;
+}
+
+MRB_API void*
+mrb_malloc(mrb_state *mrb, size_t len)
+{
+ return mrb_realloc(mrb, 0, len);
+}
+
+MRB_API void*
+mrb_malloc_simple(mrb_state *mrb, size_t len)
+{
+ return mrb_realloc_simple(mrb, 0, len);
+}
+
+MRB_API void*
+mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
+{
+ void *p;
+
+ if (nelem > 0 && len > 0 &&
+ nelem <= SIZE_MAX / len) {
+ size_t size;
+ size = nelem * len;
+ p = mrb_malloc(mrb, size);
+
+ memset(p, 0, size);
+ }
+ else {
+ p = NULL;
+ }
+
+ return p;
+}
+
+MRB_API void
+mrb_free(mrb_state *mrb, void *p)
+{
+ (mrb->allocf)(mrb, p, 0, mrb->allocf_ud);
+}
+
+MRB_API mrb_bool
+mrb_object_dead_p(mrb_state *mrb, struct RBasic *object) {
+ return is_dead(&mrb->gc, object);
+}
+
+static void
+link_heap_page(mrb_gc *gc, mrb_heap_page *page)
+{
+ page->next = gc->heaps;
+ if (gc->heaps)
+ gc->heaps->prev = page;
+ gc->heaps = page;
+}
+
+static void
+unlink_heap_page(mrb_gc *gc, mrb_heap_page *page)
+{
+ if (page->prev)
+ page->prev->next = page->next;
+ if (page->next)
+ page->next->prev = page->prev;
+ if (gc->heaps == page)
+ gc->heaps = page->next;
+ page->prev = NULL;
+ page->next = NULL;
+}
+
+static void
+link_free_heap_page(mrb_gc *gc, mrb_heap_page *page)
+{
+ page->free_next = gc->free_heaps;
+ if (gc->free_heaps) {
+ gc->free_heaps->free_prev = page;
+ }
+ gc->free_heaps = page;
+}
+
+static void
+unlink_free_heap_page(mrb_gc *gc, mrb_heap_page *page)
+{
+ if (page->free_prev)
+ page->free_prev->free_next = page->free_next;
+ if (page->free_next)
+ page->free_next->free_prev = page->free_prev;
+ if (gc->free_heaps == page)
+ gc->free_heaps = page->free_next;
+ page->free_prev = NULL;
+ page->free_next = NULL;
+}
+
+static void
+add_heap(mrb_state *mrb, mrb_gc *gc)
+{
+ mrb_heap_page *page = (mrb_heap_page *)mrb_calloc(mrb, 1, sizeof(mrb_heap_page) + MRB_HEAP_PAGE_SIZE * sizeof(RVALUE));
+ RVALUE *p, *e;
+ struct RBasic *prev = NULL;
+
+ for (p = objects(page), e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
+ p->as.free.tt = MRB_TT_FREE;
+ p->as.free.next = prev;
+ prev = &p->as.basic;
+ }
+ page->freelist = prev;
+
+ link_heap_page(gc, page);
+ link_free_heap_page(gc, page);
+}
+
+#define DEFAULT_GC_INTERVAL_RATIO 200
+#define DEFAULT_GC_STEP_RATIO 200
+#define DEFAULT_MAJOR_GC_INC_RATIO 200
+#define is_generational(gc) ((gc)->generational)
+#define is_major_gc(gc) (is_generational(gc) && (gc)->full)
+#define is_minor_gc(gc) (is_generational(gc) && !(gc)->full)
+
+void
+mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
+{
+#ifndef MRB_GC_FIXED_ARENA
+ gc->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
+ gc->arena_capa = MRB_GC_ARENA_SIZE;
+#endif
+
+ gc->current_white_part = GC_WHITE_A;
+ gc->heaps = NULL;
+ gc->free_heaps = NULL;
+ add_heap(mrb, gc);
+ gc->interval_ratio = DEFAULT_GC_INTERVAL_RATIO;
+ gc->step_ratio = DEFAULT_GC_STEP_RATIO;
+#ifndef MRB_GC_TURN_OFF_GENERATIONAL
+ gc->generational = TRUE;
+ gc->full = TRUE;
+#endif
+
+#ifdef GC_PROFILE
+ program_invoke_time = gettimeofday_time();
+#endif
+}
+
+static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
+
+void
+free_heap(mrb_state *mrb, mrb_gc *gc)
+{
+ mrb_heap_page *page = gc->heaps;
+ mrb_heap_page *tmp;
+ RVALUE *p, *e;
+
+ while (page) {
+ tmp = page;
+ page = page->next;
+ for (p = objects(tmp), e=p+MRB_HEAP_PAGE_SIZE; p<e; p++) {
+ if (p->as.free.tt != MRB_TT_FREE)
+ obj_free(mrb, &p->as.basic, TRUE);
+ }
+ mrb_free(mrb, tmp);
+ }
+}
+
+void
+mrb_gc_destroy(mrb_state *mrb, mrb_gc *gc)
+{
+ free_heap(mrb, gc);
+#ifndef MRB_GC_FIXED_ARENA
+ mrb_free(mrb, gc->arena);
+#endif
+}
+
+static void
+gc_protect(mrb_state *mrb, mrb_gc *gc, struct RBasic *p)
+{
+#ifdef MRB_GC_FIXED_ARENA
+ if (gc->arena_idx >= MRB_GC_ARENA_SIZE) {
+ /* arena overflow error */
+ gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->arena_err));
+ }
+#else
+ if (gc->arena_idx >= gc->arena_capa) {
+ /* extend arena */
+ gc->arena_capa = (int)(gc->arena_capa * 1.5);
+ gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*gc->arena_capa);
+ }
+#endif
+ gc->arena[gc->arena_idx++] = p;
+}
+
+/* mrb_gc_protect() leaves the object in the arena */
+MRB_API void
+mrb_gc_protect(mrb_state *mrb, mrb_value obj)
+{
+ if (mrb_immediate_p(obj)) return;
+ gc_protect(mrb, &mrb->gc, mrb_basic_ptr(obj));
+}
+
+#define GC_ROOT_NAME "_gc_root_"
+
+/* mrb_gc_register() keeps the object from GC.
+
+ Register your object when it's exported to C world,
+ without reference from Ruby world, e.g. callback
+ arguments. Don't forget to remove the object using
+ mrb_gc_unregister, otherwise your object will leak.
+*/
+
+MRB_API void
+mrb_gc_register(mrb_state *mrb, mrb_value obj)
+{
+ mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ mrb_value table = mrb_gv_get(mrb, root);
+
+ if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) {
+ table = mrb_ary_new(mrb);
+ mrb_gv_set(mrb, root, table);
+ }
+ mrb_ary_push(mrb, table, obj);
+}
+
+/* mrb_gc_unregister() removes the object from GC root. */
+MRB_API void
+mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
+{
+ mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+ mrb_value table = mrb_gv_get(mrb, root);
+ struct RArray *a;
+ mrb_int i;
+
+ if (mrb_nil_p(table)) return;
+ if (mrb_type(table) != MRB_TT_ARRAY) {
+ mrb_gv_set(mrb, root, mrb_nil_value());
+ return;
+ }
+ a = mrb_ary_ptr(table);
+ mrb_ary_modify(mrb, a);
+ for (i = 0; i < ARY_LEN(a); i++) {
+ if (mrb_obj_eq(mrb, ARY_PTR(a)[i], obj)) {
+ mrb_int len = ARY_LEN(a)-1;
+ mrb_value *ptr = ARY_PTR(a);
+
+ ARY_SET_LEN(a, len);
+ memmove(&ptr[i], &ptr[i + 1], (len - i) * sizeof(mrb_value));
+ break;
+ }
+ }
+}
+
+MRB_API struct RBasic*
+mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls)
+{
+ struct RBasic *p;
+ static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } };
+ mrb_gc *gc = &mrb->gc;
+
+ if (cls) {
+ enum mrb_vtype tt;
+
+ switch (cls->tt) {
+ case MRB_TT_CLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_ENV:
+ break;
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "allocation failure");
+ }
+ tt = MRB_INSTANCE_TT(cls);
+ if (tt != MRB_TT_FALSE &&
+ ttype != MRB_TT_SCLASS &&
+ ttype != MRB_TT_ICLASS &&
+ ttype != MRB_TT_ENV &&
+ ttype != tt) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls));
+ }
+ }
+
+#ifdef MRB_GC_STRESS
+ mrb_full_gc(mrb);
+#endif
+ if (gc->threshold < gc->live) {
+ mrb_incremental_gc(mrb);
+ }
+ if (gc->free_heaps == NULL) {
+ add_heap(mrb, gc);
+ }
+
+ p = gc->free_heaps->freelist;
+ gc->free_heaps->freelist = ((struct free_obj*)p)->next;
+ if (gc->free_heaps->freelist == NULL) {
+ unlink_free_heap_page(gc, gc->free_heaps);
+ }
+
+ gc->live++;
+ gc_protect(mrb, gc, p);
+ *(RVALUE *)p = RVALUE_zero;
+ p->tt = ttype;
+ p->c = cls;
+ paint_partial_white(gc, p);
+ return p;
+}
+
+static inline void
+add_gray_list(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
+{
+#ifdef MRB_GC_STRESS
+ if (obj->tt > MRB_TT_MAXDEFINE) {
+ abort();
+ }
+#endif
+ paint_gray(obj);
+ obj->gcnext = gc->gray_list;
+ gc->gray_list = obj;
+}
+
+static void
+mark_context_stack(mrb_state *mrb, struct mrb_context *c)
+{
+ size_t i;
+ size_t e;
+ mrb_value nil;
+ int nregs;
+
+ if (c->stack == NULL) return;
+ e = c->stack - c->stbase;
+ if (c->ci) {
+ nregs = c->ci->argc + 2;
+ if (c->ci->nregs > nregs)
+ nregs = c->ci->nregs;
+ e += nregs;
+ }
+ if (c->stbase + e > c->stend) e = c->stend - c->stbase;
+ for (i=0; i<e; i++) {
+ mrb_value v = c->stbase[i];
+
+ if (!mrb_immediate_p(v)) {
+ mrb_gc_mark(mrb, mrb_basic_ptr(v));
+ }
+ }
+ e = c->stend - c->stbase;
+ nil = mrb_nil_value();
+ for (; i<e; i++) {
+ c->stbase[i] = nil;
+ }
+}
+
+static void
+mark_context(mrb_state *mrb, struct mrb_context *c)
+{
+ int i;
+ mrb_callinfo *ci;
+
+ if (c->status == MRB_FIBER_TERMINATED) return;
+
+ /* mark VM stack */
+ mark_context_stack(mrb, c);
+
+ /* mark call stack */
+ if (c->cibase) {
+ for (ci = c->cibase; ci <= c->ci; ci++) {
+ mrb_gc_mark(mrb, (struct RBasic*)ci->env);
+ mrb_gc_mark(mrb, (struct RBasic*)ci->proc);
+ mrb_gc_mark(mrb, (struct RBasic*)ci->target_class);
+ }
+ }
+ /* mark ensure stack */
+ for (i=0; i<c->esize; i++) {
+ if (c->ensure[i] == NULL) break;
+ mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
+ }
+ /* mark fibers */
+ mrb_gc_mark(mrb, (struct RBasic*)c->fib);
+ if (c->prev) {
+ mark_context(mrb, c->prev);
+ }
+}
+
+static void
+gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
+{
+ mrb_assert(is_gray(obj));
+ paint_black(obj);
+ gc->gray_list = obj->gcnext;
+ mrb_gc_mark(mrb, (struct RBasic*)obj->c);
+ switch (obj->tt) {
+ case MRB_TT_ICLASS:
+ {
+ struct RClass *c = (struct RClass*)obj;
+ if (MRB_FLAG_TEST(c, MRB_FLAG_IS_ORIGIN))
+ mrb_gc_mark_mt(mrb, c);
+ mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super);
+ }
+ break;
+
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
+ {
+ struct RClass *c = (struct RClass*)obj;
+
+ mrb_gc_mark_mt(mrb, c);
+ mrb_gc_mark(mrb, (struct RBasic*)c->super);
+ }
+ /* fall through */
+
+ case MRB_TT_OBJECT:
+ case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
+ mrb_gc_mark_iv(mrb, (struct RObject*)obj);
+ break;
+
+ case MRB_TT_PROC:
+ {
+ struct RProc *p = (struct RProc*)obj;
+
+ mrb_gc_mark(mrb, (struct RBasic*)p->env);
+ mrb_gc_mark(mrb, (struct RBasic*)p->target_class);
+ if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
+ mrb_gc_mark(mrb, (struct RBasic*)p->body.irep->target_class);
+ }
+ }
+ break;
+
+ case MRB_TT_ENV:
+ {
+ struct REnv *e = (struct REnv*)obj;
+ mrb_int i, len;
+
+ if (MRB_ENV_STACK_SHARED_P(e)) {
+ if (e->cxt.c->fib) {
+ mrb_gc_mark(mrb, (struct RBasic*)e->cxt.c->fib);
+ }
+ break;
+ }
+ len = MRB_ENV_STACK_LEN(e);
+ for (i=0; i<len; i++) {
+ mrb_gc_mark_value(mrb, e->stack[i]);
+ }
+ }
+ break;
+
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+
+ if (c) mark_context(mrb, c);
+ }
+ break;
+
+ case MRB_TT_ARRAY:
+ {
+ struct RArray *a = (struct RArray*)obj;
+ size_t i, e;
+
+ for (i=0,e=ARY_LEN(a); i<e; i++) {
+ mrb_gc_mark_value(mrb, ARY_PTR(a)[i]);
+ }
+ }
+ break;
+
+ case MRB_TT_HASH:
+ mrb_gc_mark_iv(mrb, (struct RObject*)obj);
+ mrb_gc_mark_hash(mrb, (struct RHash*)obj);
+ break;
+
+ case MRB_TT_STRING:
+ break;
+
+ case MRB_TT_RANGE:
+ {
+ struct RRange *r = (struct RRange*)obj;
+
+ if (r->edges) {
+ mrb_gc_mark_value(mrb, r->edges->beg);
+ mrb_gc_mark_value(mrb, r->edges->end);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+MRB_API void
+mrb_gc_mark(mrb_state *mrb, struct RBasic *obj)
+{
+ if (obj == 0) return;
+ if (!is_white(obj)) return;
+ mrb_assert((obj)->tt != MRB_TT_FREE);
+ add_gray_list(mrb, &mrb->gc, obj);
+}
+
+static void
+obj_free(mrb_state *mrb, struct RBasic *obj, int end)
+{
+ DEBUG(fprintf(stderr, "obj_free(%p,tt=%d)\n",obj,obj->tt));
+ switch (obj->tt) {
+ /* immediate - no mark */
+ case MRB_TT_TRUE:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_SYMBOL:
+ /* cannot happen */
+ return;
+
+ case MRB_TT_FLOAT:
+#ifdef MRB_WORD_BOXING
+ break;
+#else
+ return;
+#endif
+
+ case MRB_TT_OBJECT:
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ break;
+
+ case MRB_TT_EXCEPTION:
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ break;
+
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
+ mrb_gc_free_mt(mrb, (struct RClass*)obj);
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ break;
+ case MRB_TT_ICLASS:
+ if (MRB_FLAG_TEST(obj, MRB_FLAG_IS_ORIGIN))
+ mrb_gc_free_mt(mrb, (struct RClass*)obj);
+ break;
+ case MRB_TT_ENV:
+ {
+ struct REnv *e = (struct REnv*)obj;
+
+ if (MRB_ENV_STACK_SHARED_P(e)) {
+ /* cannot be freed */
+ return;
+ }
+ mrb_free(mrb, e->stack);
+ e->stack = NULL;
+ }
+ break;
+
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+
+ if (!end && c && c != mrb->root_c) {
+ mrb_callinfo *ci = c->ci;
+ mrb_callinfo *ce = c->cibase;
+
+ while (ce <= ci) {
+ struct REnv *e = ci->env;
+ if (e && !is_dead(&mrb->gc, e) &&
+ e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
+ mrb_env_unshare(mrb, e);
+ }
+ ci--;
+ }
+ mrb_free_context(mrb, c);
+ }
+ }
+ break;
+
+ case MRB_TT_ARRAY:
+ if (ARY_SHARED_P(obj))
+ mrb_ary_decref(mrb, ((struct RArray*)obj)->as.heap.aux.shared);
+ else if (!ARY_EMBED_P(obj))
+ mrb_free(mrb, ((struct RArray*)obj)->as.heap.ptr);
+ break;
+
+ case MRB_TT_HASH:
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ mrb_gc_free_hash(mrb, (struct RHash*)obj);
+ break;
+
+ case MRB_TT_STRING:
+ mrb_gc_free_str(mrb, (struct RString*)obj);
+ break;
+
+ case MRB_TT_PROC:
+ {
+ struct RProc *p = (struct RProc*)obj;
+
+ if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
+ mrb_irep_decref(mrb, p->body.irep);
+ }
+ }
+ break;
+
+ case MRB_TT_RANGE:
+ mrb_free(mrb, ((struct RRange*)obj)->edges);
+ break;
+
+ case MRB_TT_DATA:
+ {
+ struct RData *d = (struct RData*)obj;
+ if (d->type && d->type->dfree) {
+ d->type->dfree(mrb, d->data);
+ }
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ }
+ break;
+
+ default:
+ break;
+ }
+ obj->tt = MRB_TT_FREE;
+}
+
+static void
+root_scan_phase(mrb_state *mrb, mrb_gc *gc)
+{
+ int i, e;
+
+ if (!is_minor_gc(gc)) {
+ gc->gray_list = NULL;
+ gc->atomic_gray_list = NULL;
+ }
+
+ mrb_gc_mark_gv(mrb);
+ /* mark arena */
+ for (i=0,e=gc->arena_idx; i<e; i++) {
+ mrb_gc_mark(mrb, gc->arena[i]);
+ }
+ /* mark class hierarchy */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class);
+
+ /* mark built-in classes */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->class_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->module_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->proc_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->string_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->array_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->range_class);
+
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->false_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->nil_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->symbol_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->kernel_module);
+
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->eException_class);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->eStandardError_class);
+
+ /* mark top_self */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
+ /* mark exception */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
+ /* mark pre-allocated exception */
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->stack_err);
+#ifdef MRB_GC_FIXED_ARENA
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err);
+#endif
+
+ mark_context(mrb, mrb->c);
+ if (mrb->root_c != mrb->c) {
+ mark_context(mrb, mrb->root_c);
+ }
+}
+
+static size_t
+gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
+{
+ size_t children = 0;
+
+ gc_mark_children(mrb, gc, obj);
+
+ switch (obj->tt) {
+ case MRB_TT_ICLASS:
+ children++;
+ break;
+
+ case MRB_TT_CLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_MODULE:
+ {
+ struct RClass *c = (struct RClass*)obj;
+
+ children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
+ children += mrb_gc_mark_mt_size(mrb, c);
+ children++;
+ }
+ break;
+
+ case MRB_TT_OBJECT:
+ case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
+ children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
+ break;
+
+ case MRB_TT_ENV:
+ children += (int)obj->flags;
+ break;
+
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+ size_t i;
+ mrb_callinfo *ci;
+
+ if (!c) break;
+ /* mark stack */
+ i = c->stack - c->stbase;
+ if (c->ci) i += c->ci->nregs;
+ if (c->stbase + i > c->stend) i = c->stend - c->stbase;
+ children += i;
+
+ /* mark ensure stack */
+ children += c->eidx;
+
+ /* mark closure */
+ if (c->cibase) {
+ for (i=0, ci = c->cibase; ci <= c->ci; i++, ci++)
+ ;
+ }
+ children += i;
+ }
+ break;
+
+ case MRB_TT_ARRAY:
+ {
+ struct RArray *a = (struct RArray*)obj;
+ children += ARY_LEN(a);
+ }
+ break;
+
+ case MRB_TT_HASH:
+ children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
+ children += mrb_gc_mark_hash_size(mrb, (struct RHash*)obj);
+ break;
+
+ case MRB_TT_PROC:
+ case MRB_TT_RANGE:
+ children+=2;
+ break;
+
+ default:
+ break;
+ }
+ return children;
+}
+
+
+static void
+gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) {
+ while (gc->gray_list) {
+ if (is_gray(gc->gray_list))
+ gc_mark_children(mrb, gc, gc->gray_list);
+ else
+ gc->gray_list = gc->gray_list->gcnext;
+ }
+}
+
+
+static size_t
+incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
+{
+ size_t tried_marks = 0;
+
+ while (gc->gray_list && tried_marks < limit) {
+ tried_marks += gc_gray_mark(mrb, gc, gc->gray_list);
+ }
+
+ return tried_marks;
+}
+
+static void
+final_marking_phase(mrb_state *mrb, mrb_gc *gc)
+{
+ int i, e;
+
+ /* mark arena */
+ for (i=0,e=gc->arena_idx; i<e; i++) {
+ mrb_gc_mark(mrb, gc->arena[i]);
+ }
+ mrb_gc_mark_gv(mrb);
+ mark_context(mrb, mrb->c);
+ mark_context(mrb, mrb->root_c);
+ mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
+ gc_mark_gray_list(mrb, gc);
+ mrb_assert(gc->gray_list == NULL);
+ gc->gray_list = gc->atomic_gray_list;
+ gc->atomic_gray_list = NULL;
+ gc_mark_gray_list(mrb, gc);
+ mrb_assert(gc->gray_list == NULL);
+}
+
+static void
+prepare_incremental_sweep(mrb_state *mrb, mrb_gc *gc)
+{
+ gc->state = MRB_GC_STATE_SWEEP;
+ gc->sweeps = gc->heaps;
+ gc->live_after_mark = gc->live;
+}
+
+static size_t
+incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
+{
+ mrb_heap_page *page = gc->sweeps;
+ size_t tried_sweep = 0;
+
+ while (page && (tried_sweep < limit)) {
+ RVALUE *p = objects(page);
+ RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
+ size_t freed = 0;
+ mrb_bool dead_slot = TRUE;
+ mrb_bool full = (page->freelist == NULL);
+
+ if (is_minor_gc(gc) && page->old) {
+ /* skip a slot which doesn't contain any young object */
+ p = e;
+ dead_slot = FALSE;
+ }
+ while (p<e) {
+ if (is_dead(gc, &p->as.basic)) {
+ if (p->as.basic.tt != MRB_TT_FREE) {
+ obj_free(mrb, &p->as.basic, FALSE);
+ if (p->as.basic.tt == MRB_TT_FREE) {
+ p->as.free.next = page->freelist;
+ page->freelist = (struct RBasic*)p;
+ freed++;
+ }
+ else {
+ dead_slot = FALSE;
+ }
+ }
+ }
+ else {
+ if (!is_generational(gc))
+ paint_partial_white(gc, &p->as.basic); /* next gc target */
+ dead_slot = FALSE;
+ }
+ p++;
+ }
+
+ /* free dead slot */
+ if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) {
+ mrb_heap_page *next = page->next;
+
+ unlink_heap_page(gc, page);
+ unlink_free_heap_page(gc, page);
+ mrb_free(mrb, page);
+ page = next;
+ }
+ else {
+ if (full && freed > 0) {
+ link_free_heap_page(gc, page);
+ }
+ if (page->freelist == NULL && is_minor_gc(gc))
+ page->old = TRUE;
+ else
+ page->old = FALSE;
+ page = page->next;
+ }
+ tried_sweep += MRB_HEAP_PAGE_SIZE;
+ gc->live -= freed;
+ gc->live_after_mark -= freed;
+ }
+ gc->sweeps = page;
+ return tried_sweep;
+}
+
+static size_t
+incremental_gc(mrb_state *mrb, mrb_gc *gc, size_t limit)
+{
+ switch (gc->state) {
+ case MRB_GC_STATE_ROOT:
+ root_scan_phase(mrb, gc);
+ gc->state = MRB_GC_STATE_MARK;
+ flip_white_part(gc);
+ return 0;
+ case MRB_GC_STATE_MARK:
+ if (gc->gray_list) {
+ return incremental_marking_phase(mrb, gc, limit);
+ }
+ else {
+ final_marking_phase(mrb, gc);
+ prepare_incremental_sweep(mrb, gc);
+ return 0;
+ }
+ case MRB_GC_STATE_SWEEP: {
+ size_t tried_sweep = 0;
+ tried_sweep = incremental_sweep_phase(mrb, gc, limit);
+ if (tried_sweep == 0)
+ gc->state = MRB_GC_STATE_ROOT;
+ return tried_sweep;
+ }
+ default:
+ /* unknown state */
+ mrb_assert(0);
+ return 0;
+ }
+}
+
+static void
+incremental_gc_until(mrb_state *mrb, mrb_gc *gc, mrb_gc_state to_state)
+{
+ do {
+ incremental_gc(mrb, gc, SIZE_MAX);
+ } while (gc->state != to_state);
+}
+
+static void
+incremental_gc_step(mrb_state *mrb, mrb_gc *gc)
+{
+ size_t limit = 0, result = 0;
+ limit = (GC_STEP_SIZE/100) * gc->step_ratio;
+ while (result < limit) {
+ result += incremental_gc(mrb, gc, limit);
+ if (gc->state == MRB_GC_STATE_ROOT)
+ break;
+ }
+
+ gc->threshold = gc->live + GC_STEP_SIZE;
+}
+
+static void
+clear_all_old(mrb_state *mrb, mrb_gc *gc)
+{
+ mrb_bool origin_mode = gc->generational;
+
+ mrb_assert(is_generational(gc));
+ if (is_major_gc(gc)) {
+ /* finish the half baked GC */
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ }
+
+ /* Sweep the dead objects, then reset all the live objects
+ * (including all the old objects, of course) to white. */
+ gc->generational = FALSE;
+ prepare_incremental_sweep(mrb, gc);
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ gc->generational = origin_mode;
+
+ /* The gray objects have already been painted as white */
+ gc->atomic_gray_list = gc->gray_list = NULL;
+}
+
+MRB_API void
+mrb_incremental_gc(mrb_state *mrb)
+{
+ mrb_gc *gc = &mrb->gc;
+
+ if (gc->disabled || gc->iterating) return;
+
+ GC_INVOKE_TIME_REPORT("mrb_incremental_gc()");
+ GC_TIME_START;
+
+ if (is_minor_gc(gc)) {
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ }
+ else {
+ incremental_gc_step(mrb, gc);
+ }
+
+ if (gc->state == MRB_GC_STATE_ROOT) {
+ mrb_assert(gc->live >= gc->live_after_mark);
+ gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio;
+ if (gc->threshold < GC_STEP_SIZE) {
+ gc->threshold = GC_STEP_SIZE;
+ }
+
+ if (is_major_gc(gc)) {
+ gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+ gc->full = FALSE;
+ }
+ else if (is_minor_gc(gc)) {
+ if (gc->live > gc->majorgc_old_threshold) {
+ clear_all_old(mrb, gc);
+ gc->full = TRUE;
+ }
+ }
+ }
+
+ GC_TIME_STOP_AND_REPORT;
+}
+
+/* Perform a full gc cycle */
+MRB_API void
+mrb_full_gc(mrb_state *mrb)
+{
+ mrb_gc *gc = &mrb->gc;
+
+ if (gc->disabled || gc->iterating) return;
+
+ GC_INVOKE_TIME_REPORT("mrb_full_gc()");
+ GC_TIME_START;
+
+ if (is_generational(gc)) {
+ /* clear all the old objects back to young */
+ clear_all_old(mrb, gc);
+ gc->full = TRUE;
+ }
+ else if (gc->state != MRB_GC_STATE_ROOT) {
+ /* finish half baked GC cycle */
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ }
+
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio;
+
+ if (is_generational(gc)) {
+ gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+ gc->full = FALSE;
+ }
+
+ GC_TIME_STOP_AND_REPORT;
+}
+
+MRB_API void
+mrb_garbage_collect(mrb_state *mrb)
+{
+ mrb_full_gc(mrb);
+}
+
+/*
+ * Field write barrier
+ * Paint obj(Black) -> value(White) to obj(Black) -> value(Gray).
+ */
+
+MRB_API void
+mrb_field_write_barrier(mrb_state *mrb, struct RBasic *obj, struct RBasic *value)
+{
+ mrb_gc *gc = &mrb->gc;
+
+ if (!is_black(obj)) return;
+ if (!is_white(value)) return;
+
+ mrb_assert(gc->state == MRB_GC_STATE_MARK || (!is_dead(gc, value) && !is_dead(gc, obj)));
+ mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT);
+
+ if (is_generational(gc) || gc->state == MRB_GC_STATE_MARK) {
+ add_gray_list(mrb, gc, value);
+ }
+ else {
+ mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
+ paint_partial_white(gc, obj); /* for never write barriers */
+ }
+}
+
+/*
+ * Write barrier
+ * Paint obj(Black) to obj(Gray).
+ *
+ * The object that is painted gray will be traversed atomically in final
+ * mark phase. So you use this write barrier if it's frequency written spot.
+ * e.g. Set element on Array.
+ */
+
+MRB_API void
+mrb_write_barrier(mrb_state *mrb, struct RBasic *obj)
+{
+ mrb_gc *gc = &mrb->gc;
+
+ if (!is_black(obj)) return;
+
+ mrb_assert(!is_dead(gc, obj));
+ mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT);
+ paint_gray(obj);
+ obj->gcnext = gc->atomic_gray_list;
+ gc->atomic_gray_list = obj;
+}
+
+/*
+ * call-seq:
+ * GC.start -> nil
+ *
+ * Initiates full garbage collection.
+ *
+ */
+
+static mrb_value
+gc_start(mrb_state *mrb, mrb_value obj)
+{
+ mrb_full_gc(mrb);
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * GC.enable -> true or false
+ *
+ * Enables garbage collection, returning <code>true</code> if garbage
+ * collection was previously disabled.
+ *
+ * GC.disable #=> false
+ * GC.enable #=> true
+ * GC.enable #=> false
+ *
+ */
+
+static mrb_value
+gc_enable(mrb_state *mrb, mrb_value obj)
+{
+ mrb_bool old = mrb->gc.disabled;
+
+ mrb->gc.disabled = FALSE;
+
+ return mrb_bool_value(old);
+}
+
+/*
+ * call-seq:
+ * GC.disable -> true or false
+ *
+ * Disables garbage collection, returning <code>true</code> if garbage
+ * collection was already disabled.
+ *
+ * GC.disable #=> false
+ * GC.disable #=> true
+ *
+ */
+
+static mrb_value
+gc_disable(mrb_state *mrb, mrb_value obj)
+{
+ mrb_bool old = mrb->gc.disabled;
+
+ mrb->gc.disabled = TRUE;
+
+ return mrb_bool_value(old);
+}
+
+/*
+ * call-seq:
+ * GC.interval_ratio -> fixnum
+ *
+ * Returns ratio of GC interval. Default value is 200(%).
+ *
+ */
+
+static mrb_value
+gc_interval_ratio_get(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_fixnum_value(mrb->gc.interval_ratio);
+}
+
+/*
+ * call-seq:
+ * GC.interval_ratio = fixnum -> nil
+ *
+ * Updates ratio of GC interval. Default value is 200(%).
+ * GC start as soon as after end all step of GC if you set 100(%).
+ *
+ */
+
+static mrb_value
+gc_interval_ratio_set(mrb_state *mrb, mrb_value obj)
+{
+ mrb_int ratio;
+
+ mrb_get_args(mrb, "i", &ratio);
+ mrb->gc.interval_ratio = ratio;
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * GC.step_ratio -> fixnum
+ *
+ * Returns step span ratio of Incremental GC. Default value is 200(%).
+ *
+ */
+
+static mrb_value
+gc_step_ratio_get(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_fixnum_value(mrb->gc.step_ratio);
+}
+
+/*
+ * call-seq:
+ * GC.step_ratio = fixnum -> nil
+ *
+ * Updates step span ratio of Incremental GC. Default value is 200(%).
+ * 1 step of incrementalGC becomes long if a rate is big.
+ *
+ */
+
+static mrb_value
+gc_step_ratio_set(mrb_state *mrb, mrb_value obj)
+{
+ mrb_int ratio;
+
+ mrb_get_args(mrb, "i", &ratio);
+ mrb->gc.step_ratio = ratio;
+ return mrb_nil_value();
+}
+
+static void
+change_gen_gc_mode(mrb_state *mrb, mrb_gc *gc, mrb_bool enable)
+{
+ if (gc->disabled || gc->iterating) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "generational mode changed when GC disabled");
+ return;
+ }
+ if (is_generational(gc) && !enable) {
+ clear_all_old(mrb, gc);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+ gc->full = FALSE;
+ }
+ else if (!is_generational(gc) && enable) {
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
+ gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+ gc->full = FALSE;
+ }
+ gc->generational = enable;
+}
+
+/*
+ * call-seq:
+ * GC.generational_mode -> true or false
+ *
+ * Returns generational or normal gc mode.
+ *
+ */
+
+static mrb_value
+gc_generational_mode_get(mrb_state *mrb, mrb_value self)
+{
+ return mrb_bool_value(mrb->gc.generational);
+}
+
+/*
+ * call-seq:
+ * GC.generational_mode = true or false -> true or false
+ *
+ * Changes to generational or normal gc mode.
+ *
+ */
+
+static mrb_value
+gc_generational_mode_set(mrb_state *mrb, mrb_value self)
+{
+ mrb_bool enable;
+
+ mrb_get_args(mrb, "b", &enable);
+ if (mrb->gc.generational != enable)
+ change_gen_gc_mode(mrb, &mrb->gc, enable);
+
+ return mrb_bool_value(enable);
+}
+
+
+static void
+gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void *data)
+{
+ mrb_heap_page* page;
+
+ mrb_full_gc(mrb);
+ page = gc->heaps;
+ while (page != NULL) {
+ RVALUE *p;
+ int i;
+
+ p = objects(page);
+ for (i=0; i < MRB_HEAP_PAGE_SIZE; i++) {
+ if ((*callback)(mrb, &p[i].as.basic, data) == MRB_EACH_OBJ_BREAK)
+ return;
+ }
+ page = page->next;
+ }
+}
+
+void
+mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data)
+{
+ mrb_bool iterating = mrb->gc.iterating;
+
+ mrb->gc.iterating = TRUE;
+ if (iterating) {
+ gc_each_objects(mrb, &mrb->gc, callback, data);
+ }
+ else {
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ gc_each_objects(mrb, &mrb->gc, callback, data);
+ mrb->jmp = prev_jmp;
+ mrb->gc.iterating = iterating;
+ } MRB_CATCH(&c_jmp) {
+ mrb->gc.iterating = iterating;
+ mrb->jmp = prev_jmp;
+ MRB_THROW(prev_jmp);
+ } MRB_END_EXC(&c_jmp);
+ }
+}
+
+#ifdef GC_TEST
+#ifdef GC_DEBUG
+static mrb_value gc_test(mrb_state *, mrb_value);
+#endif
+#endif
+
+void
+mrb_init_gc(mrb_state *mrb)
+{
+ struct RClass *gc;
+
+ gc = mrb_define_module(mrb, "GC");
+
+ mrb_define_class_method(mrb, gc, "start", gc_start, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, gc, "enable", gc_enable, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, gc, "disable", gc_disable, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, gc, "interval_ratio", gc_interval_ratio_get, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, gc, "interval_ratio=", gc_interval_ratio_set, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, gc, "step_ratio", gc_step_ratio_get, MRB_ARGS_NONE());
+ mrb_define_class_method(mrb, gc, "step_ratio=", gc_step_ratio_set, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, gc, "generational_mode=", gc_generational_mode_set, MRB_ARGS_REQ(1));
+ mrb_define_class_method(mrb, gc, "generational_mode", gc_generational_mode_get, MRB_ARGS_NONE());
+#ifdef GC_TEST
+#ifdef GC_DEBUG
+ mrb_define_class_method(mrb, gc, "test", gc_test, MRB_ARGS_NONE());
+#endif
+#endif
+}
+
+#ifdef GC_TEST
+#ifdef GC_DEBUG
+void
+test_mrb_field_write_barrier(void)
+{
+ mrb_state *mrb = mrb_open();
+ struct RBasic *obj, *value;
+ mrb_gc *gc = &mrb->gc;
+
+ puts("test_mrb_field_write_barrier");
+ gc->generational = FALSE;
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
+ value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value"));
+ paint_black(obj);
+ paint_partial_white(gc, value);
+
+
+ puts(" in MRB_GC_STATE_MARK");
+ gc->state = MRB_GC_STATE_MARK;
+ mrb_field_write_barrier(mrb, obj, value);
+
+ mrb_assert(is_gray(value));
+
+
+ puts(" in MRB_GC_STATE_SWEEP");
+ paint_partial_white(gc, value);
+ gc->state = MRB_GC_STATE_SWEEP;
+ mrb_field_write_barrier(mrb, obj, value);
+
+ mrb_assert(obj->color & gc->current_white_part);
+ mrb_assert(value->color & gc->current_white_part);
+
+
+ puts(" fail with black");
+ gc->state = MRB_GC_STATE_MARK;
+ paint_white(obj);
+ paint_partial_white(gc, value);
+ mrb_field_write_barrier(mrb, obj, value);
+
+ mrb_assert(obj->color & gc->current_white_part);
+
+
+ puts(" fail with gray");
+ gc->state = MRB_GC_STATE_MARK;
+ paint_black(obj);
+ paint_gray(value);
+ mrb_field_write_barrier(mrb, obj, value);
+
+ mrb_assert(is_gray(value));
+
+
+ {
+ puts("test_mrb_field_write_barrier_value");
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
+ mrb_value value = mrb_str_new_lit(mrb, "value");
+ paint_black(obj);
+ paint_partial_white(gc, mrb_basic_ptr(value));
+
+ gc->state = MRB_GC_STATE_MARK;
+ mrb_field_write_barrier_value(mrb, obj, value);
+
+ mrb_assert(is_gray(mrb_basic_ptr(value)));
+ }
+
+ mrb_close(mrb);
+}
+
+void
+test_mrb_write_barrier(void)
+{
+ mrb_state *mrb = mrb_open();
+ struct RBasic *obj;
+ mrb_gc *gc = &mrb->gc;
+
+ puts("test_mrb_write_barrier");
+ obj = mrb_basic_ptr(mrb_ary_new(mrb));
+ paint_black(obj);
+
+ puts(" in MRB_GC_STATE_MARK");
+ gc->state = MRB_GC_STATE_MARK;
+ mrb_write_barrier(mrb, obj);
+
+ mrb_assert(is_gray(obj));
+ mrb_assert(gc->atomic_gray_list == obj);
+
+
+ puts(" fail with gray");
+ paint_gray(obj);
+ mrb_write_barrier(mrb, obj);
+
+ mrb_assert(is_gray(obj));
+
+ mrb_close(mrb);
+}
+
+void
+test_add_gray_list(void)
+{
+ mrb_state *mrb = mrb_open();
+ struct RBasic *obj1, *obj2;
+ mrb_gc *gc = &mrb->gc;
+
+ puts("test_add_gray_list");
+ change_gen_gc_mode(mrb, gc, FALSE);
+ mrb_assert(gc->gray_list == NULL);
+ obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
+ add_gray_list(mrb, gc, obj1);
+ mrb_assert(gc->gray_list == obj1);
+ mrb_assert(is_gray(obj1));
+
+ obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
+ add_gray_list(mrb, gc, obj2);
+ mrb_assert(gc->gray_list == obj2);
+ mrb_assert(gc->gray_list->gcnext == obj1);
+ mrb_assert(is_gray(obj2));
+
+ mrb_close(mrb);
+}
+
+void
+test_gc_gray_mark(void)
+{
+ mrb_state *mrb = mrb_open();
+ mrb_value obj_v, value_v;
+ struct RBasic *obj;
+ size_t gray_num = 0;
+ mrb_gc *gc = &mrb->gc;
+
+ puts("test_gc_gray_mark");
+
+ puts(" in MRB_TT_CLASS");
+ obj = (struct RBasic*)mrb->object_class;
+ paint_gray(obj);
+ gray_num = gc_gray_mark(mrb, gc, obj);
+ mrb_assert(is_black(obj));
+ mrb_assert(gray_num > 1);
+
+ puts(" in MRB_TT_ARRAY");
+ obj_v = mrb_ary_new(mrb);
+ value_v = mrb_str_new_lit(mrb, "test");
+ paint_gray(mrb_basic_ptr(obj_v));
+ paint_partial_white(gc, mrb_basic_ptr(value_v));
+ mrb_ary_push(mrb, obj_v, value_v);
+ gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v));
+ mrb_assert(is_black(mrb_basic_ptr(obj_v)));
+ mrb_assert(is_gray(mrb_basic_ptr(value_v)));
+ mrb_assert(gray_num == 1);
+
+ mrb_close(mrb);
+}
+
+void
+test_incremental_gc(void)
+{
+ mrb_state *mrb = mrb_open();
+ size_t max = ~0, live = 0, total = 0, freed = 0;
+ RVALUE *free;
+ mrb_heap_page *page;
+ mrb_gc *gc = &mrb->gc;
+
+ puts("test_incremental_gc");
+ change_gen_gc_mode(mrb, gc, FALSE);
+
+ puts(" in mrb_full_gc");
+ mrb_full_gc(mrb);
+
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+ puts(" in MRB_GC_STATE_ROOT");
+ incremental_gc(mrb, gc, max);
+ mrb_assert(gc->state == MRB_GC_STATE_MARK);
+ puts(" in MRB_GC_STATE_MARK");
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
+ mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
+
+ puts(" in MRB_GC_STATE_SWEEP");
+ page = gc->heaps;
+ while (page) {
+ RVALUE *p = objects(page);
+ RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
+ while (p<e) {
+ if (is_black(&p->as.basic)) {
+ live++;
+ }
+ if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) {
+ printf("%p\n", &p->as.basic);
+ }
+ p++;
+ }
+ page = page->next;
+ total += MRB_HEAP_PAGE_SIZE;
+ }
+
+ mrb_assert(gc->gray_list == NULL);
+
+ incremental_gc(mrb, gc, max);
+ mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
+
+ incremental_gc(mrb, gc, max);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+
+ free = (RVALUE*)gc->heaps->freelist;
+ while (free) {
+ freed++;
+ free = (RVALUE*)free->as.free.next;
+ }
+
+ mrb_assert(gc->live == live);
+ mrb_assert(gc->live == total-freed);
+
+ puts("test_incremental_gc(gen)");
+ incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
+ change_gen_gc_mode(mrb, gc, TRUE);
+
+ mrb_assert(gc->full == FALSE);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+
+ puts(" in minor");
+ mrb_assert(is_minor_gc(gc));
+ mrb_assert(gc->majorgc_old_threshold > 0);
+ gc->majorgc_old_threshold = 0;
+ mrb_incremental_gc(mrb);
+ mrb_assert(gc->full == TRUE);
+ mrb_assert(gc->state == MRB_GC_STATE_ROOT);
+
+ puts(" in major");
+ mrb_assert(is_major_gc(gc));
+ do {
+ mrb_incremental_gc(mrb);
+ } while (gc->state != MRB_GC_STATE_ROOT);
+ mrb_assert(gc->full == FALSE);
+
+ mrb_close(mrb);
+}
+
+void
+test_incremental_sweep_phase(void)
+{
+ mrb_state *mrb = mrb_open();
+ mrb_gc *gc = &mrb->gc;
+
+ puts("test_incremental_sweep_phase");
+
+ add_heap(mrb, gc);
+ gc->sweeps = gc->heaps;
+
+ mrb_assert(gc->heaps->next->next == NULL);
+ mrb_assert(gc->free_heaps->next->next == NULL);
+ incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3);
+
+ mrb_assert(gc->heaps->next == NULL);
+ mrb_assert(gc->heaps == gc->free_heaps);
+
+ mrb_close(mrb);
+}
+
+static mrb_value
+gc_test(mrb_state *mrb, mrb_value self)
+{
+ test_mrb_field_write_barrier();
+ test_mrb_write_barrier();
+ test_add_gray_list();
+ test_gc_gray_mark();
+ test_incremental_gc();
+ test_incremental_sweep_phase();
+ return mrb_nil_value();
+}
+#endif /* GC_DEBUG */
+#endif /* GC_TEST */
diff --git a/web/server/h2o/libh2o/deps/mruby/src/hash.c b/web/server/h2o/libh2o/deps/mruby/src/hash.c
new file mode 100644
index 00000000..93d55018
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/hash.c
@@ -0,0 +1,905 @@
+/*
+** hash.c - Hash class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/hash.h>
+#include <mruby/khash.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+
+/* a function to get hash value of a float number */
+mrb_int mrb_float_id(mrb_float f);
+
+static inline khint_t
+mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
+{
+ enum mrb_vtype t = mrb_type(key);
+ mrb_value hv;
+ khint_t h;
+
+ switch (t) {
+ case MRB_TT_STRING:
+ h = mrb_str_hash(mrb, key);
+ break;
+
+ case MRB_TT_TRUE:
+ case MRB_TT_FALSE:
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ h = (khint_t)mrb_obj_id(key);
+ break;
+
+ default:
+ hv = mrb_funcall(mrb, key, "hash", 0);
+ h = (khint_t)t ^ mrb_fixnum(hv);
+ break;
+ }
+ return kh_int_hash_func(mrb, h);
+}
+
+static inline khint_t
+mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ enum mrb_vtype t = mrb_type(a);
+
+ switch (t) {
+ case MRB_TT_STRING:
+ return mrb_str_equal(mrb, a, b);
+
+ case MRB_TT_SYMBOL:
+ if (mrb_type(b) != MRB_TT_SYMBOL) return FALSE;
+ return mrb_symbol(a) == mrb_symbol(b);
+
+ case MRB_TT_FIXNUM:
+ switch (mrb_type(b)) {
+ case MRB_TT_FIXNUM:
+ return mrb_fixnum(a) == mrb_fixnum(b);
+ case MRB_TT_FLOAT:
+ return (mrb_float)mrb_fixnum(a) == mrb_float(b);
+ default:
+ return FALSE;
+ }
+
+ case MRB_TT_FLOAT:
+ switch (mrb_type(b)) {
+ case MRB_TT_FIXNUM:
+ return mrb_float(a) == (mrb_float)mrb_fixnum(b);
+ case MRB_TT_FLOAT:
+ return mrb_float(a) == mrb_float(b);
+ default:
+ return FALSE;
+ }
+
+ default:
+ return mrb_eql(mrb, a, b);
+ }
+}
+
+KHASH_DEFINE (ht, mrb_value, mrb_hash_value, TRUE, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal)
+
+static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
+
+static inline mrb_value
+mrb_hash_ht_key(mrb_state *mrb, mrb_value key)
+{
+ if (mrb_string_p(key) && !MRB_FROZEN_P(mrb_str_ptr(key))) {
+ key = mrb_str_dup(mrb, key);
+ MRB_SET_FROZEN_FLAG(mrb_str_ptr(key));
+ }
+ return key;
+}
+
+#define KEY(key) mrb_hash_ht_key(mrb, key)
+
+void
+mrb_gc_mark_hash(mrb_state *mrb, struct RHash *hash)
+{
+ khiter_t k;
+ khash_t(ht) *h = hash->ht;
+
+ if (!h) return;
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ mrb_value key = kh_key(h, k);
+ mrb_value val = kh_value(h, k).v;
+
+ mrb_gc_mark_value(mrb, key);
+ mrb_gc_mark_value(mrb, val);
+ }
+ }
+}
+
+size_t
+mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash)
+{
+ if (!hash->ht) return 0;
+ return kh_size(hash->ht)*2;
+}
+
+void
+mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash)
+{
+ if (hash->ht) kh_destroy(ht, mrb, hash->ht);
+}
+
+
+MRB_API mrb_value
+mrb_hash_new_capa(mrb_state *mrb, mrb_int capa)
+{
+ struct RHash *h;
+
+ h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
+ /* khash needs 1/4 empty space so it is not resized immediately */
+ h->ht = kh_init_size(ht, mrb, capa*4/3);
+ h->iv = 0;
+ return mrb_obj_value(h);
+}
+
+MRB_API mrb_value
+mrb_hash_new(mrb_state *mrb)
+{
+ return mrb_hash_new_capa(mrb, 0);
+}
+
+static mrb_value mrb_hash_default(mrb_state *mrb, mrb_value hash);
+static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key);
+
+MRB_API mrb_value
+mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+ khiter_t k;
+ mrb_sym mid;
+
+ if (h) {
+ k = kh_get(ht, mrb, h, key);
+ if (k != kh_end(h))
+ return kh_value(h, k).v;
+ }
+
+ mid = mrb_intern_lit(mrb, "default");
+ if (mrb_func_basic_p(mrb, hash, mid, mrb_hash_default)) {
+ return hash_default(mrb, hash, key);
+ }
+ /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */
+ return mrb_funcall_argv(mrb, hash, mid, 1, &key);
+}
+
+MRB_API mrb_value
+mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+ khiter_t k;
+
+ if (h) {
+ k = kh_get(ht, mrb, h, key);
+ if (k != kh_end(h))
+ return kh_value(h, k).v;
+ }
+
+ /* not found */
+ return def;
+}
+
+MRB_API void
+mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val)
+{
+ khash_t(ht) *h;
+ khiter_t k;
+ int r;
+
+ mrb_hash_modify(mrb, hash);
+ h = RHASH_TBL(hash);
+
+ if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb);
+ k = kh_put2(ht, mrb, h, key, &r);
+ kh_value(h, k).v = val;
+
+ if (r != 0) {
+ /* expand */
+ int ai = mrb_gc_arena_save(mrb);
+ key = kh_key(h, k) = KEY(key);
+ mrb_gc_arena_restore(mrb, ai);
+ kh_value(h, k).n = kh_size(h)-1;
+ }
+
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), key);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)RHASH(hash), val);
+ return;
+}
+
+static mrb_value
+mrb_hash_dup(mrb_state *mrb, mrb_value hash)
+{
+ struct RHash* ret;
+ khash_t(ht) *h, *ret_h;
+ khiter_t k, ret_k;
+ mrb_value ifnone, vret;
+
+ h = RHASH_TBL(hash);
+ ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
+ ret->ht = kh_init(ht, mrb);
+
+ if (h && kh_size(h) > 0) {
+ ret_h = ret->ht;
+
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ int ai = mrb_gc_arena_save(mrb);
+ ret_k = kh_put(ht, mrb, ret_h, KEY(kh_key(h, k)));
+ mrb_gc_arena_restore(mrb, ai);
+ kh_val(ret_h, ret_k).v = kh_val(h, k).v;
+ kh_val(ret_h, ret_k).n = kh_size(ret_h)-1;
+ }
+ }
+ }
+
+ if (MRB_RHASH_DEFAULT_P(hash)) {
+ ret->flags |= MRB_HASH_DEFAULT;
+ }
+ if (MRB_RHASH_PROCDEFAULT_P(hash)) {
+ ret->flags |= MRB_HASH_PROC_DEFAULT;
+ }
+ vret = mrb_obj_value(ret);
+ ifnone = RHASH_IFNONE(hash);
+ if (!mrb_nil_p(ifnone)) {
+ mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone);
+ }
+ return vret;
+}
+
+MRB_API mrb_value
+mrb_check_hash_type(mrb_state *mrb, mrb_value hash)
+{
+ return mrb_check_convert_type(mrb, hash, MRB_TT_HASH, "Hash", "to_hash");
+}
+
+MRB_API khash_t(ht)*
+mrb_hash_tbl(mrb_state *mrb, mrb_value hash)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+
+ if (!h) {
+ return RHASH_TBL(hash) = kh_init(ht, mrb);
+ }
+ return h;
+}
+
+static void
+mrb_hash_modify(mrb_state *mrb, mrb_value hash)
+{
+ if (MRB_FROZEN_P(mrb_hash_ptr(hash))) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen hash");
+ }
+ mrb_hash_tbl(mrb, hash);
+}
+
+/* 15.2.13.4.16 */
+/*
+ * call-seq:
+ * Hash.new -> new_hash
+ * Hash.new(obj) -> new_hash
+ * Hash.new {|hash, key| block } -> new_hash
+ *
+ * Returns a new, empty hash. If this hash is subsequently accessed by
+ * a key that doesn't correspond to a hash entry, the value returned
+ * depends on the style of <code>new</code> used to create the hash. In
+ * the first form, the access returns <code>nil</code>. If
+ * <i>obj</i> is specified, this single object will be used for
+ * all <em>default values</em>. If a block is specified, it will be
+ * called with the hash object and the key, and should return the
+ * default value. It is the block's responsibility to store the value
+ * in the hash if required.
+ *
+ * h = Hash.new("Go Fish")
+ * h["a"] = 100
+ * h["b"] = 200
+ * h["a"] #=> 100
+ * h["c"] #=> "Go Fish"
+ * # The following alters the single default object
+ * h["c"].upcase! #=> "GO FISH"
+ * h["d"] #=> "GO FISH"
+ * h.keys #=> ["a", "b"]
+ *
+ * # While this creates a new default object each time
+ * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
+ * h["c"] #=> "Go Fish: c"
+ * h["c"].upcase! #=> "GO FISH: C"
+ * h["d"] #=> "Go Fish: d"
+ * h.keys #=> ["c", "d"]
+ *
+ */
+
+static mrb_value
+mrb_hash_init(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value block, ifnone;
+ mrb_bool ifnone_p;
+
+ ifnone = mrb_nil_value();
+ mrb_get_args(mrb, "&|o?", &block, &ifnone, &ifnone_p);
+ mrb_hash_modify(mrb, hash);
+ if (!mrb_nil_p(block)) {
+ if (ifnone_p) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ }
+ RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
+ ifnone = block;
+ }
+ if (!mrb_nil_p(ifnone)) {
+ RHASH(hash)->flags |= MRB_HASH_DEFAULT;
+ mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
+ }
+ return hash;
+}
+
+/* 15.2.13.4.2 */
+/*
+ * call-seq:
+ * hsh[key] -> value
+ *
+ * Element Reference---Retrieves the <i>value</i> object corresponding
+ * to the <i>key</i> object. If not found, returns the default value (see
+ * <code>Hash::new</code> for details).
+ *
+ * h = { "a" => 100, "b" => 200 }
+ * h["a"] #=> 100
+ * h["c"] #=> nil
+ *
+ */
+static mrb_value
+mrb_hash_aget(mrb_state *mrb, mrb_value self)
+{
+ mrb_value key;
+
+ mrb_get_args(mrb, "o", &key);
+ return mrb_hash_get(mrb, self, key);
+}
+
+static mrb_value
+hash_default(mrb_state *mrb, mrb_value hash, mrb_value key)
+{
+ if (MRB_RHASH_DEFAULT_P(hash)) {
+ if (MRB_RHASH_PROCDEFAULT_P(hash)) {
+ return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
+ }
+ else {
+ return RHASH_IFNONE(hash);
+ }
+ }
+ return mrb_nil_value();
+}
+
+/* 15.2.13.4.5 */
+/*
+ * call-seq:
+ * hsh.default(key=nil) -> obj
+ *
+ * Returns the default value, the value that would be returned by
+ * <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
+ * See also <code>Hash::new</code> and <code>Hash#default=</code>.
+ *
+ * h = Hash.new #=> {}
+ * h.default #=> nil
+ * h.default(2) #=> nil
+ *
+ * h = Hash.new("cat") #=> {}
+ * h.default #=> "cat"
+ * h.default(2) #=> "cat"
+ *
+ * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {}
+ * h.default #=> nil
+ * h.default(2) #=> 20
+ */
+
+static mrb_value
+mrb_hash_default(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value key;
+ mrb_bool given;
+
+ mrb_get_args(mrb, "|o?", &key, &given);
+ if (MRB_RHASH_DEFAULT_P(hash)) {
+ if (MRB_RHASH_PROCDEFAULT_P(hash)) {
+ if (!given) return mrb_nil_value();
+ return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
+ }
+ else {
+ return RHASH_IFNONE(hash);
+ }
+ }
+ return mrb_nil_value();
+}
+
+/* 15.2.13.4.6 */
+/*
+ * call-seq:
+ * hsh.default = obj -> obj
+ *
+ * Sets the default value, the value returned for a key that does not
+ * exist in the hash. It is not possible to set the default to a
+ * <code>Proc</code> that will be executed on each key lookup.
+ *
+ * h = { "a" => 100, "b" => 200 }
+ * h.default = "Go fish"
+ * h["a"] #=> 100
+ * h["z"] #=> "Go fish"
+ * # This doesn't do what you might hope...
+ * h.default = proc do |hash, key|
+ * hash[key] = key + key
+ * end
+ * h[2] #=> #<Proc:0x401b3948@-:6>
+ * h["cat"] #=> #<Proc:0x401b3948@-:6>
+ */
+
+static mrb_value
+mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value ifnone;
+
+ mrb_get_args(mrb, "o", &ifnone);
+ mrb_hash_modify(mrb, hash);
+ mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
+ RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT;
+ if (!mrb_nil_p(ifnone)) {
+ RHASH(hash)->flags |= MRB_HASH_DEFAULT;
+ }
+ else {
+ RHASH(hash)->flags &= ~MRB_HASH_DEFAULT;
+ }
+ return ifnone;
+}
+
+/* 15.2.13.4.7 */
+/*
+ * call-seq:
+ * hsh.default_proc -> anObject
+ *
+ * If <code>Hash::new</code> was invoked with a block, return that
+ * block, otherwise return <code>nil</code>.
+ *
+ * h = Hash.new {|h,k| h[k] = k*k } #=> {}
+ * p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
+ * a = [] #=> []
+ * p.call(a, 2)
+ * a #=> [nil, nil, 4]
+ */
+
+
+static mrb_value
+mrb_hash_default_proc(mrb_state *mrb, mrb_value hash)
+{
+ if (MRB_RHASH_PROCDEFAULT_P(hash)) {
+ return RHASH_PROCDEFAULT(hash);
+ }
+ return mrb_nil_value();
+}
+
+/*
+ * call-seq:
+ * hsh.default_proc = proc_obj -> proc_obj
+ *
+ * Sets the default proc to be executed on each key lookup.
+ *
+ * h.default_proc = proc do |hash, key|
+ * hash[key] = key + key
+ * end
+ * h[2] #=> 4
+ * h["cat"] #=> "catcat"
+ */
+
+static mrb_value
+mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value ifnone;
+
+ mrb_get_args(mrb, "o", &ifnone);
+ mrb_hash_modify(mrb, hash);
+ mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
+ if (!mrb_nil_p(ifnone)) {
+ RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
+ RHASH(hash)->flags |= MRB_HASH_DEFAULT;
+ }
+ else {
+ RHASH(hash)->flags &= ~MRB_HASH_DEFAULT;
+ RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT;
+ }
+
+ return ifnone;
+}
+
+MRB_API mrb_value
+mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+ khiter_t k;
+ mrb_value delVal;
+ mrb_int n;
+
+ if (h) {
+ k = kh_get(ht, mrb, h, key);
+ if (k != kh_end(h)) {
+ delVal = kh_value(h, k).v;
+ n = kh_value(h, k).n;
+ kh_del(ht, mrb, h, k);
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (!kh_exist(h, k)) continue;
+ if (kh_value(h, k).n > n) kh_value(h, k).n--;
+ }
+ return delVal;
+ }
+ }
+
+ /* not found */
+ return mrb_nil_value();
+}
+
+/* 15.2.13.4.8 */
+/*
+ * call-seq:
+ * hsh.delete(key) -> value
+ * hsh.delete(key) {| key | block } -> value
+ *
+ * Deletes and returns a key-value pair from <i>hsh</i> whose key is
+ * equal to <i>key</i>. If the key is not found, returns the
+ * <em>default value</em>. If the optional code block is given and the
+ * key is not found, pass in the key and return the result of
+ * <i>block</i>.
+ *
+ * h = { "a" => 100, "b" => 200 }
+ * h.delete("a") #=> 100
+ * h.delete("z") #=> nil
+ * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
+ *
+ */
+static mrb_value
+mrb_hash_delete(mrb_state *mrb, mrb_value self)
+{
+ mrb_value key;
+
+ mrb_get_args(mrb, "o", &key);
+ mrb_hash_modify(mrb, self);
+ return mrb_hash_delete_key(mrb, self, key);
+}
+
+/* 15.2.13.4.24 */
+/*
+ * call-seq:
+ * hsh.shift -> anArray or obj
+ *
+ * Removes a key-value pair from <i>hsh</i> and returns it as the
+ * two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
+ * the hash's default value if the hash is empty.
+ *
+ * h = { 1 => "a", 2 => "b", 3 => "c" }
+ * h.shift #=> [1, "a"]
+ * h #=> {2=>"b", 3=>"c"}
+ */
+
+static mrb_value
+mrb_hash_shift(mrb_state *mrb, mrb_value hash)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+ khiter_t k;
+ mrb_value delKey, delVal;
+
+ mrb_hash_modify(mrb, hash);
+ if (h && kh_size(h) > 0) {
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (!kh_exist(h, k)) continue;
+
+ delKey = kh_key(h, k);
+ mrb_gc_protect(mrb, delKey);
+ delVal = mrb_hash_delete_key(mrb, hash, delKey);
+ mrb_gc_protect(mrb, delVal);
+
+ return mrb_assoc_new(mrb, delKey, delVal);
+ }
+ }
+
+ if (MRB_RHASH_DEFAULT_P(hash)) {
+ if (MRB_RHASH_PROCDEFAULT_P(hash)) {
+ return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value());
+ }
+ else {
+ return RHASH_IFNONE(hash);
+ }
+ }
+ return mrb_nil_value();
+}
+
+/* 15.2.13.4.4 */
+/*
+ * call-seq:
+ * hsh.clear -> hsh
+ *
+ * Removes all key-value pairs from `hsh`.
+ *
+ * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
+ * h.clear #=> {}
+ *
+ */
+
+MRB_API mrb_value
+mrb_hash_clear(mrb_state *mrb, mrb_value hash)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+
+ mrb_hash_modify(mrb, hash);
+ if (h) kh_clear(ht, mrb, h);
+ return hash;
+}
+
+/* 15.2.13.4.3 */
+/* 15.2.13.4.26 */
+/*
+ * call-seq:
+ * hsh[key] = value -> value
+ * hsh.store(key, value) -> value
+ *
+ * Element Assignment---Associates the value given by
+ * <i>value</i> with the key given by <i>key</i>.
+ * <i>key</i> should not have its value changed while it is in
+ * use as a key (a <code>String</code> passed as a key will be
+ * duplicated and frozen).
+ *
+ * h = { "a" => 100, "b" => 200 }
+ * h["a"] = 9
+ * h["c"] = 4
+ * h #=> {"a"=>9, "b"=>200, "c"=>4}
+ *
+ */
+static mrb_value
+mrb_hash_aset(mrb_state *mrb, mrb_value self)
+{
+ mrb_value key, val;
+
+ mrb_get_args(mrb, "oo", &key, &val);
+ mrb_hash_set(mrb, self, key, val);
+ return val;
+}
+
+/* 15.2.13.4.20 */
+/* 15.2.13.4.25 */
+/*
+ * call-seq:
+ * hsh.length -> fixnum
+ * hsh.size -> fixnum
+ *
+ * Returns the number of key-value pairs in the hash.
+ *
+ * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
+ * h.length #=> 4
+ * h.delete("a") #=> 200
+ * h.length #=> 3
+ */
+static mrb_value
+mrb_hash_size_m(mrb_state *mrb, mrb_value self)
+{
+ khash_t(ht) *h = RHASH_TBL(self);
+
+ if (!h) return mrb_fixnum_value(0);
+ return mrb_fixnum_value(kh_size(h));
+}
+
+/* 15.2.13.4.12 */
+/*
+ * call-seq:
+ * hsh.empty? -> true or false
+ *
+ * Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
+ *
+ * {}.empty? #=> true
+ *
+ */
+MRB_API mrb_value
+mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
+{
+ khash_t(ht) *h = RHASH_TBL(self);
+
+ if (h) return mrb_bool_value(kh_size(h) == 0);
+ return mrb_true_value();
+}
+
+/* 15.2.13.4.29 (x)*/
+/*
+ * call-seq:
+ * hsh.to_hash => hsh
+ *
+ * Returns +self+.
+ */
+
+static mrb_value
+mrb_hash_to_hash(mrb_state *mrb, mrb_value hash)
+{
+ return hash;
+}
+
+/* 15.2.13.4.19 */
+/*
+ * call-seq:
+ * hsh.keys -> array
+ *
+ * Returns a new array populated with the keys from this hash. See also
+ * <code>Hash#values</code>.
+ *
+ * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
+ * h.keys #=> ["a", "b", "c", "d"]
+ *
+ */
+
+MRB_API mrb_value
+mrb_hash_keys(mrb_state *mrb, mrb_value hash)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+ khiter_t k;
+ mrb_int end;
+ mrb_value ary;
+ mrb_value *p;
+
+ if (!h || kh_size(h) == 0) return mrb_ary_new(mrb);
+ ary = mrb_ary_new_capa(mrb, kh_size(h));
+ end = kh_size(h)-1;
+ mrb_ary_set(mrb, ary, end, mrb_nil_value());
+ p = RARRAY_PTR(ary);
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ mrb_value kv = kh_key(h, k);
+ mrb_hash_value hv = kh_value(h, k);
+
+ if (hv.n <= end) {
+ p[hv.n] = kv;
+ }
+ else {
+ p[end] = kv;
+ }
+ }
+ }
+ return ary;
+}
+
+/* 15.2.13.4.28 */
+/*
+ * call-seq:
+ * hsh.values -> array
+ *
+ * Returns a new array populated with the values from <i>hsh</i>. See
+ * also <code>Hash#keys</code>.
+ *
+ * h = { "a" => 100, "b" => 200, "c" => 300 }
+ * h.values #=> [100, 200, 300]
+ *
+ */
+
+MRB_API mrb_value
+mrb_hash_values(mrb_state *mrb, mrb_value hash)
+{
+ khash_t(ht) *h = RHASH_TBL(hash);
+ khiter_t k;
+ mrb_value ary;
+
+ if (!h) return mrb_ary_new(mrb);
+ ary = mrb_ary_new_capa(mrb, kh_size(h));
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ mrb_hash_value hv = kh_value(h, k);
+
+ mrb_ary_set(mrb, ary, hv.n, hv.v);
+ }
+ }
+ return ary;
+}
+
+/* 15.2.13.4.13 */
+/* 15.2.13.4.15 */
+/* 15.2.13.4.18 */
+/* 15.2.13.4.21 */
+/*
+ * call-seq:
+ * hsh.has_key?(key) -> true or false
+ * hsh.include?(key) -> true or false
+ * hsh.key?(key) -> true or false
+ * hsh.member?(key) -> true or false
+ *
+ * Returns <code>true</code> if the given key is present in <i>hsh</i>.
+ *
+ * h = { "a" => 100, "b" => 200 }
+ * h.has_key?("a") #=> true
+ * h.has_key?("z") #=> false
+ *
+ */
+
+static mrb_value
+mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value key;
+ khash_t(ht) *h;
+ khiter_t k;
+
+ mrb_get_args(mrb, "o", &key);
+
+ h = RHASH_TBL(hash);
+ if (h) {
+ k = kh_get(ht, mrb, h, key);
+ return mrb_bool_value(k != kh_end(h));
+ }
+ return mrb_false_value();
+}
+
+/* 15.2.13.4.14 */
+/* 15.2.13.4.27 */
+/*
+ * call-seq:
+ * hsh.has_value?(value) -> true or false
+ * hsh.value?(value) -> true or false
+ *
+ * Returns <code>true</code> if the given value is present for some key
+ * in <i>hsh</i>.
+ *
+ * h = { "a" => 100, "b" => 200 }
+ * h.has_value?(100) #=> true
+ * h.has_value?(999) #=> false
+ */
+
+static mrb_value
+mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value val;
+ khash_t(ht) *h;
+ khiter_t k;
+
+ mrb_get_args(mrb, "o", &val);
+ h = RHASH_TBL(hash);
+
+ if (h) {
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (!kh_exist(h, k)) continue;
+
+ if (mrb_equal(mrb, kh_value(h, k).v, val)) {
+ return mrb_true_value();
+ }
+ }
+ }
+ return mrb_false_value();
+}
+
+void
+mrb_init_hash(mrb_state *mrb)
+{
+ struct RClass *h;
+
+ mrb->hash_class = h = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */
+ MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
+
+ mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */
+ mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */
+ mrb_define_method(mrb, h, "clear", mrb_hash_clear, MRB_ARGS_NONE()); /* 15.2.13.4.4 */
+ mrb_define_method(mrb, h, "default", mrb_hash_default, MRB_ARGS_ANY()); /* 15.2.13.4.5 */
+ mrb_define_method(mrb, h, "default=", mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6 */
+ mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */
+ mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */
+ mrb_define_method(mrb, h, "__delete", mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */
+ mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, MRB_ARGS_NONE()); /* 15.2.13.4.12 */
+ mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */
+ mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */
+ mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */
+ mrb_define_method(mrb, h, "initialize", mrb_hash_init, MRB_ARGS_OPT(1)); /* 15.2.13.4.16 */
+ mrb_define_method(mrb, h, "key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */
+ mrb_define_method(mrb, h, "keys", mrb_hash_keys, MRB_ARGS_NONE()); /* 15.2.13.4.19 */
+ mrb_define_method(mrb, h, "length", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.20 */
+ mrb_define_method(mrb, h, "member?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */
+ mrb_define_method(mrb, h, "shift", mrb_hash_shift, MRB_ARGS_NONE()); /* 15.2.13.4.24 */
+ mrb_define_method(mrb, h, "dup", mrb_hash_dup, MRB_ARGS_NONE());
+ mrb_define_method(mrb, h, "size", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.25 */
+ mrb_define_method(mrb, h, "store", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */
+ mrb_define_method(mrb, h, "value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */
+ mrb_define_method(mrb, h, "values", mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */
+
+ mrb_define_method(mrb, h, "to_hash", mrb_hash_to_hash, MRB_ARGS_NONE()); /* 15.2.13.4.29 (x)*/
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/init.c b/web/server/h2o/libh2o/deps/mruby/src/init.c
new file mode 100644
index 00000000..afd69975
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/init.c
@@ -0,0 +1,51 @@
+/*
+** init.c - initialize mruby core
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+
+void mrb_init_symtbl(mrb_state*);
+void mrb_init_class(mrb_state*);
+void mrb_init_object(mrb_state*);
+void mrb_init_kernel(mrb_state*);
+void mrb_init_comparable(mrb_state*);
+void mrb_init_enumerable(mrb_state*);
+void mrb_init_symbol(mrb_state*);
+void mrb_init_string(mrb_state*);
+void mrb_init_exception(mrb_state*);
+void mrb_init_proc(mrb_state*);
+void mrb_init_array(mrb_state*);
+void mrb_init_hash(mrb_state*);
+void mrb_init_numeric(mrb_state*);
+void mrb_init_range(mrb_state*);
+void mrb_init_gc(mrb_state*);
+void mrb_init_math(mrb_state*);
+void mrb_init_version(mrb_state*);
+void mrb_init_mrblib(mrb_state*);
+
+#define DONE mrb_gc_arena_restore(mrb, 0);
+void
+mrb_init_core(mrb_state *mrb)
+{
+ mrb_init_symtbl(mrb); DONE;
+
+ mrb_init_class(mrb); DONE;
+ mrb_init_object(mrb); DONE;
+ mrb_init_kernel(mrb); DONE;
+ mrb_init_comparable(mrb); DONE;
+ mrb_init_enumerable(mrb); DONE;
+
+ mrb_init_symbol(mrb); DONE;
+ mrb_init_string(mrb); DONE;
+ mrb_init_exception(mrb); DONE;
+ mrb_init_proc(mrb); DONE;
+ mrb_init_array(mrb); DONE;
+ mrb_init_hash(mrb); DONE;
+ mrb_init_numeric(mrb); DONE;
+ mrb_init_range(mrb); DONE;
+ mrb_init_gc(mrb); DONE;
+ mrb_init_version(mrb); DONE;
+ mrb_init_mrblib(mrb); DONE;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/kernel.c b/web/server/h2o/libh2o/deps/mruby/src/kernel.c
new file mode 100644
index 00000000..4e95ab24
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/kernel.c
@@ -0,0 +1,1238 @@
+/*
+** kernel.c - Kernel module
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/hash.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
+#include <mruby/istruct.h>
+
+typedef enum {
+ NOEX_PUBLIC = 0x00,
+ NOEX_NOSUPER = 0x01,
+ NOEX_PRIVATE = 0x02,
+ NOEX_PROTECTED = 0x04,
+ NOEX_MASK = 0x06,
+ NOEX_BASIC = 0x08,
+ NOEX_UNDEF = NOEX_NOSUPER,
+ NOEX_MODFUNC = 0x12,
+ NOEX_SUPER = 0x20,
+ NOEX_VCALL = 0x40,
+ NOEX_RESPONDS = 0x80
+} mrb_method_flag_t;
+
+MRB_API mrb_bool
+mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func)
+{
+ struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mid);
+ if (MRB_PROC_CFUNC_P(me) && (me->body.func == func))
+ return TRUE;
+ return FALSE;
+}
+
+static mrb_bool
+mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_func_basic_p(mrb, obj, mrb_intern_lit(mrb, "to_s"), mrb_any_to_s);
+}
+
+/* 15.3.1.3.17 */
+/*
+ * call-seq:
+ * obj.inspect -> string
+ *
+ * Returns a string containing a human-readable representation of
+ * <i>obj</i>. If not overridden and no instance variables, uses the
+ * <code>to_s</code> method to generate the string.
+ * <i>obj</i>. If not overridden, uses the <code>to_s</code> method to
+ * generate the string.
+ *
+ * [ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]"
+ * Time.new.inspect #=> "2008-03-08 19:43:39 +0900"
+ */
+MRB_API mrb_value
+mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
+{
+ if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
+ return mrb_obj_iv_inspect(mrb, mrb_obj_ptr(obj));
+ }
+ return mrb_any_to_s(mrb, obj);
+}
+
+/* 15.3.1.3.2 */
+/*
+ * call-seq:
+ * obj === other -> true or false
+ *
+ * Case Equality---For class <code>Object</code>, effectively the same
+ * as calling <code>#==</code>, but typically overridden by descendants
+ * to provide meaningful semantics in <code>case</code> statements.
+ */
+static mrb_value
+mrb_equal_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ return mrb_bool_value(mrb_equal(mrb, self, arg));
+}
+
+/* 15.3.1.3.3 */
+/* 15.3.1.3.33 */
+/*
+ * Document-method: __id__
+ * Document-method: object_id
+ *
+ * call-seq:
+ * obj.__id__ -> fixnum
+ * obj.object_id -> fixnum
+ *
+ * Returns an integer identifier for <i>obj</i>. The same number will
+ * be returned on all calls to <code>id</code> for a given object, and
+ * no two active objects will share an id.
+ * <code>Object#object_id</code> is a different concept from the
+ * <code>:name</code> notation, which returns the symbol id of
+ * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
+ */
+mrb_value
+mrb_obj_id_m(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(mrb_obj_id(self));
+}
+
+/* 15.3.1.2.2 */
+/* 15.3.1.2.5 */
+/* 15.3.1.3.6 */
+/* 15.3.1.3.25 */
+/*
+ * call-seq:
+ * block_given? -> true or false
+ * iterator? -> true or false
+ *
+ * Returns <code>true</code> if <code>yield</code> would execute a
+ * block in the current context. The <code>iterator?</code> form
+ * is mildly deprecated.
+ *
+ * def try
+ * if block_given?
+ * yield
+ * else
+ * "no block"
+ * end
+ * end
+ * try #=> "no block"
+ * try { "hello" } #=> "hello"
+ * try do "hello" end #=> "hello"
+ */
+static mrb_value
+mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+ mrb_value *bp;
+
+ bp = ci->stackent + 1;
+ ci--;
+ if (ci <= mrb->c->cibase) {
+ return mrb_false_value();
+ }
+ /* block_given? called within block; check upper scope */
+ if (ci->proc->env) {
+ struct REnv *e = ci->proc->env;
+
+ while (e->c) {
+ e = (struct REnv*)e->c;
+ }
+ /* top-level does not have block slot (always false) */
+ if (e->stack == mrb->c->stbase)
+ return mrb_false_value();
+ if (e->stack && e->cioff < 0) {
+ /* use saved block arg position */
+ bp = &e->stack[-e->cioff];
+ ci = 0; /* no callinfo available */
+ }
+ else {
+ ci = e->cxt.c->cibase + e->cioff;
+ bp = ci[1].stackent + 1;
+ }
+ }
+ if (ci && ci->argc > 0) {
+ bp += ci->argc;
+ }
+ if (mrb_nil_p(*bp))
+ return mrb_false_value();
+ return mrb_true_value();
+}
+
+/* 15.3.1.3.7 */
+/*
+ * call-seq:
+ * obj.class -> class
+ *
+ * Returns the class of <i>obj</i>. This method must always be
+ * called with an explicit receiver, as <code>class</code> is also a
+ * reserved word in Ruby.
+ *
+ * 1.class #=> Fixnum
+ * self.class #=> Object
+ */
+static mrb_value
+mrb_obj_class_m(mrb_state *mrb, mrb_value self)
+{
+ return mrb_obj_value(mrb_obj_class(mrb, self));
+}
+
+static struct RClass*
+mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
+{
+ struct RClass *klass = mrb_basic_ptr(obj)->c;
+
+ if (klass->tt != MRB_TT_SCLASS)
+ return klass;
+ else {
+ /* copy singleton(unnamed) class */
+ struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
+
+ switch (mrb_type(obj)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_SCLASS:
+ break;
+ default:
+ clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
+ break;
+ }
+ clone->super = klass->super;
+ if (klass->iv) {
+ mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
+ mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj);
+ }
+ if (klass->mt) {
+ clone->mt = kh_copy(mt, mrb, klass->mt);
+ }
+ else {
+ clone->mt = kh_init(mt, mrb);
+ }
+ clone->tt = MRB_TT_SCLASS;
+ return clone;
+ }
+}
+
+static void
+copy_class(mrb_state *mrb, mrb_value dst, mrb_value src)
+{
+ struct RClass *dc = mrb_class_ptr(dst);
+ struct RClass *sc = mrb_class_ptr(src);
+ /* if the origin is not the same as the class, then the origin and
+ the current class need to be copied */
+ if (sc->flags & MRB_FLAG_IS_PREPENDED) {
+ struct RClass *c0 = sc->super;
+ struct RClass *c1 = dc;
+
+ /* copy prepended iclasses */
+ while (!(c0->flags & MRB_FLAG_IS_ORIGIN)) {
+ c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
+ c1 = c1->super;
+ c0 = c0->super;
+ }
+ c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
+ c1->super->flags |= MRB_FLAG_IS_ORIGIN;
+ }
+ if (sc->mt) {
+ dc->mt = kh_copy(mt, mrb, sc->mt);
+ }
+ else {
+ dc->mt = kh_init(mt, mrb);
+ }
+ dc->super = sc->super;
+ MRB_SET_INSTANCE_TT(dc, MRB_INSTANCE_TT(sc));
+}
+
+static void
+init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
+{
+ switch (mrb_type(obj)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ copy_class(mrb, dest, obj);
+ /* fall through */
+ case MRB_TT_OBJECT:
+ case MRB_TT_SCLASS:
+ case MRB_TT_HASH:
+ case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
+ mrb_iv_copy(mrb, dest, obj);
+ break;
+ case MRB_TT_ISTRUCT:
+ mrb_istruct_copy(dest, obj);
+ break;
+
+ default:
+ break;
+ }
+ mrb_funcall(mrb, dest, "initialize_copy", 1, obj);
+}
+
+/* 15.3.1.3.8 */
+/*
+ * call-seq:
+ * obj.clone -> an_object
+ *
+ * Produces a shallow copy of <i>obj</i>---the instance variables of
+ * <i>obj</i> are copied, but not the objects they reference. Copies
+ * the frozen state of <i>obj</i>. See also the discussion
+ * under <code>Object#dup</code>.
+ *
+ * class Klass
+ * attr_accessor :str
+ * end
+ * s1 = Klass.new #=> #<Klass:0x401b3a38>
+ * s1.str = "Hello" #=> "Hello"
+ * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
+ * s2.str[1,4] = "i" #=> "i"
+ * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
+ * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
+ *
+ * This method may have class-specific behavior. If so, that
+ * behavior will be documented under the #+initialize_copy+ method of
+ * the class.
+ *
+ * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone.
+ */
+MRB_API mrb_value
+mrb_obj_clone(mrb_state *mrb, mrb_value self)
+{
+ struct RObject *p;
+ mrb_value clone;
+
+ if (mrb_immediate_p(self)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
+ }
+ if (mrb_type(self) == MRB_TT_SCLASS) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
+ }
+ p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
+ p->c = mrb_singleton_class_clone(mrb, self);
+ mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)p->c);
+ clone = mrb_obj_value(p);
+ init_copy(mrb, clone, self);
+
+ return clone;
+}
+
+/* 15.3.1.3.9 */
+/*
+ * call-seq:
+ * obj.dup -> an_object
+ *
+ * Produces a shallow copy of <i>obj</i>---the instance variables of
+ * <i>obj</i> are copied, but not the objects they reference.
+ * <code>dup</code> copies the frozen state of <i>obj</i>. See also
+ * the discussion under <code>Object#clone</code>. In general,
+ * <code>clone</code> and <code>dup</code> may have different semantics
+ * in descendant classes. While <code>clone</code> is used to duplicate
+ * an object, including its internal state, <code>dup</code> typically
+ * uses the class of the descendant object to create the new instance.
+ *
+ * This method may have class-specific behavior. If so, that
+ * behavior will be documented under the #+initialize_copy+ method of
+ * the class.
+ */
+
+MRB_API mrb_value
+mrb_obj_dup(mrb_state *mrb, mrb_value obj)
+{
+ struct RBasic *p;
+ mrb_value dup;
+
+ if (mrb_immediate_p(obj)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
+ }
+ if (mrb_type(obj) == MRB_TT_SCLASS) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
+ }
+ p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
+ dup = mrb_obj_value(p);
+ init_copy(mrb, dup, obj);
+
+ return dup;
+}
+
+static mrb_value
+mrb_obj_extend(mrb_state *mrb, mrb_int argc, mrb_value *argv, mrb_value obj)
+{
+ mrb_int i;
+
+ if (argc == 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)");
+ }
+ for (i = 0; i < argc; i++) {
+ mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
+ }
+ while (argc--) {
+ mrb_funcall(mrb, argv[argc], "extend_object", 1, obj);
+ mrb_funcall(mrb, argv[argc], "extended", 1, obj);
+ }
+ return obj;
+}
+
+/* 15.3.1.3.13 */
+/*
+ * call-seq:
+ * obj.extend(module, ...) -> obj
+ *
+ * Adds to _obj_ the instance methods from each module given as a
+ * parameter.
+ *
+ * module Mod
+ * def hello
+ * "Hello from Mod.\n"
+ * end
+ * end
+ *
+ * class Klass
+ * def hello
+ * "Hello from Klass.\n"
+ * end
+ * end
+ *
+ * k = Klass.new
+ * k.hello #=> "Hello from Klass.\n"
+ * k.extend(Mod) #=> #<Klass:0x401b3bc8>
+ * k.hello #=> "Hello from Mod.\n"
+ */
+static mrb_value
+mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ mrb_int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_extend(mrb, argc, argv, self);
+}
+
+static mrb_value
+mrb_obj_freeze(mrb_state *mrb, mrb_value self)
+{
+ struct RBasic *b;
+
+ switch (mrb_type(self)) {
+ case MRB_TT_FALSE:
+ case MRB_TT_TRUE:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FLOAT:
+ return self;
+ default:
+ break;
+ }
+
+ b = mrb_basic_ptr(self);
+ if (!MRB_FROZEN_P(b)) {
+ MRB_SET_FROZEN_FLAG(b);
+ }
+ return self;
+}
+
+static mrb_value
+mrb_obj_frozen(mrb_state *mrb, mrb_value self)
+{
+ struct RBasic *b;
+
+ switch (mrb_type(self)) {
+ case MRB_TT_FALSE:
+ case MRB_TT_TRUE:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FLOAT:
+ return mrb_true_value();
+ default:
+ break;
+ }
+
+ b = mrb_basic_ptr(self);
+ if (!MRB_FROZEN_P(b)) {
+ return mrb_false_value();
+ }
+ return mrb_true_value();
+}
+
+/* 15.3.1.3.15 */
+/*
+ * call-seq:
+ * obj.hash -> fixnum
+ *
+ * Generates a <code>Fixnum</code> hash value for this object. This
+ * function must have the property that <code>a.eql?(b)</code> implies
+ * <code>a.hash == b.hash</code>. The hash value is used by class
+ * <code>Hash</code>. Any hash value that exceeds the capacity of a
+ * <code>Fixnum</code> will be truncated before being used.
+ */
+MRB_API mrb_value
+mrb_obj_hash(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(mrb_obj_id(self));
+}
+
+/* 15.3.1.3.16 */
+static mrb_value
+mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
+{
+ mrb_value orig;
+
+ mrb_get_args(mrb, "o", &orig);
+ if (mrb_obj_equal(mrb, self, orig)) return self;
+ if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
+ }
+ return self;
+}
+
+
+MRB_API mrb_bool
+mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c)
+{
+ if (mrb_obj_class(mrb, obj) == c) return TRUE;
+ return FALSE;
+}
+
+/* 15.3.1.3.19 */
+/*
+ * call-seq:
+ * obj.instance_of?(class) -> true or false
+ *
+ * Returns <code>true</code> if <i>obj</i> is an instance of the given
+ * class. See also <code>Object#kind_of?</code>.
+ */
+static mrb_value
+obj_is_instance_of(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "C", &arg);
+
+ return mrb_bool_value(mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg)));
+}
+
+/* 15.3.1.3.20 */
+/*
+ * call-seq:
+ * obj.instance_variable_defined?(symbol) -> true or false
+ *
+ * Returns <code>true</code> if the given instance variable is
+ * defined in <i>obj</i>.
+ *
+ * class Fred
+ * def initialize(p1, p2)
+ * @a, @b = p1, p2
+ * end
+ * end
+ * fred = Fred.new('cat', 99)
+ * fred.instance_variable_defined?(:@a) #=> true
+ * fred.instance_variable_defined?("@b") #=> true
+ * fred.instance_variable_defined?("@c") #=> false
+ */
+static mrb_value
+mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym sym;
+
+ mrb_get_args(mrb, "n", &sym);
+ mrb_iv_check(mrb, sym);
+ return mrb_bool_value(mrb_iv_defined(mrb, self, sym));
+}
+
+/* 15.3.1.3.21 */
+/*
+ * call-seq:
+ * obj.instance_variable_get(symbol) -> obj
+ *
+ * Returns the value of the given instance variable, or nil if the
+ * instance variable is not set. The <code>@</code> part of the
+ * variable name should be included for regular instance
+ * variables. Throws a <code>NameError</code> exception if the
+ * supplied symbol is not valid as an instance variable name.
+ *
+ * class Fred
+ * def initialize(p1, p2)
+ * @a, @b = p1, p2
+ * end
+ * end
+ * fred = Fred.new('cat', 99)
+ * fred.instance_variable_get(:@a) #=> "cat"
+ * fred.instance_variable_get("@b") #=> 99
+ */
+static mrb_value
+mrb_obj_ivar_get(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym iv_name;
+
+ mrb_get_args(mrb, "n", &iv_name);
+ mrb_iv_check(mrb, iv_name);
+ return mrb_iv_get(mrb, self, iv_name);
+}
+
+/* 15.3.1.3.22 */
+/*
+ * call-seq:
+ * obj.instance_variable_set(symbol, obj) -> obj
+ *
+ * Sets the instance variable names by <i>symbol</i> to
+ * <i>object</i>, thereby frustrating the efforts of the class's
+ * author to attempt to provide proper encapsulation. The variable
+ * did not have to exist prior to this call.
+ *
+ * class Fred
+ * def initialize(p1, p2)
+ * @a, @b = p1, p2
+ * end
+ * end
+ * fred = Fred.new('cat', 99)
+ * fred.instance_variable_set(:@a, 'dog') #=> "dog"
+ * fred.instance_variable_set(:@c, 'cat') #=> "cat"
+ * fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
+ */
+static mrb_value
+mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym iv_name;
+ mrb_value val;
+
+ mrb_get_args(mrb, "no", &iv_name, &val);
+ mrb_iv_check(mrb, iv_name);
+ mrb_iv_set(mrb, self, iv_name, val);
+ return val;
+}
+
+/* 15.3.1.3.24 */
+/* 15.3.1.3.26 */
+/*
+ * call-seq:
+ * obj.is_a?(class) -> true or false
+ * obj.kind_of?(class) -> true or false
+ *
+ * Returns <code>true</code> if <i>class</i> is the class of
+ * <i>obj</i>, or if <i>class</i> is one of the superclasses of
+ * <i>obj</i> or modules included in <i>obj</i>.
+ *
+ * module M; end
+ * class A
+ * include M
+ * end
+ * class B < A; end
+ * class C < B; end
+ * b = B.new
+ * b.instance_of? A #=> false
+ * b.instance_of? B #=> true
+ * b.instance_of? C #=> false
+ * b.instance_of? M #=> false
+ * b.kind_of? A #=> true
+ * b.kind_of? B #=> true
+ * b.kind_of? C #=> false
+ * b.kind_of? M #=> true
+ */
+static mrb_value
+mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "C", &arg);
+
+ return mrb_bool_value(mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg)));
+}
+
+KHASH_DECLARE(st, mrb_sym, char, FALSE)
+KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal)
+
+static void
+method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
+{
+ khint_t i;
+
+ khash_t(mt) *h = klass->mt;
+ if (!h) return;
+ for (i=0;i<kh_end(h);i++) {
+ if (kh_exist(h, i) && kh_value(h, i)) {
+ kh_put(st, mrb, set, kh_key(h, i));
+ }
+ }
+}
+
+mrb_value
+mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
+{
+ khint_t i;
+ mrb_value ary;
+ mrb_bool prepended = FALSE;
+ struct RClass* oldklass;
+ khash_t(st)* set = kh_init(st, mrb);
+
+ if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) {
+ MRB_CLASS_ORIGIN(klass);
+ prepended = TRUE;
+ }
+
+ oldklass = 0;
+ while (klass && (klass != oldklass)) {
+ method_entry_loop(mrb, klass, set);
+ if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
+ (klass->tt == MRB_TT_SCLASS)) {
+ }
+ else {
+ if (!recur) break;
+ }
+ oldklass = klass;
+ klass = klass->super;
+ }
+
+ ary = mrb_ary_new(mrb);
+ for (i=0;i<kh_end(set);i++) {
+ if (kh_exist(set, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
+ }
+ }
+ kh_destroy(st, mrb, set);
+
+ return ary;
+}
+
+static mrb_value
+mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
+{
+ khint_t i;
+ mrb_value ary;
+ struct RClass* klass;
+ khash_t(st)* set = kh_init(st, mrb);
+
+ klass = mrb_class(mrb, obj);
+
+ if (klass && (klass->tt == MRB_TT_SCLASS)) {
+ method_entry_loop(mrb, klass, set);
+ klass = klass->super;
+ }
+ if (recur) {
+ while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
+ method_entry_loop(mrb, klass, set);
+ klass = klass->super;
+ }
+ }
+
+ ary = mrb_ary_new(mrb);
+ for (i=0;i<kh_end(set);i++) {
+ if (kh_exist(set, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set, i)));
+ }
+ }
+ kh_destroy(st, mrb, set);
+
+ return ary;
+}
+
+static mrb_value
+mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, mrb_method_flag_t flag)
+{
+ return mrb_class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0);
+}
+/* 15.3.1.3.31 */
+/*
+ * call-seq:
+ * obj.methods -> array
+ *
+ * Returns a list of the names of methods publicly accessible in
+ * <i>obj</i>. This will include all the methods accessible in
+ * <i>obj</i>'s ancestors.
+ *
+ * class Klass
+ * def kMethod()
+ * end
+ * end
+ * k = Klass.new
+ * k.methods[0..9] #=> [:kMethod, :respond_to?, :nil?, :is_a?,
+ * # :class, :instance_variable_set,
+ * # :methods, :extend, :__send__, :instance_eval]
+ * k.methods.length #=> 42
+ */
+static mrb_value
+mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_bool recur = TRUE;
+ mrb_get_args(mrb, "|b", &recur);
+ return mrb_obj_methods(mrb, recur, self, (mrb_method_flag_t)0); /* everything but private */
+}
+
+/* 15.3.1.3.32 */
+/*
+ * call_seq:
+ * nil.nil? -> true
+ * <anything_else>.nil? -> false
+ *
+ * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
+ */
+static mrb_value
+mrb_false(mrb_state *mrb, mrb_value self)
+{
+ return mrb_false_value();
+}
+
+/* 15.3.1.3.36 */
+/*
+ * call-seq:
+ * obj.private_methods(all=true) -> array
+ *
+ * Returns the list of private methods accessible to <i>obj</i>. If
+ * the <i>all</i> parameter is set to <code>false</code>, only those methods
+ * in the receiver will be listed.
+ */
+static mrb_value
+mrb_obj_private_methods(mrb_state *mrb, mrb_value self)
+{
+ mrb_bool recur = TRUE;
+ mrb_get_args(mrb, "|b", &recur);
+ return mrb_obj_methods(mrb, recur, self, NOEX_PRIVATE); /* private attribute not define */
+}
+
+/* 15.3.1.3.37 */
+/*
+ * call-seq:
+ * obj.protected_methods(all=true) -> array
+ *
+ * Returns the list of protected methods accessible to <i>obj</i>. If
+ * the <i>all</i> parameter is set to <code>false</code>, only those methods
+ * in the receiver will be listed.
+ */
+static mrb_value
+mrb_obj_protected_methods(mrb_state *mrb, mrb_value self)
+{
+ mrb_bool recur = TRUE;
+ mrb_get_args(mrb, "|b", &recur);
+ return mrb_obj_methods(mrb, recur, self, NOEX_PROTECTED); /* protected attribute not define */
+}
+
+/* 15.3.1.3.38 */
+/*
+ * call-seq:
+ * obj.public_methods(all=true) -> array
+ *
+ * Returns the list of public methods accessible to <i>obj</i>. If
+ * the <i>all</i> parameter is set to <code>false</code>, only those methods
+ * in the receiver will be listed.
+ */
+static mrb_value
+mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
+{
+ mrb_bool recur = TRUE;
+ mrb_get_args(mrb, "|b", &recur);
+ return mrb_obj_methods(mrb, recur, self, NOEX_PUBLIC); /* public attribute not define */
+}
+
+/* 15.3.1.2.12 */
+/* 15.3.1.3.40 */
+/*
+ * call-seq:
+ * raise
+ * raise(string)
+ * raise(exception [, string])
+ *
+ * With no arguments, raises a <code>RuntimeError</code>
+ * With a single +String+ argument, raises a
+ * +RuntimeError+ with the string as a message. Otherwise,
+ * the first parameter should be the name of an +Exception+
+ * class (or an object that returns an +Exception+ object when sent
+ * an +exception+ message). The optional second parameter sets the
+ * message associated with the exception, and the third parameter is an
+ * array of callback information. Exceptions are caught by the
+ * +rescue+ clause of <code>begin...end</code> blocks.
+ *
+ * raise "Failed to create socket"
+ * raise ArgumentError, "No parameters", caller
+ */
+MRB_API mrb_value
+mrb_f_raise(mrb_state *mrb, mrb_value self)
+{
+ mrb_value a[2], exc;
+ int argc;
+
+
+ argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]);
+ switch (argc) {
+ case 0:
+ mrb_raise(mrb, E_RUNTIME_ERROR, "");
+ break;
+ case 1:
+ if (mrb_string_p(a[0])) {
+ a[1] = a[0];
+ argc = 2;
+ a[0] = mrb_obj_value(E_RUNTIME_ERROR);
+ }
+ /* fall through */
+ default:
+ exc = mrb_make_exception(mrb, argc, a);
+ mrb_exc_raise(mrb, exc);
+ break;
+ }
+ return mrb_nil_value(); /* not reached */
+}
+
+/* 15.3.1.3.41 */
+/*
+ * call-seq:
+ * obj.remove_instance_variable(symbol) -> obj
+ *
+ * Removes the named instance variable from <i>obj</i>, returning that
+ * variable's value.
+ *
+ * class Dummy
+ * attr_reader :var
+ * def initialize
+ * @var = 99
+ * end
+ * def remove
+ * remove_instance_variable(:@var)
+ * end
+ * end
+ * d = Dummy.new
+ * d.var #=> 99
+ * d.remove #=> 99
+ * d.var #=> nil
+ */
+static mrb_value
+mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym sym;
+ mrb_value val;
+
+ mrb_get_args(mrb, "n", &sym);
+ mrb_iv_check(mrb, sym);
+ val = mrb_iv_remove(mrb, self, sym);
+ if (mrb_undef_p(val)) {
+ mrb_name_error(mrb, sym, "instance variable %S not defined", mrb_sym2str(mrb, sym));
+ }
+ return val;
+}
+
+void
+mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
+{
+ mrb_sym inspect;
+ mrb_value repr;
+
+ inspect = mrb_intern_lit(mrb, "inspect");
+ if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
+ /* method missing in inspect; avoid recursion */
+ repr = mrb_any_to_s(mrb, self);
+ }
+ else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 16) {
+ repr = mrb_funcall_argv(mrb, self, inspect, 0, 0);
+ if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
+ repr = mrb_any_to_s(mrb, self);
+ }
+ }
+ else {
+ repr = mrb_any_to_s(mrb, self);
+ }
+
+ mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S",
+ mrb_sym2str(mrb, name), repr);
+}
+
+/* 15.3.1.3.30 */
+/*
+ * call-seq:
+ * obj.method_missing(symbol [, *args] ) -> result
+ *
+ * Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
+ * <i>symbol</i> is the symbol for the method called, and <i>args</i>
+ * are any arguments that were passed to it. By default, the interpreter
+ * raises an error when this method is called. However, it is possible
+ * to override the method to provide more dynamic behavior.
+ * If it is decided that a particular method should not be handled, then
+ * <i>super</i> should be called, so that ancestors can pick up the
+ * missing method.
+ * The example below creates
+ * a class <code>Roman</code>, which responds to methods with names
+ * consisting of roman numerals, returning the corresponding integer
+ * values.
+ *
+ * class Roman
+ * def romanToInt(str)
+ * # ...
+ * end
+ * def method_missing(methId)
+ * str = methId.id2name
+ * romanToInt(str)
+ * end
+ * end
+ *
+ * r = Roman.new
+ * r.iv #=> 4
+ * r.xxiii #=> 23
+ * r.mm #=> 2000
+ */
+#ifdef MRB_DEFAULT_METHOD_MISSING
+static mrb_value
+mrb_obj_missing(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym name;
+ mrb_value *a;
+ mrb_int alen;
+
+ mrb_get_args(mrb, "n*!", &name, &a, &alen);
+ mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
+ /* not reached */
+ return mrb_nil_value();
+}
+#endif
+
+static inline mrb_bool
+basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
+{
+ return mrb_respond_to(mrb, obj, id);
+}
+/* 15.3.1.3.43 */
+/*
+ * call-seq:
+ * obj.respond_to?(symbol, include_private=false) -> true or false
+ *
+ * Returns +true+ if _obj_ responds to the given
+ * method. Private methods are included in the search only if the
+ * optional second parameter evaluates to +true+.
+ *
+ * If the method is not implemented,
+ * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
+ * false is returned.
+ *
+ * If the method is not defined, <code>respond_to_missing?</code>
+ * method is called and the result is returned.
+ */
+static mrb_value
+obj_respond_to(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mid;
+ mrb_sym id, rtm_id;
+ mrb_bool priv = FALSE, respond_to_p = TRUE;
+
+ mrb_get_args(mrb, "o|b", &mid, &priv);
+
+ if (mrb_symbol_p(mid)) {
+ id = mrb_symbol(mid);
+ }
+ else {
+ mrb_value tmp;
+ if (mrb_string_p(mid)) {
+ tmp = mrb_check_intern_str(mrb, mid);
+ }
+ else {
+ tmp = mrb_check_string_type(mrb, mid);
+ if (mrb_nil_p(tmp)) {
+ tmp = mrb_inspect(mrb, mid);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
+ }
+ tmp = mrb_check_intern_str(mrb, tmp);
+ }
+ if (mrb_nil_p(tmp)) {
+ respond_to_p = FALSE;
+ }
+ else {
+ id = mrb_symbol(tmp);
+ }
+ }
+
+ if (respond_to_p) {
+ respond_to_p = basic_obj_respond_to(mrb, self, id, !priv);
+ }
+
+ if (!respond_to_p) {
+ rtm_id = mrb_intern_lit(mrb, "respond_to_missing?");
+ if (basic_obj_respond_to(mrb, self, rtm_id, !priv)) {
+ mrb_value args[2], v;
+ args[0] = mid;
+ args[1] = mrb_bool_value(priv);
+ v = mrb_funcall_argv(mrb, self, rtm_id, 2, args);
+ return mrb_bool_value(mrb_bool(v));
+ }
+ }
+ return mrb_bool_value(respond_to_p);
+}
+
+/* 15.3.1.3.45 */
+/*
+ * call-seq:
+ * obj.singleton_methods(all=true) -> array
+ *
+ * Returns an array of the names of singleton methods for <i>obj</i>.
+ * If the optional <i>all</i> parameter is true, the list will include
+ * methods in modules included in <i>obj</i>.
+ * Only public and protected singleton methods are returned.
+ *
+ * module Other
+ * def three() end
+ * end
+ *
+ * class Single
+ * def Single.four() end
+ * end
+ *
+ * a = Single.new
+ *
+ * def a.one()
+ * end
+ *
+ * class << a
+ * include Other
+ * def two()
+ * end
+ * end
+ *
+ * Single.singleton_methods #=> [:four]
+ * a.singleton_methods(false) #=> [:two, :one]
+ * a.singleton_methods #=> [:two, :one, :three]
+ */
+static mrb_value
+mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_bool recur = TRUE;
+ mrb_get_args(mrb, "|b", &recur);
+ return mrb_obj_singleton_methods(mrb, recur, self);
+}
+
+static mrb_value
+mod_define_singleton_method(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *p;
+ mrb_sym mid;
+ mrb_value blk = mrb_nil_value();
+
+ mrb_get_args(mrb, "n&", &mid, &blk);
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ mrb_proc_copy(p, mrb_proc_ptr(blk));
+ p->flags |= MRB_PROC_STRICT;
+ mrb_define_method_raw(mrb, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p);
+ return mrb_symbol_value(mid);
+}
+
+static mrb_value
+mrb_obj_ceqq(mrb_state *mrb, mrb_value self)
+{
+ mrb_value v;
+ mrb_int i, len;
+ mrb_sym eqq = mrb_intern_lit(mrb, "===");
+ mrb_value ary = mrb_ary_splat(mrb, self);
+
+ mrb_get_args(mrb, "o", &v);
+ len = RARRAY_LEN(ary);
+ for (i=0; i<len; i++) {
+ mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v);
+ if (mrb_test(c)) return mrb_true_value();
+ }
+ return mrb_false_value();
+}
+
+/* 15.3.1.2.7 */
+/*
+ * call-seq:
+ * local_variables -> array
+ *
+ * Returns the names of local variables in the current scope.
+ *
+ * [mruby limitation]
+ * If variable symbol information was stripped out from
+ * compiled binary files using `mruby-strip -l`, this
+ * method always returns an empty array.
+ */
+static mrb_value
+mrb_local_variables(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *proc;
+ mrb_irep *irep;
+ mrb_value vars;
+ size_t i;
+
+ proc = mrb->c->ci[-1].proc;
+
+ if (MRB_PROC_CFUNC_P(proc)) {
+ return mrb_ary_new(mrb);
+ }
+ vars = mrb_hash_new(mrb);
+ irep = proc->body.irep;
+ while (irep) {
+ if (!irep->lv) break;
+ for (i = 0; i + 1 < irep->nlocals; ++i) {
+ if (irep->lv[i].name) {
+ mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value());
+ }
+ }
+ if (!proc->env) break;
+ irep = irep->outer;
+ }
+
+ return mrb_hash_keys(mrb, vars);
+}
+
+mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value);
+void
+mrb_init_kernel(mrb_state *mrb)
+{
+ struct RClass *krn;
+
+ mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */
+ mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */
+ mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.2.4 */
+ mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */
+ mrb_define_class_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.2.7 */
+; /* 15.3.1.2.11 */
+ mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */
+
+ mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */
+ mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */
+ mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */
+ mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */
+ mrb_define_method(mrb, krn, "dup", mrb_obj_dup, MRB_ARGS_NONE()); /* 15.3.1.3.9 */
+ mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */
+ mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */
+ mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, MRB_ARGS_ANY()); /* 15.3.1.3.13 */
+ mrb_define_method(mrb, krn, "freeze", mrb_obj_freeze, MRB_ARGS_NONE());
+ mrb_define_method(mrb, krn, "frozen?", mrb_obj_frozen, MRB_ARGS_NONE());
+ mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.3.14 */
+ mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */
+ mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */
+ mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */
+ mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */
+ mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, MRB_ARGS_REQ(1)); /* 15.3.1.3.20 */
+ mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, MRB_ARGS_REQ(1)); /* 15.3.1.3.21 */
+ mrb_define_method(mrb, krn, "instance_variable_set", mrb_obj_ivar_set, MRB_ARGS_REQ(2)); /* 15.3.1.3.22 */
+ mrb_define_method(mrb, krn, "instance_variables", mrb_obj_instance_variables, MRB_ARGS_NONE()); /* 15.3.1.3.23 */
+ mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */
+ mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */
+ mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */
+ mrb_define_method(mrb, krn, "local_variables", mrb_local_variables, MRB_ARGS_NONE()); /* 15.3.1.3.28 */
+#ifdef MRB_DEFAULT_METHOD_MISSING
+ mrb_define_method(mrb, krn, "method_missing", mrb_obj_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */
+#endif
+ mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.31 */
+ mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */
+ mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */
+ mrb_define_method(mrb, krn, "private_methods", mrb_obj_private_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.36 */
+ mrb_define_method(mrb, krn, "protected_methods", mrb_obj_protected_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.37 */
+ mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, MRB_ARGS_OPT(1)); /* 15.3.1.3.38 */
+ mrb_define_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */
+ mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */
+ mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */
+ mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */
+ mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */
+ mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_ANY());
+ mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
+ mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
+
+ mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
+ mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone"));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/load.c b/web/server/h2o/libh2o/deps/mruby/src/load.c
new file mode 100644
index 00000000..8ae607ff
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/load.c
@@ -0,0 +1,704 @@
+/*
+** load.c - mruby binary loader
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby/dump.h>
+#include <mruby/irep.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+#include <mruby/debug.h>
+#include <mruby/error.h>
+
+#if SIZE_MAX < UINT32_MAX
+# error size_t must be at least 32 bits wide
+#endif
+
+#define FLAG_BYTEORDER_BIG 2
+#define FLAG_BYTEORDER_LIL 4
+#define FLAG_BYTEORDER_NATIVE 8
+#define FLAG_SRC_MALLOC 1
+#define FLAG_SRC_STATIC 0
+
+#define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size))
+
+static size_t
+skip_padding(const uint8_t *buf)
+{
+ const size_t align = MRB_DUMP_ALIGNMENT;
+ return -(intptr_t)buf & (align-1);
+}
+
+static size_t
+offset_crc_body(void)
+{
+ struct rite_binary_header header;
+ return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc);
+}
+
+static mrb_irep*
+read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
+{
+ int i;
+ const uint8_t *src = bin;
+ ptrdiff_t diff;
+ uint16_t tt, pool_data_len, snl;
+ int plen;
+ int ai = mrb_gc_arena_save(mrb);
+ mrb_irep *irep = mrb_add_irep(mrb);
+
+ /* skip record size */
+ src += sizeof(uint32_t);
+
+ /* number of local variable */
+ irep->nlocals = bin_to_uint16(src);
+ src += sizeof(uint16_t);
+
+ /* number of register variable */
+ irep->nregs = bin_to_uint16(src);
+ src += sizeof(uint16_t);
+
+ /* number of child irep */
+ irep->rlen = (size_t)bin_to_uint16(src);
+ src += sizeof(uint16_t);
+
+ /* Binary Data Section */
+ /* ISEQ BLOCK */
+ irep->ilen = (size_t)bin_to_uint32(src);
+ src += sizeof(uint32_t);
+ src += skip_padding(src);
+
+ if (irep->ilen > 0) {
+ if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
+ return NULL;
+ }
+ if ((flags & FLAG_SRC_MALLOC) == 0 &&
+ (flags & FLAG_BYTEORDER_NATIVE)) {
+ irep->iseq = (mrb_code*)src;
+ src += sizeof(uint32_t) * irep->ilen;
+ irep->flags |= MRB_ISEQ_NO_FREE;
+ }
+ else {
+ irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen);
+ if (flags & FLAG_BYTEORDER_NATIVE) {
+ memcpy(irep->iseq, src, sizeof(uint32_t) * irep->ilen);
+ src += sizeof(uint32_t) * irep->ilen;
+ }
+ else if (flags & FLAG_BYTEORDER_BIG) {
+ for (i = 0; i < irep->ilen; i++) {
+ irep->iseq[i] = (mrb_code)bin_to_uint32(src); /* iseq */
+ src += sizeof(uint32_t);
+ }
+ }
+ else {
+ for (i = 0; i < irep->ilen; i++) {
+ irep->iseq[i] = (mrb_code)bin_to_uint32l(src); /* iseq */
+ src += sizeof(uint32_t);
+ }
+ }
+ }
+ }
+
+ /* POOL BLOCK */
+ plen = bin_to_uint32(src); /* number of pool */
+ src += sizeof(uint32_t);
+ if (plen > 0) {
+ if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) {
+ return NULL;
+ }
+ irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen);
+
+ for (i = 0; i < plen; i++) {
+ mrb_value s;
+
+ tt = *src++; /* pool TT */
+ pool_data_len = bin_to_uint16(src); /* pool data length */
+ src += sizeof(uint16_t);
+ if (flags & FLAG_SRC_MALLOC) {
+ s = mrb_str_new(mrb, (char *)src, pool_data_len);
+ }
+ else {
+ s = mrb_str_new_static(mrb, (char *)src, pool_data_len);
+ }
+ src += pool_data_len;
+ switch (tt) { /* pool data */
+ case IREP_TT_FIXNUM:
+ irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE);
+ break;
+
+ case IREP_TT_FLOAT:
+ irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE));
+ break;
+
+ case IREP_TT_STRING:
+ irep->pool[i] = mrb_str_pool(mrb, s);
+ break;
+
+ default:
+ /* should not happen */
+ irep->pool[i] = mrb_nil_value();
+ break;
+ }
+ irep->plen++;
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ }
+
+ /* SYMS BLOCK */
+ irep->slen = (size_t)bin_to_uint32(src); /* syms length */
+ src += sizeof(uint32_t);
+ if (irep->slen > 0) {
+ if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) {
+ return NULL;
+ }
+ irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen);
+
+ for (i = 0; i < irep->slen; i++) {
+ snl = bin_to_uint16(src); /* symbol name length */
+ src += sizeof(uint16_t);
+
+ if (snl == MRB_DUMP_NULL_SYM_LEN) {
+ irep->syms[i] = 0;
+ continue;
+ }
+
+ if (flags & FLAG_SRC_MALLOC) {
+ irep->syms[i] = mrb_intern(mrb, (char *)src, snl);
+ }
+ else {
+ irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl);
+ }
+ src += snl + 1;
+
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ }
+
+ irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen);
+
+ diff = src - bin;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ *len = (size_t)diff;
+
+ return irep;
+}
+
+static mrb_irep*
+read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
+{
+ mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags);
+ int i;
+
+ if (irep == NULL) {
+ return NULL;
+ }
+
+ bin += *len;
+ for (i=0; i<irep->rlen; i++) {
+ size_t rlen;
+
+ irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags);
+ if (irep->reps[i] == NULL) {
+ return NULL;
+ }
+ bin += rlen;
+ *len += rlen;
+ }
+ return irep;
+}
+
+static mrb_irep*
+read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags)
+{
+ size_t len;
+
+ bin += sizeof(struct rite_section_irep_header);
+ return read_irep_record(mrb, bin, &len, flags);
+}
+
+static int
+read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len)
+{
+ size_t i, fname_len, niseq;
+ char *fname;
+ uint16_t *lines;
+
+ *len = 0;
+ bin += sizeof(uint32_t); /* record size */
+ *len += sizeof(uint32_t);
+ fname_len = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ *len += sizeof(uint16_t);
+ fname = (char *)mrb_malloc(mrb, fname_len + 1);
+ memcpy(fname, bin, fname_len);
+ fname[fname_len] = '\0';
+ bin += fname_len;
+ *len += fname_len;
+
+ niseq = (size_t)bin_to_uint32(bin);
+ bin += sizeof(uint32_t); /* niseq */
+ *len += sizeof(uint32_t);
+
+ if (SIZE_ERROR_MUL(niseq, sizeof(uint16_t))) {
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
+ lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t));
+ for (i = 0; i < niseq; i++) {
+ lines[i] = bin_to_uint16(bin);
+ bin += sizeof(uint16_t); /* niseq */
+ *len += sizeof(uint16_t);
+ }
+
+ irep->filename = fname;
+ irep->lines = lines;
+ return MRB_DUMP_OK;
+}
+
+static int
+read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp)
+{
+ int result = read_lineno_record_1(mrb, bin, irep, lenp);
+ int i;
+
+ if (result != MRB_DUMP_OK) return result;
+ for (i = 0; i < irep->rlen; i++) {
+ size_t len;
+
+ result = read_lineno_record(mrb, bin, irep->reps[i], &len);
+ if (result != MRB_DUMP_OK) break;
+ bin += len;
+ *lenp += len;
+ }
+ return result;
+}
+
+static int
+read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep)
+{
+ size_t len;
+
+ len = 0;
+ bin += sizeof(struct rite_section_lineno_header);
+
+ /* Read Binary Data Section */
+ return read_lineno_record(mrb, bin, irep, &len);
+}
+
+static int
+read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *record_len, const mrb_sym *filenames, size_t filenames_len)
+{
+ const uint8_t *bin = start;
+ ptrdiff_t diff;
+ size_t record_size;
+ uint16_t f_idx;
+ int i;
+
+ if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
+
+ irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
+ irep->debug_info->pc_count = (uint32_t)irep->ilen;
+
+ record_size = (size_t)bin_to_uint32(bin);
+ bin += sizeof(uint32_t);
+
+ irep->debug_info->flen = bin_to_uint16(bin);
+ irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen);
+ bin += sizeof(uint16_t);
+
+ for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
+ mrb_irep_debug_info_file *file;
+ uint16_t filename_idx;
+ mrb_int len;
+
+ file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file));
+ irep->debug_info->files[f_idx] = file;
+
+ file->start_pos = bin_to_uint32(bin);
+ bin += sizeof(uint32_t);
+
+ /* filename */
+ filename_idx = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ mrb_assert(filename_idx < filenames_len);
+ file->filename_sym = filenames[filename_idx];
+ len = 0;
+ file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len);
+
+ file->line_entry_count = bin_to_uint32(bin);
+ bin += sizeof(uint32_t);
+ file->line_type = (mrb_debug_line_type)bin_to_uint8(bin);
+ bin += sizeof(uint8_t);
+ switch (file->line_type) {
+ case mrb_debug_line_ary: {
+ uint32_t l;
+
+ file->lines.ary = (uint16_t *)mrb_malloc(mrb, sizeof(uint16_t) * (size_t)(file->line_entry_count));
+ for (l = 0; l < file->line_entry_count; ++l) {
+ file->lines.ary[l] = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ }
+ } break;
+
+ case mrb_debug_line_flat_map: {
+ uint32_t l;
+
+ file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(
+ mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count));
+ for (l = 0; l < file->line_entry_count; ++l) {
+ file->lines.flat_map[l].start_pos = bin_to_uint32(bin);
+ bin += sizeof(uint32_t);
+ file->lines.flat_map[l].line = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ }
+ } break;
+
+ default: return MRB_DUMP_GENERAL_FAILURE;
+ }
+ }
+
+ diff = bin - start;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+
+ if (record_size != (size_t)diff) {
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
+
+ for (i = 0; i < irep->rlen; i++) {
+ size_t len;
+ int ret;
+
+ ret = read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len);
+ if (ret != MRB_DUMP_OK) return ret;
+ bin += len;
+ }
+
+ diff = bin - start;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ *record_len = (size_t)diff;
+
+ return MRB_DUMP_OK;
+}
+
+static int
+read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags)
+{
+ const uint8_t *bin;
+ ptrdiff_t diff;
+ struct rite_section_debug_header *header;
+ uint16_t i;
+ size_t len = 0;
+ int result;
+ uint16_t filenames_len;
+ mrb_sym *filenames;
+
+ bin = start;
+ header = (struct rite_section_debug_header *)bin;
+ bin += sizeof(struct rite_section_debug_header);
+
+ filenames_len = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len);
+ for (i = 0; i < filenames_len; ++i) {
+ uint16_t f_len = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ if (flags & FLAG_SRC_MALLOC) {
+ filenames[i] = mrb_intern(mrb, (const char *)bin, (size_t)f_len);
+ }
+ else {
+ filenames[i] = mrb_intern_static(mrb, (const char *)bin, (size_t)f_len);
+ }
+ bin += f_len;
+ }
+
+ result = read_debug_record(mrb, bin, irep, &len, filenames, filenames_len);
+ if (result != MRB_DUMP_OK) goto debug_exit;
+
+ bin += len;
+ diff = bin - start;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ if ((uint32_t)diff != bin_to_uint32(header->section_size)) {
+ result = MRB_DUMP_GENERAL_FAILURE;
+ }
+
+debug_exit:
+ mrb_free(mrb, filenames);
+ return result;
+}
+
+static int
+read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *record_len, mrb_sym const *syms, uint32_t syms_len)
+{
+ const uint8_t *bin = start;
+ ptrdiff_t diff;
+ int i;
+
+ irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1));
+
+ for (i = 0; i + 1< irep->nlocals; ++i) {
+ uint16_t const sym_idx = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+ if (sym_idx == RITE_LV_NULL_MARK) {
+ irep->lv[i].name = 0;
+ irep->lv[i].r = 0;
+ }
+ else {
+ if (sym_idx >= syms_len) {
+ return MRB_DUMP_GENERAL_FAILURE;
+ }
+ irep->lv[i].name = syms[sym_idx];
+
+ irep->lv[i].r = bin_to_uint16(bin);
+ }
+ bin += sizeof(uint16_t);
+ }
+
+ for (i = 0; i < irep->rlen; ++i) {
+ size_t len;
+ int ret;
+
+ ret = read_lv_record(mrb, bin, irep->reps[i], &len, syms, syms_len);
+ if (ret != MRB_DUMP_OK) return ret;
+ bin += len;
+ }
+
+ diff = bin - start;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ *record_len = (size_t)diff;
+
+ return MRB_DUMP_OK;
+}
+
+static int
+read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t flags)
+{
+ const uint8_t *bin;
+ ptrdiff_t diff;
+ struct rite_section_lv_header const *header;
+ uint32_t i;
+ size_t len = 0;
+ int result;
+ uint32_t syms_len;
+ mrb_sym *syms;
+ mrb_sym (*intern_func)(mrb_state*, const char*, size_t) =
+ (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static;
+
+ bin = start;
+ header = (struct rite_section_lv_header const*)bin;
+ bin += sizeof(struct rite_section_lv_header);
+
+ syms_len = bin_to_uint32(bin);
+ bin += sizeof(uint32_t);
+ syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len);
+ for (i = 0; i < syms_len; ++i) {
+ uint16_t const str_len = bin_to_uint16(bin);
+ bin += sizeof(uint16_t);
+
+ syms[i] = intern_func(mrb, (const char*)bin, str_len);
+ bin += str_len;
+ }
+
+ result = read_lv_record(mrb, bin, irep, &len, syms, syms_len);
+ if (result != MRB_DUMP_OK) goto lv_exit;
+
+ bin += len;
+ diff = bin - start;
+ mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
+ if ((uint32_t)diff != bin_to_uint32(header->section_size)) {
+ result = MRB_DUMP_GENERAL_FAILURE;
+ }
+
+lv_exit:
+ mrb_free(mrb, syms);
+ return result;
+}
+
+static int
+read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t *flags)
+{
+ const struct rite_binary_header *header = (const struct rite_binary_header *)bin;
+
+ if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) {
+ if (bigendian_p())
+ *flags |= FLAG_BYTEORDER_NATIVE;
+ else
+ *flags |= FLAG_BYTEORDER_BIG;
+ }
+ else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) {
+ if (bigendian_p())
+ *flags |= FLAG_BYTEORDER_LIL;
+ else
+ *flags |= FLAG_BYTEORDER_NATIVE;
+ }
+ else {
+ return MRB_DUMP_INVALID_FILE_HEADER;
+ }
+
+ if (crc) {
+ *crc = bin_to_uint16(header->binary_crc);
+ }
+ *bin_size = (size_t)bin_to_uint32(header->binary_size);
+
+ return MRB_DUMP_OK;
+}
+
+static mrb_irep*
+read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags)
+{
+ int result;
+ mrb_irep *irep = NULL;
+ const struct rite_section_header *section_header;
+ uint16_t crc;
+ size_t bin_size = 0;
+ size_t n;
+
+ if ((mrb == NULL) || (bin == NULL)) {
+ return NULL;
+ }
+
+ result = read_binary_header(bin, &bin_size, &crc, &flags);
+ if (result != MRB_DUMP_OK) {
+ return NULL;
+ }
+
+ n = offset_crc_body();
+ if (crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) {
+ return NULL;
+ }
+
+ bin += sizeof(struct rite_binary_header);
+ do {
+ section_header = (const struct rite_section_header *)bin;
+ if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) {
+ irep = read_section_irep(mrb, bin, flags);
+ if (!irep) return NULL;
+ }
+ else if (memcmp(section_header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(section_header->section_ident)) == 0) {
+ if (!irep) return NULL; /* corrupted data */
+ result = read_section_lineno(mrb, bin, irep);
+ if (result < MRB_DUMP_OK) {
+ return NULL;
+ }
+ }
+ else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) {
+ if (!irep) return NULL; /* corrupted data */
+ result = read_section_debug(mrb, bin, irep, flags);
+ if (result < MRB_DUMP_OK) {
+ return NULL;
+ }
+ }
+ else if (memcmp(section_header->section_ident, RITE_SECTION_LV_IDENT, sizeof(section_header->section_ident)) == 0) {
+ if (!irep) return NULL;
+ result = read_section_lv(mrb, bin, irep, flags);
+ if (result < MRB_DUMP_OK) {
+ return NULL;
+ }
+ }
+ bin += bin_to_uint32(section_header->section_size);
+ } while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0);
+
+ return irep;
+}
+
+mrb_irep*
+mrb_read_irep(mrb_state *mrb, const uint8_t *bin)
+{
+#ifdef MRB_USE_ETEXT_EDATA
+ uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC;
+#else
+ uint8_t flags = FLAG_SRC_STATIC;
+#endif
+
+ return read_irep(mrb, bin, flags);
+}
+
+void mrb_exc_set(mrb_state *mrb, mrb_value exc);
+
+static void
+irep_error(mrb_state *mrb)
+{
+ mrb_exc_set(mrb, mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error"));
+}
+
+void mrb_codedump_all(mrb_state*, struct RProc*);
+
+static mrb_value
+load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c)
+{
+ struct RProc *proc;
+
+ if (!irep) {
+ irep_error(mrb);
+ return mrb_nil_value();
+ }
+ proc = mrb_proc_new(mrb, irep);
+ proc->c = NULL;
+ mrb_irep_decref(mrb, irep);
+ if (c && c->dump_result) mrb_codedump_all(mrb, proc);
+ if (c && c->no_exec) return mrb_obj_value(proc);
+ return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0);
+}
+
+MRB_API mrb_value
+mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c)
+{
+ return load_irep(mrb, mrb_read_irep(mrb, bin), c);
+}
+
+MRB_API mrb_value
+mrb_load_irep(mrb_state *mrb, const uint8_t *bin)
+{
+ return mrb_load_irep_cxt(mrb, bin, NULL);
+}
+
+#ifndef MRB_DISABLE_STDIO
+
+mrb_irep*
+mrb_read_irep_file(mrb_state *mrb, FILE* fp)
+{
+ mrb_irep *irep = NULL;
+ uint8_t *buf;
+ const size_t header_size = sizeof(struct rite_binary_header);
+ size_t buf_size = 0;
+ uint8_t flags = 0;
+ int result;
+
+ if ((mrb == NULL) || (fp == NULL)) {
+ return NULL;
+ }
+
+ buf = (uint8_t*)mrb_malloc(mrb, header_size);
+ if (fread(buf, header_size, 1, fp) == 0) {
+ goto irep_exit;
+ }
+ result = read_binary_header(buf, &buf_size, NULL, &flags);
+ if (result != MRB_DUMP_OK || buf_size <= header_size) {
+ goto irep_exit;
+ }
+
+ buf = (uint8_t*)mrb_realloc(mrb, buf, buf_size);
+ if (fread(buf+header_size, buf_size-header_size, 1, fp) == 0) {
+ goto irep_exit;
+ }
+ irep = read_irep(mrb, buf, FLAG_SRC_MALLOC);
+
+irep_exit:
+ mrb_free(mrb, buf);
+ return irep;
+}
+
+MRB_API mrb_value
+mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrbc_context *c)
+{
+ return load_irep(mrb, mrb_read_irep_file(mrb, fp), c);
+}
+
+MRB_API mrb_value
+mrb_load_irep_file(mrb_state *mrb, FILE* fp)
+{
+ return mrb_load_irep_file_cxt(mrb, fp, NULL);
+}
+#endif /* MRB_DISABLE_STDIO */
diff --git a/web/server/h2o/libh2o/deps/mruby/src/mruby_core.rake b/web/server/h2o/libh2o/deps/mruby/src/mruby_core.rake
new file mode 100644
index 00000000..4558493d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/mruby_core.rake
@@ -0,0 +1,19 @@
+MRuby.each_target do
+ current_dir = File.dirname(__FILE__).relative_path_from(Dir.pwd)
+ relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT)
+ current_build_dir = "#{build_dir}/#{relative_from_root}"
+
+ objs = Dir.glob("#{current_dir}/*.c").map { |f|
+ next nil if cxx_exception_enabled? and f =~ /(error|vm).c$/
+ objfile(f.pathmap("#{current_build_dir}/%n"))
+ }.compact
+
+ if cxx_exception_enabled?
+ objs += %w(vm error).map { |v| compile_as_cxx "#{current_dir}/#{v}.c", "#{current_build_dir}/#{v}.cxx" }
+ end
+ self.libmruby << objs
+
+ file libfile("#{build_dir}/lib/libmruby_core") => objs do |t|
+ archiver.run t.name, t.prerequisites
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/src/numeric.c b/web/server/h2o/libh2o/deps/mruby/src/numeric.c
new file mode 100644
index 00000000..afb8415a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/numeric.c
@@ -0,0 +1,1355 @@
+/*
+** numeric.c - Numeric, Integer, Float, Fixnum class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include <mruby/class.h>
+
+#ifdef MRB_USE_FLOAT
+#define trunc(f) truncf(f)
+#define floor(f) floorf(f)
+#define ceil(f) ceilf(f)
+#define fmod(x,y) fmodf(x,y)
+#define MRB_FLO_TO_STR_FMT "%.7g"
+#else
+#define MRB_FLO_TO_STR_FMT "%.14g"
+#endif
+
+MRB_API mrb_float
+mrb_to_flo(mrb_state *mrb, mrb_value val)
+{
+ switch (mrb_type(val)) {
+ case MRB_TT_FIXNUM:
+ return (mrb_float)mrb_fixnum(val);
+ case MRB_TT_FLOAT:
+ break;
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "non float value");
+ }
+ return mrb_float(val);
+}
+
+/*
+ * call-seq:
+ *
+ * num ** other -> num
+ *
+ * Raises <code>num</code> the <code>other</code> power.
+ *
+ * 2.0**3 #=> 8.0
+ */
+static mrb_value
+num_pow(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ mrb_float d;
+
+ mrb_get_args(mrb, "o", &y);
+ if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) {
+ /* try ipow() */
+ mrb_int base = mrb_fixnum(x);
+ mrb_int exp = mrb_fixnum(y);
+ mrb_int result = 1;
+
+ if (exp < 0) goto float_pow;
+ for (;;) {
+ if (exp & 1) {
+ if (mrb_int_mul_overflow(result, base, &result)) {
+ goto float_pow;
+ }
+ }
+ exp >>= 1;
+ if (exp == 0) break;
+ if (mrb_int_mul_overflow(base, base, &base)) {
+ goto float_pow;
+ }
+ }
+ return mrb_fixnum_value(result);
+ }
+ float_pow:
+ d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y));
+ return mrb_float_value(mrb, d);
+}
+
+/* 15.2.8.3.4 */
+/* 15.2.9.3.4 */
+/*
+ * call-seq:
+ * num / other -> num
+ *
+ * Performs division: the class of the resulting object depends on
+ * the class of <code>num</code> and on the magnitude of the
+ * result.
+ */
+
+mrb_value
+mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y));
+}
+
+/* 15.2.9.3.19(x) */
+/*
+ * call-seq:
+ * num.quo(numeric) -> real
+ *
+ * Returns most exact division.
+ */
+
+static mrb_value
+num_div(mrb_state *mrb, mrb_value x)
+{
+ mrb_float y;
+
+ mrb_get_args(mrb, "f", &y);
+ return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y);
+}
+
+/********************************************************************
+ *
+ * Document-class: Float
+ *
+ * <code>Float</code> objects represent inexact real numbers using
+ * the native architecture's double-precision floating point
+ * representation.
+ */
+
+/* 15.2.9.3.16(x) */
+/*
+ * call-seq:
+ * flt.to_s -> string
+ *
+ * Returns a string containing a representation of self. As well as a
+ * fixed or exponential form of the number, the call may return
+ * "<code>NaN</code>", "<code>Infinity</code>", and
+ * "<code>-Infinity</code>".
+ */
+
+static mrb_value
+flo_to_s(mrb_state *mrb, mrb_value flt)
+{
+ if (isnan(mrb_float(flt))) {
+ return mrb_str_new_lit(mrb, "NaN");
+ }
+ return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT);
+}
+
+/* 15.2.9.3.2 */
+/*
+ * call-seq:
+ * float - other -> float
+ *
+ * Returns a new float which is the difference of <code>float</code>
+ * and <code>other</code>.
+ */
+
+static mrb_value
+flo_minus(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
+}
+
+/* 15.2.9.3.3 */
+/*
+ * call-seq:
+ * float * other -> float
+ *
+ * Returns a new float which is the product of <code>float</code>
+ * and <code>other</code>.
+ */
+
+static mrb_value
+flo_mul(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
+}
+
+static void
+flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp)
+{
+ mrb_float div;
+ mrb_float mod;
+
+ if (y == 0.0) {
+ if (x > 0.0) div = INFINITY;
+ else if (x < 0.0) div = -INFINITY;
+ else div = NAN; /* x == 0.0 */
+ mod = NAN;
+ }
+ else {
+ mod = fmod(x, y);
+ if (isinf(x) && isfinite(y))
+ div = x;
+ else
+ div = (x - mod) / y;
+ if (y*mod < 0) {
+ mod += y;
+ div -= 1.0;
+ }
+ }
+
+ if (modp) *modp = mod;
+ if (divp) *divp = div;
+}
+
+/* 15.2.9.3.5 */
+/*
+ * call-seq:
+ * flt % other -> float
+ * flt.modulo(other) -> float
+ *
+ * Return the modulo after division of <code>flt</code> by <code>other</code>.
+ *
+ * 6543.21.modulo(137) #=> 104.21
+ * 6543.21.modulo(137.24) #=> 92.9299999999996
+ */
+
+static mrb_value
+flo_mod(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ mrb_float mod;
+
+ mrb_get_args(mrb, "o", &y);
+
+ flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod);
+ return mrb_float_value(mrb, mod);
+}
+
+/* 15.2.8.3.16 */
+/*
+ * call-seq:
+ * num.eql?(numeric) -> true or false
+ *
+ * Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the
+ * same type and have equal values.
+ *
+ * 1 == 1.0 #=> true
+ * 1.eql?(1.0) #=> false
+ * (1.0).eql?(1.0) #=> true
+ */
+static mrb_value
+fix_eql(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ if (!mrb_fixnum_p(y)) return mrb_false_value();
+ return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
+}
+
+static mrb_value
+flo_eql(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ if (!mrb_float_p(y)) return mrb_false_value();
+ return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
+}
+
+/* 15.2.9.3.7 */
+/*
+ * call-seq:
+ * flt == obj -> true or false
+ *
+ * Returns <code>true</code> only if <i>obj</i> has the same value
+ * as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which
+ * requires <i>obj</i> to be a <code>Float</code>.
+ *
+ * 1.0 == 1 #=> true
+ *
+ */
+
+static mrb_value
+flo_eq(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ mrb_get_args(mrb, "o", &y);
+
+ switch (mrb_type(y)) {
+ case MRB_TT_FIXNUM:
+ return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
+ case MRB_TT_FLOAT:
+ return mrb_bool_value(mrb_float(x) == mrb_float(y));
+ default:
+ return mrb_false_value();
+ }
+}
+
+static int64_t
+value_int64(mrb_state *mrb, mrb_value x)
+{
+ switch (mrb_type(x)) {
+ case MRB_TT_FIXNUM:
+ return (int64_t)mrb_fixnum(x);
+ break;
+ case MRB_TT_FLOAT:
+ return (int64_t)mrb_float(x);
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "cannot convert to Integer");
+ break;
+ }
+ /* not reached */
+ return 0;
+}
+
+static mrb_value
+int64_value(mrb_state *mrb, int64_t v)
+{
+ if (FIXABLE(v)) {
+ return mrb_fixnum_value((mrb_int)v);
+ }
+ return mrb_float_value(mrb, (mrb_float)v);
+}
+
+static mrb_value
+flo_rev(mrb_state *mrb, mrb_value x)
+{
+ int64_t v1;
+ mrb_get_args(mrb, "");
+ v1 = (int64_t)mrb_float(x);
+ return int64_value(mrb, ~v1);
+}
+
+static mrb_value
+flo_and(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ int64_t v1, v2;
+ mrb_get_args(mrb, "o", &y);
+
+ v1 = (int64_t)mrb_float(x);
+ v2 = value_int64(mrb, y);
+ return int64_value(mrb, v1 & v2);
+}
+
+static mrb_value
+flo_or(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ int64_t v1, v2;
+ mrb_get_args(mrb, "o", &y);
+
+ v1 = (int64_t)mrb_float(x);
+ v2 = value_int64(mrb, y);
+ return int64_value(mrb, v1 | v2);
+}
+
+static mrb_value
+flo_xor(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ int64_t v1, v2;
+ mrb_get_args(mrb, "o", &y);
+
+ v1 = (int64_t)mrb_float(x);
+ v2 = value_int64(mrb, y);
+ return int64_value(mrb, v1 ^ v2);
+}
+
+static mrb_value
+flo_shift(mrb_state *mrb, mrb_value x, mrb_int width)
+{
+ mrb_float val;
+
+ if (width == 0) {
+ return x;
+ }
+ val = mrb_float(x);
+ if (width < 0) {
+ while (width++) {
+ val /= 2;
+ }
+#if defined(_ISOC99_SOURCE)
+ val = trunc(val);
+#else
+ if (val > 0){
+ val = floor(val);
+ } else {
+ val = ceil(val);
+ }
+#endif
+ if (val == 0 && mrb_float(x) < 0) {
+ return mrb_fixnum_value(-1);
+ }
+ }
+ else {
+ while (width--) {
+ val *= 2;
+ }
+ }
+ if (FIXABLE_FLOAT(val)) {
+ return mrb_fixnum_value((mrb_int)val);
+ }
+ return mrb_float_value(mrb, val);
+}
+
+static mrb_value
+flo_lshift(mrb_state *mrb, mrb_value x)
+{
+ mrb_int width;
+
+ mrb_get_args(mrb, "i", &width);
+ return flo_shift(mrb, x, -width);
+}
+
+static mrb_value
+flo_rshift(mrb_state *mrb, mrb_value x)
+{
+ mrb_int width;
+
+ mrb_get_args(mrb, "i", &width);
+ return flo_shift(mrb, x, width);
+}
+
+/* 15.2.9.3.13 */
+/*
+ * call-seq:
+ * flt.to_f -> self
+ *
+ * As <code>flt</code> is already a float, returns +self+.
+ */
+
+static mrb_value
+flo_to_f(mrb_state *mrb, mrb_value num)
+{
+ return num;
+}
+
+/* 15.2.9.3.11 */
+/*
+ * call-seq:
+ * flt.infinite? -> nil, -1, +1
+ *
+ * Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i>
+ * is finite, -infinity, or +infinity.
+ *
+ * (0.0).infinite? #=> nil
+ * (-1.0/0.0).infinite? #=> -1
+ * (+1.0/0.0).infinite? #=> 1
+ */
+
+static mrb_value
+flo_infinite_p(mrb_state *mrb, mrb_value num)
+{
+ mrb_float value = mrb_float(num);
+
+ if (isinf(value)) {
+ return mrb_fixnum_value(value < 0 ? -1 : 1);
+ }
+ return mrb_nil_value();
+}
+
+/* 15.2.9.3.9 */
+/*
+ * call-seq:
+ * flt.finite? -> true or false
+ *
+ * Returns <code>true</code> if <i>flt</i> is a valid IEEE floating
+ * point number (it is not infinite, and <code>nan?</code> is
+ * <code>false</code>).
+ *
+ */
+
+static mrb_value
+flo_finite_p(mrb_state *mrb, mrb_value num)
+{
+ return mrb_bool_value(isfinite(mrb_float(num)));
+}
+
+void
+mrb_check_num_exact(mrb_state *mrb, mrb_float num)
+{
+ if (isinf(num)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, num < 0 ? "-Infinity" : "Infinity");
+ }
+ if (isnan(num)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
+ }
+}
+
+/* 15.2.9.3.10 */
+/*
+ * call-seq:
+ * flt.floor -> integer
+ *
+ * Returns the largest integer less than or equal to <i>flt</i>.
+ *
+ * 1.2.floor #=> 1
+ * 2.0.floor #=> 2
+ * (-1.2).floor #=> -2
+ * (-2.0).floor #=> -2
+ */
+
+static mrb_value
+flo_floor(mrb_state *mrb, mrb_value num)
+{
+ mrb_float f = floor(mrb_float(num));
+
+ mrb_check_num_exact(mrb, f);
+ if (!FIXABLE_FLOAT(f)) {
+ return mrb_float_value(mrb, f);
+ }
+ return mrb_fixnum_value((mrb_int)f);
+}
+
+/* 15.2.9.3.8 */
+/*
+ * call-seq:
+ * flt.ceil -> integer
+ *
+ * Returns the smallest <code>Integer</code> greater than or equal to
+ * <i>flt</i>.
+ *
+ * 1.2.ceil #=> 2
+ * 2.0.ceil #=> 2
+ * (-1.2).ceil #=> -1
+ * (-2.0).ceil #=> -2
+ */
+
+static mrb_value
+flo_ceil(mrb_state *mrb, mrb_value num)
+{
+ mrb_float f = ceil(mrb_float(num));
+
+ mrb_check_num_exact(mrb, f);
+ if (!FIXABLE_FLOAT(f)) {
+ return mrb_float_value(mrb, f);
+ }
+ return mrb_fixnum_value((mrb_int)f);
+}
+
+/* 15.2.9.3.12 */
+/*
+ * call-seq:
+ * flt.round([ndigits]) -> integer or float
+ *
+ * Rounds <i>flt</i> to a given precision in decimal digits (default 0 digits).
+ * Precision may be negative. Returns a floating point number when ndigits
+ * is more than zero.
+ *
+ * 1.4.round #=> 1
+ * 1.5.round #=> 2
+ * 1.6.round #=> 2
+ * (-1.5).round #=> -2
+ *
+ * 1.234567.round(2) #=> 1.23
+ * 1.234567.round(3) #=> 1.235
+ * 1.234567.round(4) #=> 1.2346
+ * 1.234567.round(5) #=> 1.23457
+ *
+ * 34567.89.round(-5) #=> 0
+ * 34567.89.round(-4) #=> 30000
+ * 34567.89.round(-3) #=> 35000
+ * 34567.89.round(-2) #=> 34600
+ * 34567.89.round(-1) #=> 34570
+ * 34567.89.round(0) #=> 34568
+ * 34567.89.round(1) #=> 34567.9
+ * 34567.89.round(2) #=> 34567.89
+ * 34567.89.round(3) #=> 34567.89
+ *
+ */
+
+static mrb_value
+flo_round(mrb_state *mrb, mrb_value num)
+{
+ double number, f;
+ mrb_int ndigits = 0;
+ mrb_int i;
+
+ mrb_get_args(mrb, "|i", &ndigits);
+ number = mrb_float(num);
+
+ if (0 < ndigits && (isinf(number) || isnan(number))) {
+ return num;
+ }
+ mrb_check_num_exact(mrb, number);
+
+ f = 1.0;
+ i = ndigits >= 0 ? ndigits : -ndigits;
+ while (--i >= 0)
+ f = f*10.0;
+
+ if (isinf(f)) {
+ if (ndigits < 0) number = 0;
+ }
+ else {
+ double d;
+
+ if (ndigits < 0) number /= f;
+ else number *= f;
+
+ /* home-made inline implementation of round(3) */
+ if (number > 0.0) {
+ d = floor(number);
+ number = d + (number - d >= 0.5);
+ }
+ else if (number < 0.0) {
+ d = ceil(number);
+ number = d - (d - number >= 0.5);
+ }
+
+ if (ndigits < 0) number *= f;
+ else number /= f;
+ }
+
+ if (ndigits > 0) {
+ if (!isfinite(number)) return num;
+ return mrb_float_value(mrb, number);
+ }
+ return mrb_fixnum_value((mrb_int)number);
+}
+
+/* 15.2.9.3.14 */
+/* 15.2.9.3.15 */
+/*
+ * call-seq:
+ * flt.to_i -> integer
+ * flt.to_int -> integer
+ * flt.truncate -> integer
+ *
+ * Returns <i>flt</i> truncated to an <code>Integer</code>.
+ */
+
+static mrb_value
+flo_truncate(mrb_state *mrb, mrb_value num)
+{
+ mrb_float f = mrb_float(num);
+
+ if (f > 0.0) f = floor(f);
+ if (f < 0.0) f = ceil(f);
+
+ mrb_check_num_exact(mrb, f);
+ if (!FIXABLE_FLOAT(f)) {
+ return mrb_float_value(mrb, f);
+ }
+ return mrb_fixnum_value((mrb_int)f);
+}
+
+static mrb_value
+flo_nan_p(mrb_state *mrb, mrb_value num)
+{
+ return mrb_bool_value(isnan(mrb_float(num)));
+}
+
+/*
+ * Document-class: Integer
+ *
+ * <code>Integer</code> is the basis for the two concrete classes that
+ * hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>.
+ *
+ */
+
+
+/*
+ * call-seq:
+ * int.to_i -> integer
+ * int.to_int -> integer
+ *
+ * As <i>int</i> is already an <code>Integer</code>, all these
+ * methods simply return the receiver.
+ */
+
+static mrb_value
+int_to_i(mrb_state *mrb, mrb_value num)
+{
+ return num;
+}
+
+mrb_value
+mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ mrb_int a;
+
+ a = mrb_fixnum(x);
+ if (mrb_fixnum_p(y)) {
+ mrb_int b, c;
+
+ if (a == 0) return x;
+ b = mrb_fixnum(y);
+ if (mrb_int_mul_overflow(a, b, &c)) {
+ return mrb_float_value(mrb, (mrb_float)a * (mrb_float)b);
+ }
+ return mrb_fixnum_value(c);
+ }
+ return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
+}
+
+/* 15.2.8.3.3 */
+/*
+ * call-seq:
+ * fix * numeric -> numeric_result
+ *
+ * Performs multiplication: the class of the resulting object depends on
+ * the class of <code>numeric</code> and on the magnitude of the
+ * result.
+ */
+
+static mrb_value
+fix_mul(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ return mrb_fixnum_mul(mrb, x, y);
+}
+
+static void
+fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp)
+{
+ mrb_int div, mod;
+
+ /* TODO: add mrb_assert(y != 0) to make sure */
+
+ if (y < 0) {
+ if (x < 0)
+ div = -x / -y;
+ else
+ div = - (x / -y);
+ }
+ else {
+ if (x < 0)
+ div = - (-x / y);
+ else
+ div = x / y;
+ }
+ mod = x - div*y;
+ if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
+ mod += y;
+ div -= 1;
+ }
+ if (divp) *divp = div;
+ if (modp) *modp = mod;
+}
+
+/* 15.2.8.3.5 */
+/*
+ * call-seq:
+ * fix % other -> real
+ * fix.modulo(other) -> real
+ *
+ * Returns <code>fix</code> modulo <code>other</code>.
+ * See <code>numeric.divmod</code> for more information.
+ */
+
+static mrb_value
+fix_mod(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ mrb_int a;
+
+ mrb_get_args(mrb, "o", &y);
+ a = mrb_fixnum(x);
+ if (mrb_fixnum_p(y)) {
+ mrb_int b, mod;
+
+ if ((b=mrb_fixnum(y)) == 0) {
+ return mrb_float_value(mrb, NAN);
+ }
+ fixdivmod(mrb, a, b, 0, &mod);
+ return mrb_fixnum_value(mod);
+ }
+ else {
+ mrb_float mod;
+
+ flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod);
+ return mrb_float_value(mrb, mod);
+ }
+}
+
+/*
+ * call-seq:
+ * fix.divmod(numeric) -> array
+ *
+ * See <code>Numeric#divmod</code>.
+ */
+static mrb_value
+fix_divmod(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+
+ if (mrb_fixnum_p(y)) {
+ mrb_int div, mod;
+
+ if (mrb_fixnum(y) == 0) {
+ return mrb_assoc_new(mrb, ((mrb_fixnum(x) == 0) ?
+ mrb_float_value(mrb, NAN):
+ mrb_float_value(mrb, INFINITY)),
+ mrb_float_value(mrb, NAN));
+ }
+ fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod);
+ return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod));
+ }
+ else {
+ mrb_float div, mod;
+ mrb_value a, b;
+
+ flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod);
+ a = mrb_float_value(mrb, div);
+ b = mrb_float_value(mrb, mod);
+ return mrb_assoc_new(mrb, a, b);
+ }
+}
+
+static mrb_value
+flo_divmod(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ mrb_float div, mod;
+ mrb_value a, b;
+
+ mrb_get_args(mrb, "o", &y);
+
+ flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
+ a = mrb_float_value(mrb, div);
+ b = mrb_float_value(mrb, mod);
+ return mrb_assoc_new(mrb, a, b);
+}
+
+/* 15.2.8.3.7 */
+/*
+ * call-seq:
+ * fix == other -> true or false
+ *
+ * Return <code>true</code> if <code>fix</code> equals <code>other</code>
+ * numerically.
+ *
+ * 1 == 2 #=> false
+ * 1 == 1.0 #=> true
+ */
+
+static mrb_value
+fix_equal(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ switch (mrb_type(y)) {
+ case MRB_TT_FIXNUM:
+ return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
+ case MRB_TT_FLOAT:
+ return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y));
+ default:
+ return mrb_false_value();
+ }
+}
+
+/* 15.2.8.3.8 */
+/*
+ * call-seq:
+ * ~fix -> integer
+ *
+ * One's complement: returns a number where each bit is flipped.
+ * ex.0---00001 (1)-> 1---11110 (-2)
+ * ex.0---00010 (2)-> 1---11101 (-3)
+ * ex.0---00100 (4)-> 1---11011 (-5)
+ */
+
+static mrb_value
+fix_rev(mrb_state *mrb, mrb_value num)
+{
+ mrb_int val = mrb_fixnum(num);
+
+ return mrb_fixnum_value(~val);
+}
+
+static mrb_value flo_and(mrb_state *mrb, mrb_value x);
+static mrb_value flo_or(mrb_state *mrb, mrb_value x);
+static mrb_value flo_xor(mrb_state *mrb, mrb_value x);
+#define bit_op(x,y,op1,op2) do {\
+ if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
+ return flo_ ## op1(mrb, mrb_float_value(mrb, mrb_fixnum(x)));\
+} while(0)
+
+/* 15.2.8.3.9 */
+/*
+ * call-seq:
+ * fix & integer -> integer_result
+ *
+ * Bitwise AND.
+ */
+
+static mrb_value
+fix_and(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ bit_op(x, y, and, &);
+}
+
+/* 15.2.8.3.10 */
+/*
+ * call-seq:
+ * fix | integer -> integer_result
+ *
+ * Bitwise OR.
+ */
+
+static mrb_value
+fix_or(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ bit_op(x, y, or, |);
+}
+
+/* 15.2.8.3.11 */
+/*
+ * call-seq:
+ * fix ^ integer -> integer_result
+ *
+ * Bitwise EXCLUSIVE OR.
+ */
+
+static mrb_value
+fix_xor(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ bit_op(x, y, or, ^);
+}
+
+#define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1)
+
+static mrb_value
+lshift(mrb_state *mrb, mrb_int val, mrb_int width)
+{
+ if (width < 0) { /* mrb_int overflow */
+ return mrb_float_value(mrb, INFINITY);
+ }
+ if (val > 0) {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val > (MRB_INT_MAX >> width))) {
+ goto bit_overflow;
+ }
+ return mrb_fixnum_value(val << width);
+ }
+ else {
+ if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
+ (val < (MRB_INT_MIN >> width))) {
+ goto bit_overflow;
+ }
+ return mrb_fixnum_value(val * (1u << width));
+ }
+
+bit_overflow:
+ {
+ mrb_float f = (mrb_float)val;
+ while (width--) {
+ f *= 2;
+ }
+ return mrb_float_value(mrb, f);
+ }
+}
+
+static mrb_value
+rshift(mrb_int val, mrb_int width)
+{
+ if (width < 0) { /* mrb_int overflow */
+ return mrb_fixnum_value(0);
+ }
+ if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
+ if (val < 0) {
+ return mrb_fixnum_value(-1);
+ }
+ return mrb_fixnum_value(0);
+ }
+ return mrb_fixnum_value(val >> width);
+}
+
+/* 15.2.8.3.12 */
+/*
+ * call-seq:
+ * fix << count -> integer or float
+ *
+ * Shifts _fix_ left _count_ positions (right if _count_ is negative).
+ */
+
+static mrb_value
+fix_lshift(mrb_state *mrb, mrb_value x)
+{
+ mrb_int width, val;
+
+ mrb_get_args(mrb, "i", &width);
+ if (width == 0) {
+ return x;
+ }
+ val = mrb_fixnum(x);
+ if (val == 0) return x;
+ if (width < 0) {
+ return rshift(val, -width);
+ }
+ return lshift(mrb, val, width);
+}
+
+/* 15.2.8.3.13 */
+/*
+ * call-seq:
+ * fix >> count -> integer or float
+ *
+ * Shifts _fix_ right _count_ positions (left if _count_ is negative).
+ */
+
+static mrb_value
+fix_rshift(mrb_state *mrb, mrb_value x)
+{
+ mrb_int width, val;
+
+ mrb_get_args(mrb, "i", &width);
+ if (width == 0) {
+ return x;
+ }
+ val = mrb_fixnum(x);
+ if (val == 0) return x;
+ if (width < 0) {
+ return lshift(mrb, val, -width);
+ }
+ return rshift(val, width);
+}
+
+/* 15.2.8.3.23 */
+/*
+ * call-seq:
+ * fix.to_f -> float
+ *
+ * Converts <i>fix</i> to a <code>Float</code>.
+ *
+ */
+
+static mrb_value
+fix_to_f(mrb_state *mrb, mrb_value num)
+{
+ return mrb_float_value(mrb, (mrb_float)mrb_fixnum(num));
+}
+
+/*
+ * Document-class: FloatDomainError
+ *
+ * Raised when attempting to convert special float values
+ * (in particular infinite or NaN)
+ * to numerical classes which don't support them.
+ *
+ * Float::INFINITY.to_r
+ *
+ * <em>raises the exception:</em>
+ *
+ * FloatDomainError: Infinity
+ */
+/* ------------------------------------------------------------------------*/
+MRB_API mrb_value
+mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
+{
+ mrb_int z = 0;
+
+ if (!mrb_float_p(x)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "non float value");
+ z = 0; /* not reached. just suppress warnings. */
+ }
+ else {
+ mrb_float d = mrb_float(x);
+
+ if (isinf(d)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
+ }
+ if (isnan(d)) {
+ mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
+ }
+ if (FIXABLE_FLOAT(d)) {
+ z = (mrb_int)d;
+ }
+ else {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x);
+ }
+ }
+ return mrb_fixnum_value(z);
+}
+
+mrb_value
+mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ mrb_int a;
+
+ a = mrb_fixnum(x);
+ if (mrb_fixnum_p(y)) {
+ mrb_int b, c;
+
+ if (a == 0) return y;
+ b = mrb_fixnum(y);
+ if (mrb_int_add_overflow(a, b, &c)) {
+ return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b);
+ }
+ return mrb_fixnum_value(c);
+ }
+ return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
+}
+
+/* 15.2.8.3.1 */
+/*
+ * call-seq:
+ * fix + numeric -> numeric_result
+ *
+ * Performs addition: the class of the resulting object depends on
+ * the class of <code>numeric</code> and on the magnitude of the
+ * result.
+ */
+static mrb_value
+fix_plus(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+
+ mrb_get_args(mrb, "o", &other);
+ return mrb_fixnum_plus(mrb, self, other);
+}
+
+mrb_value
+mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
+{
+ mrb_int a;
+
+ a = mrb_fixnum(x);
+ if (mrb_fixnum_p(y)) {
+ mrb_int b, c;
+
+ b = mrb_fixnum(y);
+ if (mrb_int_sub_overflow(a, b, &c)) {
+ return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b);
+ }
+ return mrb_fixnum_value(c);
+ }
+ return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
+}
+
+/* 15.2.8.3.2 */
+/* 15.2.8.3.16 */
+/*
+ * call-seq:
+ * fix - numeric -> numeric_result
+ *
+ * Performs subtraction: the class of the resulting object depends on
+ * the class of <code>numeric</code> and on the magnitude of the
+ * result.
+ */
+static mrb_value
+fix_minus(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+
+ mrb_get_args(mrb, "o", &other);
+ return mrb_fixnum_minus(mrb, self, other);
+}
+
+
+MRB_API mrb_value
+mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base)
+{
+ char buf[MRB_INT_BIT+1];
+ char *b = buf + sizeof buf;
+ mrb_int val = mrb_fixnum(x);
+
+ if (base < 2 || 36 < base) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
+ }
+
+ if (val == 0) {
+ *--b = '0';
+ }
+ else if (val < 0) {
+ do {
+ *--b = mrb_digitmap[-(val % base)];
+ } while (val /= base);
+ *--b = '-';
+ }
+ else {
+ do {
+ *--b = mrb_digitmap[(int)(val % base)];
+ } while (val /= base);
+ }
+
+ return mrb_str_new(mrb, b, buf + sizeof(buf) - b);
+}
+
+/* 15.2.8.3.25 */
+/*
+ * call-seq:
+ * fix.to_s(base=10) -> string
+ *
+ * Returns a string containing the representation of <i>fix</i> radix
+ * <i>base</i> (between 2 and 36).
+ *
+ * 12345.to_s #=> "12345"
+ * 12345.to_s(2) #=> "11000000111001"
+ * 12345.to_s(8) #=> "30071"
+ * 12345.to_s(10) #=> "12345"
+ * 12345.to_s(16) #=> "3039"
+ * 12345.to_s(36) #=> "9ix"
+ *
+ */
+static mrb_value
+fix_to_s(mrb_state *mrb, mrb_value self)
+{
+ mrb_int base = 10;
+
+ mrb_get_args(mrb, "|i", &base);
+ return mrb_fixnum_to_str(mrb, self, base);
+}
+
+/* 15.2.9.3.6 */
+/*
+ * call-seq:
+ * self.f <=> other.f => -1, 0, +1
+ * < => -1
+ * = => 0
+ * > => +1
+ * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
+ * less than, equal to, or greater than <i>numeric</i>. This is the
+ * basis for the tests in <code>Comparable</code>.
+ */
+static mrb_value
+num_cmp(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+ mrb_float x, y;
+
+ mrb_get_args(mrb, "o", &other);
+
+ x = mrb_to_flo(mrb, self);
+ switch (mrb_type(other)) {
+ case MRB_TT_FIXNUM:
+ y = (mrb_float)mrb_fixnum(other);
+ break;
+ case MRB_TT_FLOAT:
+ y = mrb_float(other);
+ break;
+ default:
+ return mrb_nil_value();
+ }
+ if (x > y)
+ return mrb_fixnum_value(1);
+ else {
+ if (x < y)
+ return mrb_fixnum_value(-1);
+ return mrb_fixnum_value(0);
+ }
+}
+
+/* 15.2.9.3.1 */
+/*
+ * call-seq:
+ * float + other -> float
+ *
+ * Returns a new float which is the sum of <code>float</code>
+ * and <code>other</code>.
+ */
+static mrb_value
+flo_plus(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
+}
+
+/* ------------------------------------------------------------------------*/
+void
+mrb_init_numeric(mrb_state *mrb)
+{
+ struct RClass *numeric, *integer, *fixnum, *fl;
+
+ /* Numeric Class */
+ numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */
+
+ mrb_define_method(mrb, numeric, "**", num_pow, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */
+ mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
+ mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
+
+ /* Integer Class */
+ integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */
+ MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM);
+ mrb_undef_class_method(mrb, integer, "new");
+ mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
+ mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE());
+ mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */
+ mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */
+ mrb_define_method(mrb, integer, "round", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 (x) */
+ mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.15 (x) */
+
+ /* Fixnum Class */
+ mrb->fixnum_class = fixnum = mrb_define_class(mrb, "Fixnum", integer);
+ mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
+ mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
+ mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
+ mrb_define_method(mrb, fixnum, "%", fix_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */
+ mrb_define_method(mrb, fixnum, "==", fix_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */
+ mrb_define_method(mrb, fixnum, "~", fix_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */
+ mrb_define_method(mrb, fixnum, "&", fix_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */
+ mrb_define_method(mrb, fixnum, "|", fix_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */
+ mrb_define_method(mrb, fixnum, "^", fix_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */
+ mrb_define_method(mrb, fixnum, "<<", fix_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */
+ mrb_define_method(mrb, fixnum, ">>", fix_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
+ mrb_define_method(mrb, fixnum, "eql?", fix_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
+ mrb_define_method(mrb, fixnum, "to_f", fix_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */
+ mrb_define_method(mrb, fixnum, "to_s", fix_to_s, MRB_ARGS_NONE()); /* 15.2.8.3.25 */
+ mrb_define_method(mrb, fixnum, "inspect", fix_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
+
+ /* Float Class */
+ mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */
+ MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT);
+ mrb_undef_class_method(mrb, fl, "new");
+ mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */
+ mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */
+ mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */
+ mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */
+ mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */
+ mrb_define_method(mrb, fl, "~", flo_rev, MRB_ARGS_NONE());
+ mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, ">>", flo_lshift, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, "<<", flo_rshift, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */
+ mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */
+ mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */
+ mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */
+ mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
+ mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
+ mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
+ mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE());
+ mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */
+ mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
+
+ mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */
+ mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE());
+
+#ifdef INFINITY
+ mrb_define_const(mrb, fl, "INFINITY", mrb_float_value(mrb, INFINITY));
+#endif
+#ifdef NAN
+ mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN));
+#endif
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/object.c b/web/server/h2o/libh2o/deps/mruby/src/object.c
new file mode 100644
index 00000000..368e90b9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/object.c
@@ -0,0 +1,610 @@
+/*
+** object.c - Object, NilClass, TrueClass, FalseClass class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include <mruby/class.h>
+
+MRB_API mrb_bool
+mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
+{
+ if (mrb_type(v1) != mrb_type(v2)) return FALSE;
+ switch (mrb_type(v1)) {
+ case MRB_TT_TRUE:
+ return TRUE;
+
+ case MRB_TT_FALSE:
+ case MRB_TT_FIXNUM:
+ return (mrb_fixnum(v1) == mrb_fixnum(v2));
+ case MRB_TT_SYMBOL:
+ return (mrb_symbol(v1) == mrb_symbol(v2));
+
+ case MRB_TT_FLOAT:
+ return (mrb_float(v1) == mrb_float(v2));
+
+ default:
+ return (mrb_ptr(v1) == mrb_ptr(v2));
+ }
+}
+
+MRB_API mrb_bool
+mrb_obj_equal(mrb_state *mrb, mrb_value v1, mrb_value v2)
+{
+ /* temporary definition */
+ return mrb_obj_eq(mrb, v1, v2);
+}
+
+MRB_API mrb_bool
+mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
+{
+ mrb_value result;
+
+ if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE;
+ result = mrb_funcall(mrb, obj1, "==", 1, obj2);
+ if (mrb_test(result)) return TRUE;
+ return FALSE;
+}
+
+/*
+ * Document-class: NilClass
+ *
+ * The class of the singleton object <code>nil</code>.
+ */
+
+/* 15.2.4.3.4 */
+/*
+ * call_seq:
+ * nil.nil? -> true
+ *
+ * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
+ */
+
+static mrb_value
+mrb_true(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_true_value();
+}
+
+/* 15.2.4.3.5 */
+/*
+ * call-seq:
+ * nil.to_s -> ""
+ *
+ * Always returns the empty string.
+ */
+
+static mrb_value
+nil_to_s(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_str_new(mrb, 0, 0);
+}
+
+static mrb_value
+nil_inspect(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_str_new_lit(mrb, "nil");
+}
+
+/***********************************************************************
+ * Document-class: TrueClass
+ *
+ * The global value <code>true</code> is the only instance of class
+ * <code>TrueClass</code> and represents a logically true value in
+ * boolean expressions. The class provides operators allowing
+ * <code>true</code> to be used in logical expressions.
+ */
+
+/* 15.2.5.3.1 */
+/*
+ * call-seq:
+ * true & obj -> true or false
+ *
+ * And---Returns <code>false</code> if <i>obj</i> is
+ * <code>nil</code> or <code>false</code>, <code>true</code> otherwise.
+ */
+
+static mrb_value
+true_and(mrb_state *mrb, mrb_value obj)
+{
+ mrb_bool obj2;
+
+ mrb_get_args(mrb, "b", &obj2);
+
+ return mrb_bool_value(obj2);
+}
+
+/* 15.2.5.3.2 */
+/*
+ * call-seq:
+ * true ^ obj -> !obj
+ *
+ * Exclusive Or---Returns <code>true</code> if <i>obj</i> is
+ * <code>nil</code> or <code>false</code>, <code>false</code>
+ * otherwise.
+ */
+
+static mrb_value
+true_xor(mrb_state *mrb, mrb_value obj)
+{
+ mrb_bool obj2;
+
+ mrb_get_args(mrb, "b", &obj2);
+ return mrb_bool_value(!obj2);
+}
+
+/* 15.2.5.3.3 */
+/*
+ * call-seq:
+ * true.to_s -> "true"
+ *
+ * The string representation of <code>true</code> is "true".
+ */
+
+static mrb_value
+true_to_s(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_str_new_lit(mrb, "true");
+}
+
+/* 15.2.5.3.4 */
+/*
+ * call-seq:
+ * true | obj -> true
+ *
+ * Or---Returns <code>true</code>. As <i>anObject</i> is an argument to
+ * a method call, it is always evaluated; there is no short-circuit
+ * evaluation in this case.
+ *
+ * true | puts("or")
+ * true || puts("logical or")
+ *
+ * <em>produces:</em>
+ *
+ * or
+ */
+
+static mrb_value
+true_or(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_true_value();
+}
+
+/*
+ * Document-class: FalseClass
+ *
+ * The global value <code>false</code> is the only instance of class
+ * <code>FalseClass</code> and represents a logically false value in
+ * boolean expressions. The class provides operators allowing
+ * <code>false</code> to participate correctly in logical expressions.
+ *
+ */
+
+/* 15.2.4.3.1 */
+/* 15.2.6.3.1 */
+/*
+ * call-seq:
+ * false & obj -> false
+ * nil & obj -> false
+ *
+ * And---Returns <code>false</code>. <i>obj</i> is always
+ * evaluated as it is the argument to a method call---there is no
+ * short-circuit evaluation in this case.
+ */
+
+static mrb_value
+false_and(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_false_value();
+}
+
+/* 15.2.4.3.2 */
+/* 15.2.6.3.2 */
+/*
+ * call-seq:
+ * false ^ obj -> true or false
+ * nil ^ obj -> true or false
+ *
+ * Exclusive Or---If <i>obj</i> is <code>nil</code> or
+ * <code>false</code>, returns <code>false</code>; otherwise, returns
+ * <code>true</code>.
+ *
+ */
+
+static mrb_value
+false_xor(mrb_state *mrb, mrb_value obj)
+{
+ mrb_bool obj2;
+
+ mrb_get_args(mrb, "b", &obj2);
+ return mrb_bool_value(obj2);
+}
+
+/* 15.2.4.3.3 */
+/* 15.2.6.3.4 */
+/*
+ * call-seq:
+ * false | obj -> true or false
+ * nil | obj -> true or false
+ *
+ * Or---Returns <code>false</code> if <i>obj</i> is
+ * <code>nil</code> or <code>false</code>; <code>true</code> otherwise.
+ */
+
+static mrb_value
+false_or(mrb_state *mrb, mrb_value obj)
+{
+ mrb_bool obj2;
+
+ mrb_get_args(mrb, "b", &obj2);
+ return mrb_bool_value(obj2);
+}
+
+/* 15.2.6.3.3 */
+/*
+ * call-seq:
+ * false.to_s -> "false"
+ *
+ * 'nuf said...
+ */
+
+static mrb_value
+false_to_s(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_str_new_lit(mrb, "false");
+}
+
+void
+mrb_init_object(mrb_state *mrb)
+{
+ struct RClass *n;
+ struct RClass *t;
+ struct RClass *f;
+
+ mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class);
+ MRB_SET_INSTANCE_TT(n, MRB_TT_TRUE);
+ mrb_undef_class_method(mrb, n, "new");
+ mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */
+ mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */
+ mrb_define_method(mrb, n, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.4.3.3 */
+ mrb_define_method(mrb, n, "nil?", mrb_true, MRB_ARGS_NONE()); /* 15.2.4.3.4 */
+ mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */
+ mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE());
+
+ mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class);
+ MRB_SET_INSTANCE_TT(t, MRB_TT_TRUE);
+ mrb_undef_class_method(mrb, t, "new");
+ mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */
+ mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */
+ mrb_define_method(mrb, t, "to_s", true_to_s, MRB_ARGS_NONE()); /* 15.2.5.3.3 */
+ mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */
+ mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE());
+
+ mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class);
+ MRB_SET_INSTANCE_TT(f, MRB_TT_TRUE);
+ mrb_undef_class_method(mrb, f, "new");
+ mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */
+ mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */
+ mrb_define_method(mrb, f, "to_s", false_to_s, MRB_ARGS_NONE()); /* 15.2.6.3.3 */
+ mrb_define_method(mrb, f, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.6.3.4 */
+ mrb_define_method(mrb, f, "inspect", false_to_s, MRB_ARGS_NONE());
+}
+
+static mrb_value
+inspect_type(mrb_state *mrb, mrb_value val)
+{
+ if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) {
+ return mrb_inspect(mrb, val);
+ }
+ else {
+ return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val));
+ }
+}
+
+static mrb_value
+convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise)
+{
+ mrb_sym m = 0;
+
+ m = mrb_intern_cstr(mrb, method);
+ if (!mrb_respond_to(mrb, val, m)) {
+ if (raise) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname));
+ }
+ return mrb_nil_value();
+ }
+ return mrb_funcall_argv(mrb, val, m, 0, 0);
+}
+
+MRB_API mrb_value
+mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method)
+{
+ mrb_value v;
+
+ if (mrb_fixnum_p(val)) return val;
+ v = convert_type(mrb, val, "Integer", method, FALSE);
+ if (mrb_nil_p(v) || !mrb_fixnum_p(v)) {
+ return mrb_nil_value();
+ }
+ return v;
+}
+
+MRB_API mrb_value
+mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method)
+{
+ mrb_value v;
+
+ if (mrb_type(val) == type) return val;
+ v = convert_type(mrb, val, tname, method, TRUE);
+ if (mrb_type(v) != type) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val,
+ mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method));
+ }
+ return v;
+}
+
+MRB_API mrb_value
+mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method)
+{
+ mrb_value v;
+
+ if (mrb_type(val) == type && type != MRB_TT_DATA && type != MRB_TT_ISTRUCT) return val;
+ v = convert_type(mrb, val, tname, method, FALSE);
+ if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value();
+ return v;
+}
+
+static const struct types {
+ unsigned char type;
+ const char *name;
+} builtin_types[] = {
+/* {MRB_TT_NIL, "nil"}, */
+ {MRB_TT_FALSE, "false"},
+ {MRB_TT_TRUE, "true"},
+ {MRB_TT_FIXNUM, "Fixnum"},
+ {MRB_TT_SYMBOL, "Symbol"}, /* :symbol */
+ {MRB_TT_MODULE, "Module"},
+ {MRB_TT_OBJECT, "Object"},
+ {MRB_TT_CLASS, "Class"},
+ {MRB_TT_ICLASS, "iClass"}, /* internal use: mixed-in module holder */
+ {MRB_TT_SCLASS, "SClass"},
+ {MRB_TT_PROC, "Proc"},
+ {MRB_TT_FLOAT, "Float"},
+ {MRB_TT_ARRAY, "Array"},
+ {MRB_TT_HASH, "Hash"},
+ {MRB_TT_STRING, "String"},
+ {MRB_TT_RANGE, "Range"},
+/* {MRB_TT_BIGNUM, "Bignum"}, */
+ {MRB_TT_FILE, "File"},
+ {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */
+/* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */
+/* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */
+/* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */
+ {MRB_TT_MAXDEFINE, 0}
+};
+
+MRB_API void
+mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
+{
+ const struct types *type = builtin_types;
+ enum mrb_vtype xt;
+
+ xt = mrb_type(x);
+ if ((xt != t) || (xt == MRB_TT_DATA) || (xt == MRB_TT_ISTRUCT)) {
+ while (type->type < MRB_TT_MAXDEFINE) {
+ if (type->type == t) {
+ const char *etype;
+
+ if (mrb_nil_p(x)) {
+ etype = "nil";
+ }
+ else if (mrb_fixnum_p(x)) {
+ etype = "Fixnum";
+ }
+ else if (mrb_type(x) == MRB_TT_SYMBOL) {
+ etype = "Symbol";
+ }
+ else if (mrb_immediate_p(x)) {
+ etype = RSTRING_PTR(mrb_obj_as_string(mrb, x));
+ }
+ else {
+ etype = mrb_obj_classname(mrb, x);
+ }
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
+ mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name));
+ }
+ type++;
+ }
+ mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)",
+ mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x)));
+ }
+}
+
+/* 15.3.1.3.46 */
+/*
+ * call-seq:
+ * obj.to_s => string
+ *
+ * Returns a string representing <i>obj</i>. The default
+ * <code>to_s</code> prints the object's class and an encoding of the
+ * object id. As a special case, the top-level object that is the
+ * initial execution context of Ruby programs returns "main."
+ */
+
+MRB_API mrb_value
+mrb_any_to_s(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value str = mrb_str_new_capa(mrb, 20);
+ const char *cname = mrb_obj_classname(mrb, obj);
+
+ mrb_str_cat_lit(mrb, str, "#<");
+ mrb_str_cat_cstr(mrb, str, cname);
+ mrb_str_cat_lit(mrb, str, ":");
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_ptr(obj)));
+ mrb_str_cat_lit(mrb, str, ">");
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * obj.is_a?(class) => true or false
+ * obj.kind_of?(class) => true or false
+ *
+ * Returns <code>true</code> if <i>class</i> is the class of
+ * <i>obj</i>, or if <i>class</i> is one of the superclasses of
+ * <i>obj</i> or modules included in <i>obj</i>.
+ *
+ * module M; end
+ * class A
+ * include M
+ * end
+ * class B < A; end
+ * class C < B; end
+ * b = B.new
+ * b.instance_of? A #=> false
+ * b.instance_of? B #=> true
+ * b.instance_of? C #=> false
+ * b.instance_of? M #=> false
+ * b.kind_of? A #=> true
+ * b.kind_of? B #=> true
+ * b.kind_of? C #=> false
+ * b.kind_of? M #=> true
+ */
+
+MRB_API mrb_bool
+mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c)
+{
+ struct RClass *cl = mrb_class(mrb, obj);
+
+ switch (c->tt) {
+ case MRB_TT_MODULE:
+ case MRB_TT_CLASS:
+ case MRB_TT_ICLASS:
+ case MRB_TT_SCLASS:
+ break;
+
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "class or module required");
+ }
+
+ MRB_CLASS_ORIGIN(c);
+ while (cl) {
+ if (cl == c || cl->mt == c->mt)
+ return TRUE;
+ cl = cl->super;
+ }
+ return FALSE;
+}
+
+static mrb_value
+mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method)
+{
+ mrb_value v;
+
+ if (mrb_fixnum_p(val)) return val;
+ v = convert_type(mrb, val, "Integer", method, TRUE);
+ if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) {
+ mrb_value type = inspect_type(mrb, val);
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)",
+ type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v));
+ }
+ return v;
+}
+
+MRB_API mrb_value
+mrb_to_int(mrb_state *mrb, mrb_value val)
+{
+ return mrb_to_integer(mrb, val, "to_int");
+}
+
+MRB_API mrb_value
+mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base)
+{
+ mrb_value tmp;
+
+ if (mrb_nil_p(val)) {
+ if (base != 0) goto arg_error;
+ mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer");
+ }
+ switch (mrb_type(val)) {
+ case MRB_TT_FLOAT:
+ if (base != 0) goto arg_error;
+ else {
+ mrb_float f = mrb_float(val);
+ if (FIXABLE_FLOAT(f)) {
+ break;
+ }
+ }
+ return mrb_flo_to_fixnum(mrb, val);
+
+ case MRB_TT_FIXNUM:
+ if (base != 0) goto arg_error;
+ return val;
+
+ case MRB_TT_STRING:
+ string_conv:
+ return mrb_str_to_inum(mrb, val, base, TRUE);
+
+ default:
+ break;
+ }
+ if (base != 0) {
+ tmp = mrb_check_string_type(mrb, val);
+ if (!mrb_nil_p(tmp)) {
+ val = tmp;
+ goto string_conv;
+ }
+arg_error:
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value");
+ }
+ tmp = convert_type(mrb, val, "Integer", "to_int", FALSE);
+ if (mrb_nil_p(tmp)) {
+ return mrb_to_integer(mrb, val, "to_i");
+ }
+ return tmp;
+}
+
+MRB_API mrb_value
+mrb_Integer(mrb_state *mrb, mrb_value val)
+{
+ return mrb_convert_to_integer(mrb, val, 0);
+}
+
+MRB_API mrb_value
+mrb_Float(mrb_state *mrb, mrb_value val)
+{
+ if (mrb_nil_p(val)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float");
+ }
+ switch (mrb_type(val)) {
+ case MRB_TT_FIXNUM:
+ return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val));
+
+ case MRB_TT_FLOAT:
+ return val;
+
+ case MRB_TT_STRING:
+ return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE));
+
+ default:
+ return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f");
+ }
+}
+
+MRB_API mrb_value
+mrb_inspect(mrb_state *mrb, mrb_value obj)
+{
+ return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0));
+}
+
+MRB_API mrb_bool
+mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
+{
+ if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE;
+ return mrb_test(mrb_funcall(mrb, obj1, "eql?", 1, obj2));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/opcode.h b/web/server/h2o/libh2o/deps/mruby/src/opcode.h
new file mode 100644
index 00000000..fe4d17a2
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/opcode.h
@@ -0,0 +1,2 @@
+/* this header file is to be removed soon. */
+#include <mruby/opcode.h>
diff --git a/web/server/h2o/libh2o/deps/mruby/src/pool.c b/web/server/h2o/libh2o/deps/mruby/src/pool.c
new file mode 100644
index 00000000..db4546ab
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/pool.c
@@ -0,0 +1,198 @@
+/*
+** pool.c - memory pool
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <mruby.h>
+
+/* configuration section */
+/* allocated memory address should be multiple of POOL_ALIGNMENT */
+/* or undef it if alignment does not matter */
+#ifndef POOL_ALIGNMENT
+#if INTPTR_MAX == INT64_MAX
+#define POOL_ALIGNMENT 8
+#else
+#define POOL_ALIGNMENT 4
+#endif
+#endif
+/* page size of memory pool */
+#ifndef POOL_PAGE_SIZE
+#define POOL_PAGE_SIZE 16000
+#endif
+/* end of configuration section */
+
+struct mrb_pool_page {
+ struct mrb_pool_page *next;
+ size_t offset;
+ size_t len;
+ void *last;
+ char page[];
+};
+
+struct mrb_pool {
+ mrb_state *mrb;
+ struct mrb_pool_page *pages;
+};
+
+#undef TEST_POOL
+#ifdef TEST_POOL
+
+#define mrb_malloc_simple(m,s) malloc(s)
+#define mrb_free(m,p) free(p)
+#endif
+
+#ifdef POOL_ALIGNMENT
+# define ALIGN_PADDING(x) ((SIZE_MAX - (x) + 1) & (POOL_ALIGNMENT - 1))
+#else
+# define ALIGN_PADDING(x) (0)
+#endif
+
+MRB_API mrb_pool*
+mrb_pool_open(mrb_state *mrb)
+{
+ mrb_pool *pool = (mrb_pool *)mrb_malloc_simple(mrb, sizeof(mrb_pool));
+
+ if (pool) {
+ pool->mrb = mrb;
+ pool->pages = NULL;
+ }
+
+ return pool;
+}
+
+MRB_API void
+mrb_pool_close(mrb_pool *pool)
+{
+ struct mrb_pool_page *page, *tmp;
+
+ if (!pool) return;
+ page = pool->pages;
+ while (page) {
+ tmp = page;
+ page = page->next;
+ mrb_free(pool->mrb, tmp);
+ }
+ mrb_free(pool->mrb, pool);
+}
+
+static struct mrb_pool_page*
+page_alloc(mrb_pool *pool, size_t len)
+{
+ struct mrb_pool_page *page;
+
+ if (len < POOL_PAGE_SIZE)
+ len = POOL_PAGE_SIZE;
+ page = (struct mrb_pool_page *)mrb_malloc_simple(pool->mrb, sizeof(struct mrb_pool_page)+len);
+ if (page) {
+ page->offset = 0;
+ page->len = len;
+ }
+
+ return page;
+}
+
+MRB_API void*
+mrb_pool_alloc(mrb_pool *pool, size_t len)
+{
+ struct mrb_pool_page *page;
+ size_t n;
+
+ if (!pool) return NULL;
+ len += ALIGN_PADDING(len);
+ page = pool->pages;
+ while (page) {
+ if (page->offset + len <= page->len) {
+ n = page->offset;
+ page->offset += len;
+ page->last = (char*)page->page+n;
+ return page->last;
+ }
+ page = page->next;
+ }
+ page = page_alloc(pool, len);
+ if (!page) return NULL;
+ page->offset = len;
+ page->next = pool->pages;
+ pool->pages = page;
+
+ page->last = (void*)page->page;
+ return page->last;
+}
+
+MRB_API mrb_bool
+mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
+{
+ struct mrb_pool_page *page;
+
+ if (!pool) return FALSE;
+ len += ALIGN_PADDING(len);
+ page = pool->pages;
+ while (page) {
+ if (page->last == p) {
+ size_t beg;
+
+ beg = (char*)p - page->page;
+ if (beg + len > page->len) return FALSE;
+ return TRUE;
+ }
+ page = page->next;
+ }
+ return FALSE;
+}
+
+MRB_API void*
+mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
+{
+ struct mrb_pool_page *page;
+ void *np;
+
+ if (!pool) return NULL;
+ oldlen += ALIGN_PADDING(oldlen);
+ newlen += ALIGN_PADDING(newlen);
+ page = pool->pages;
+ while (page) {
+ if (page->last == p) {
+ size_t beg;
+
+ beg = (char*)p - page->page;
+ if (beg + oldlen != page->offset) break;
+ if (beg + newlen > page->len) {
+ page->offset = beg;
+ break;
+ }
+ page->offset = beg + newlen;
+ return p;
+ }
+ page = page->next;
+ }
+ np = mrb_pool_alloc(pool, newlen);
+ if (np == NULL) {
+ return NULL;
+ }
+ memcpy(np, p, oldlen);
+ return np;
+}
+
+#ifdef TEST_POOL
+int
+main(void)
+{
+ int i, len = 250;
+ mrb_pool *pool;
+ void *p;
+
+ pool = mrb_pool_open(NULL);
+ p = mrb_pool_alloc(pool, len);
+ for (i=1; i<20; i++) {
+ printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2));
+ p = mrb_pool_realloc(pool, p, len, len*2);
+ len *= 2;
+ }
+ mrb_pool_close(pool);
+ return 0;
+}
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/src/print.c b/web/server/h2o/libh2o/deps/mruby/src/print.c
new file mode 100644
index 00000000..03b5eadf
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/print.c
@@ -0,0 +1,47 @@
+/*
+** print.c - Kernel.#p
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+
+#ifndef MRB_DISABLE_STDIO
+static void
+printstr(mrb_value obj, FILE *stream)
+{
+ if (mrb_string_p(obj)) {
+ fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stream);
+ putc('\n', stream);
+ }
+}
+#else
+# define printstr(obj, stream) (void)0
+#endif
+
+MRB_API void
+mrb_p(mrb_state *mrb, mrb_value obj)
+{
+ printstr(mrb_inspect(mrb, obj), stdout);
+}
+
+MRB_API void
+mrb_print_error(mrb_state *mrb)
+{
+ mrb_print_backtrace(mrb);
+ printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr);
+}
+
+MRB_API void
+mrb_show_version(mrb_state *mrb)
+{
+ printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")), stdout);
+}
+
+MRB_API void
+mrb_show_copyright(mrb_state *mrb)
+{
+ printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")), stdout);
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/proc.c b/web/server/h2o/libh2o/deps/mruby/src/proc.c
new file mode 100644
index 00000000..10a2c4f3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/proc.c
@@ -0,0 +1,294 @@
+/*
+** proc.c - Proc class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
+
+static mrb_code call_iseq[] = {
+ MKOP_A(OP_CALL, 0),
+};
+
+struct RProc*
+mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
+{
+ struct RProc *p;
+ mrb_callinfo *ci = mrb->c->ci;
+
+ p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ p->target_class = 0;
+ if (ci) {
+ if (ci->proc)
+ p->target_class = ci->proc->target_class;
+ if (!p->target_class)
+ p->target_class = ci->target_class;
+ }
+ p->body.irep = irep;
+ p->env = 0;
+ mrb_irep_incref(mrb, irep);
+
+ return p;
+}
+
+static struct REnv*
+env_new(mrb_state *mrb, int nlocals)
+{
+ struct REnv *e;
+
+ e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
+ MRB_SET_ENV_STACK_LEN(e, nlocals);
+ e->cxt.c = mrb->c;
+ e->cioff = mrb->c->ci - mrb->c->cibase;
+ e->stack = mrb->c->stack;
+
+ return e;
+}
+
+static void
+closure_setup(mrb_state *mrb, struct RProc *p, int nlocals)
+{
+ struct REnv *e;
+
+ if (!mrb->c->ci->env) {
+ e = env_new(mrb, nlocals);
+ mrb->c->ci->env = e;
+ }
+ else {
+ e = mrb->c->ci->env;
+ }
+ p->env = e;
+ mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
+}
+
+struct RProc*
+mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
+{
+ struct RProc *p = mrb_proc_new(mrb, irep);
+
+ closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals);
+ return p;
+}
+
+MRB_API struct RProc*
+mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
+{
+ struct RProc *p;
+
+ p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ p->body.func = func;
+ p->flags |= MRB_PROC_CFUNC;
+ p->env = 0;
+
+ return p;
+}
+
+MRB_API struct RProc*
+mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv)
+{
+ struct RProc *p = mrb_proc_new_cfunc(mrb, func);
+ struct REnv *e;
+ int i;
+
+ p->env = e = env_new(mrb, argc);
+ mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
+ MRB_ENV_UNSHARE_STACK(e);
+ e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
+ if (argv) {
+ for (i = 0; i < argc; ++i) {
+ e->stack[i] = argv[i];
+ }
+ }
+ else {
+ for (i = 0; i < argc; ++i) {
+ SET_NIL_VALUE(e->stack[i]);
+ }
+ }
+ return p;
+}
+
+MRB_API struct RProc*
+mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals)
+{
+ return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL);
+}
+
+MRB_API mrb_value
+mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
+{
+ struct RProc *p = mrb->c->ci->proc;
+ struct REnv *e = p->env;
+
+ if (!MRB_PROC_CFUNC_P(p)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc.");
+ }
+ if (!e) {
+ mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
+ }
+ if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) {
+ mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)",
+ mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e)));
+ }
+
+ return e->stack[idx];
+}
+
+void
+mrb_proc_copy(struct RProc *a, struct RProc *b)
+{
+ if (a->body.irep) {
+ /* already initialized proc */
+ return;
+ }
+ a->flags = b->flags;
+ a->body = b->body;
+ if (!MRB_PROC_CFUNC_P(a) && a->body.irep) {
+ a->body.irep->refcnt++;
+ }
+ a->target_class = b->target_class;
+ a->env = b->env;
+}
+
+static mrb_value
+mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class)
+{
+ mrb_value blk;
+ mrb_value proc;
+ struct RProc *p;
+
+ mrb_get_args(mrb, "&", &blk);
+ if (mrb_nil_p(blk)) {
+ /* Calling Proc.new without a block is not implemented yet */
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
+ }
+ p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class));
+ mrb_proc_copy(p, mrb_proc_ptr(blk));
+ proc = mrb_obj_value(p);
+ mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, proc);
+ if (!MRB_PROC_STRICT_P(p) &&
+ mrb->c->ci > mrb->c->cibase && p->env == mrb->c->ci[-1].env) {
+ p->flags |= MRB_PROC_ORPHAN;
+ }
+ return proc;
+}
+
+static mrb_value
+mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
+{
+ mrb_value proc;
+
+ mrb_get_args(mrb, "o", &proc);
+ if (mrb_type(proc) != MRB_TT_PROC) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
+ }
+ mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc));
+ return self;
+}
+
+int
+mrb_proc_cfunc_p(struct RProc *p)
+{
+ return MRB_PROC_CFUNC_P(p);
+}
+
+mrb_value
+mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)
+{
+ return (p->body.func)(mrb, self);
+}
+
+/* 15.2.17.4.2 */
+static mrb_value
+mrb_proc_arity(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *p = mrb_proc_ptr(self);
+ struct mrb_irep *irep;
+ mrb_code *iseq;
+ mrb_aspec aspec;
+ int ma, op, ra, pa, arity;
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ /* TODO cfunc aspec not implemented yet */
+ return mrb_fixnum_value(-1);
+ }
+
+ irep = p->body.irep;
+ if (!irep) {
+ return mrb_fixnum_value(0);
+ }
+
+ iseq = irep->iseq;
+ /* arity is depend on OP_ENTER */
+ if (GET_OPCODE(*iseq) != OP_ENTER) {
+ return mrb_fixnum_value(0);
+ }
+
+ aspec = GETARG_Ax(*iseq);
+ ma = MRB_ASPEC_REQ(aspec);
+ op = MRB_ASPEC_OPT(aspec);
+ ra = MRB_ASPEC_REST(aspec);
+ pa = MRB_ASPEC_POST(aspec);
+ arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
+
+ return mrb_fixnum_value(arity);
+}
+
+/* 15.3.1.2.6 */
+/* 15.3.1.3.27 */
+/*
+ * call-seq:
+ * lambda { |...| block } -> a_proc
+ *
+ * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
+ * check the number of parameters passed when called.
+ */
+static mrb_value
+proc_lambda(mrb_state *mrb, mrb_value self)
+{
+ mrb_value blk;
+ struct RProc *p;
+
+ mrb_get_args(mrb, "&", &blk);
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
+ }
+ if (mrb_type(blk) != MRB_TT_PROC) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
+ }
+ p = mrb_proc_ptr(blk);
+ if (!MRB_PROC_STRICT_P(p)) {
+ struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c);
+ mrb_proc_copy(p2, p);
+ p2->flags |= MRB_PROC_STRICT;
+ return mrb_obj_value(p2);
+ }
+ return blk;
+}
+
+void
+mrb_init_proc(mrb_state *mrb)
+{
+ struct RProc *m;
+ mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
+ static const mrb_irep mrb_irep_zero = { 0 };
+
+ *call_irep = mrb_irep_zero;
+ call_irep->flags = MRB_ISEQ_NO_FREE;
+ call_irep->iseq = call_iseq;
+ call_irep->ilen = 1;
+ call_irep->nregs = 2; /* receiver and block */
+
+ mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_ANY());
+ mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
+
+ m = mrb_proc_new(mrb, call_irep);
+ mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
+ mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
+
+ mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */
+ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/range.c b/web/server/h2o/libh2o/deps/mruby/src/range.c
new file mode 100644
index 00000000..eb9a9c61
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/range.c
@@ -0,0 +1,442 @@
+/*
+** range.c - Range class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/array.h>
+
+MRB_API struct RRange*
+mrb_range_ptr(mrb_state *mrb, mrb_value v)
+{
+ struct RRange *r = (struct RRange*)mrb_ptr(v);
+
+ if (r->edges == NULL) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized range");
+ }
+ return r;
+}
+
+static void
+range_check(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value ans;
+ enum mrb_vtype ta;
+ enum mrb_vtype tb;
+
+ ta = mrb_type(a);
+ tb = mrb_type(b);
+ if ((ta == MRB_TT_FIXNUM || ta == MRB_TT_FLOAT) &&
+ (tb == MRB_TT_FIXNUM || tb == MRB_TT_FLOAT)) {
+ return;
+ }
+
+ ans = mrb_funcall(mrb, a, "<=>", 1, b);
+ if (mrb_nil_p(ans)) {
+ /* can not be compared */
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
+ }
+}
+
+MRB_API mrb_value
+mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, mrb_bool excl)
+{
+ struct RRange *r;
+
+ range_check(mrb, beg, end);
+ r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, mrb->range_class);
+ r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
+ r->edges->beg = beg;
+ r->edges->end = end;
+ r->excl = excl;
+ return mrb_range_value(r);
+}
+
+/*
+ * call-seq:
+ * rng.first => obj
+ * rng.begin => obj
+ *
+ * Returns the first object in <i>rng</i>.
+ */
+mrb_value
+mrb_range_beg(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ return r->edges->beg;
+}
+
+/*
+ * call-seq:
+ * rng.end => obj
+ * rng.last => obj
+ *
+ * Returns the object that defines the end of <i>rng</i>.
+ *
+ * (1..10).end #=> 10
+ * (1...10).end #=> 10
+ */
+
+mrb_value
+mrb_range_end(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ return r->edges->end;
+}
+
+/*
+ * call-seq:
+ * range.exclude_end? => true or false
+ *
+ * Returns <code>true</code> if <i>range</i> excludes its end value.
+ */
+mrb_value
+mrb_range_excl(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ return mrb_bool_value(r->excl);
+}
+
+static void
+range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_bool exclude_end)
+{
+ struct RRange *r = mrb_range_raw_ptr(range);
+
+ range_check(mrb, beg, end);
+ r->excl = exclude_end;
+ if (!r->edges) {
+ r->edges = (mrb_range_edges *)mrb_malloc(mrb, sizeof(mrb_range_edges));
+ }
+ r->edges->beg = beg;
+ r->edges->end = end;
+}
+/*
+ * call-seq:
+ * Range.new(start, end, exclusive=false) => range
+ *
+ * Constructs a range using the given <i>start</i> and <i>end</i>. If the third
+ * parameter is omitted or is <code>false</code>, the <i>range</i> will include
+ * the end object; otherwise, it will be excluded.
+ */
+
+mrb_value
+mrb_range_initialize(mrb_state *mrb, mrb_value range)
+{
+ mrb_value beg, end;
+ mrb_bool exclusive;
+ int n;
+
+ n = mrb_get_args(mrb, "oo|b", &beg, &end, &exclusive);
+ if (n != 3) {
+ exclusive = FALSE;
+ }
+ /* Ranges are immutable, so that they should be initialized only once. */
+ if (mrb_range_raw_ptr(range)->edges) {
+ mrb_name_error(mrb, mrb_intern_lit(mrb, "initialize"), "`initialize' called twice");
+ }
+ range_init(mrb, range, beg, end, exclusive);
+ return range;
+}
+/*
+ * call-seq:
+ * range == obj => true or false
+ *
+ * Returns <code>true</code> only if
+ * 1) <i>obj</i> is a Range,
+ * 2) <i>obj</i> has equivalent beginning and end items (by comparing them with <code>==</code>),
+ * 3) <i>obj</i> has the same #exclude_end? setting as <i>rng</t>.
+ *
+ * (0..2) == (0..2) #=> true
+ * (0..2) == Range.new(0,2) #=> true
+ * (0..2) == (0...2) #=> false
+ *
+ */
+
+mrb_value
+mrb_range_eq(mrb_state *mrb, mrb_value range)
+{
+ struct RRange *rr;
+ struct RRange *ro;
+ mrb_value obj, v1, v2;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
+ if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
+ return mrb_false_value();
+ }
+
+ rr = mrb_range_ptr(mrb, range);
+ ro = mrb_range_ptr(mrb, obj);
+ v1 = mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg);
+ v2 = mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end);
+ if (!mrb_bool(v1) || !mrb_bool(v2) || rr->excl != ro->excl) {
+ return mrb_false_value();
+ }
+ return mrb_true_value();
+}
+
+static mrb_bool
+r_le(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ if (mrb_fixnum_p(r)) {
+ mrb_int c = mrb_fixnum(r);
+ if (c == 0 || c == -1) return TRUE;
+ }
+
+ return FALSE;
+}
+
+static mrb_bool
+r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ return mrb_fixnum_p(r) && mrb_fixnum(r) == 1;
+}
+
+static mrb_bool
+r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
+ /* output :a < b => -1, a = b => 0, a > b => +1 */
+
+ if (mrb_fixnum_p(r)) {
+ mrb_int c = mrb_fixnum(r);
+ if (c == 0 || c == 1) return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * call-seq:
+ * range === obj => true or false
+ * range.member?(val) => true or false
+ * range.include?(val) => true or false
+ *
+ */
+mrb_value
+mrb_range_include(mrb_state *mrb, mrb_value range)
+{
+ mrb_value val;
+ struct RRange *r = mrb_range_ptr(mrb, range);
+ mrb_value beg, end;
+ mrb_bool include_p;
+
+ mrb_get_args(mrb, "o", &val);
+
+ beg = r->edges->beg;
+ end = r->edges->end;
+ include_p = r_le(mrb, beg, val) && /* beg <= val */
+ (r->excl ? r_gt(mrb, end, val) /* end > val */
+ : r_ge(mrb, end, val)); /* end >= val */
+
+ return mrb_bool_value(include_p);
+}
+
+MRB_API mrb_int
+mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc)
+{
+ mrb_int beg, end;
+ struct RRange *r;
+
+ if (mrb_type(range) != MRB_TT_RANGE) return 0;
+ r = mrb_range_ptr(mrb, range);
+
+ beg = mrb_int(mrb, r->edges->beg);
+ end = mrb_int(mrb, r->edges->end);
+
+ if (beg < 0) {
+ beg += len;
+ if (beg < 0) return 2;
+ }
+
+ if (trunc) {
+ if (beg > len) return 2;
+ if (end > len) end = len;
+ }
+
+ if (end < 0) end += len;
+ if (!r->excl && (!trunc || end < len))
+ end++; /* include end point */
+ len = end - beg;
+ if (len < 0) len = 0;
+
+ *begp = beg;
+ *lenp = len;
+ return 1;
+}
+
+/* 15.2.14.4.12(x) */
+/*
+ * call-seq:
+ * rng.to_s -> string
+ *
+ * Convert this range object to a printable form.
+ */
+
+static mrb_value
+range_to_s(mrb_state *mrb, mrb_value range)
+{
+ mrb_value str, str2;
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ str = mrb_obj_as_string(mrb, r->edges->beg);
+ str2 = mrb_obj_as_string(mrb, r->edges->end);
+ str = mrb_str_dup(mrb, str);
+ mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
+ mrb_str_cat_str(mrb, str, str2);
+
+ return str;
+}
+
+/* 15.2.14.4.13(x) */
+/*
+ * call-seq:
+ * rng.inspect -> string
+ *
+ * Convert this range object to a printable form (using
+ * <code>inspect</code> to convert the start and end
+ * objects).
+ */
+
+static mrb_value
+range_inspect(mrb_state *mrb, mrb_value range)
+{
+ mrb_value str, str2;
+ struct RRange *r = mrb_range_ptr(mrb, range);
+
+ str = mrb_inspect(mrb, r->edges->beg);
+ str2 = mrb_inspect(mrb, r->edges->end);
+ str = mrb_str_dup(mrb, str);
+ mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
+ mrb_str_cat_str(mrb, str, str2);
+
+ return str;
+}
+
+/* 15.2.14.4.14(x) */
+/*
+ * call-seq:
+ * rng.eql?(obj) -> true or false
+ *
+ * Returns <code>true</code> only if <i>obj</i> is a Range, has equivalent
+ * beginning and end items (by comparing them with #eql?), and has the same
+ * #exclude_end? setting as <i>rng</i>.
+ *
+ * (0..2).eql?(0..2) #=> true
+ * (0..2).eql?(Range.new(0,2)) #=> true
+ * (0..2).eql?(0...2) #=> false
+ *
+ */
+
+static mrb_value
+range_eql(mrb_state *mrb, mrb_value range)
+{
+ mrb_value obj;
+ struct RRange *r, *o;
+
+ mrb_get_args(mrb, "o", &obj);
+
+ if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
+ if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) {
+ return mrb_false_value();
+ }
+ if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value();
+
+ r = mrb_range_ptr(mrb, range);
+ o = mrb_range_ptr(mrb, obj);
+ if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) ||
+ !mrb_eql(mrb, r->edges->end, o->edges->end) ||
+ (r->excl != o->excl)) {
+ return mrb_false_value();
+ }
+ return mrb_true_value();
+}
+
+/* 15.2.14.4.15(x) */
+static mrb_value
+range_initialize_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_value src;
+ struct RRange *r;
+
+ mrb_get_args(mrb, "o", &src);
+
+ if (mrb_obj_equal(mrb, copy, src)) return copy;
+ if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+
+ r = mrb_range_ptr(mrb, src);
+ range_init(mrb, copy, r->edges->beg, r->edges->end, r->excl);
+
+ return copy;
+}
+
+mrb_value
+mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int))
+{
+ mrb_int i, j, beg, len;
+ mrb_value result;
+ result = mrb_ary_new(mrb);
+
+ for (i = 0; i < argc; ++i) {
+ if (mrb_fixnum_p(argv[i])) {
+ mrb_ary_push(mrb, result, func(mrb, obj, mrb_fixnum(argv[i])));
+ }
+ else if (mrb_range_beg_len(mrb, argv[i], &beg, &len, olen, FALSE) == 1) {
+ mrb_int const end = olen < beg + len ? olen : beg + len;
+ for (j = beg; j < end; ++j) {
+ mrb_ary_push(mrb, result, func(mrb, obj, j));
+ }
+
+ for (; j < beg + len; ++j) {
+ mrb_ary_push(mrb, result, mrb_nil_value());
+ }
+ }
+ else {
+ mrb_raisef(mrb, E_TYPE_ERROR, "invalid values selector: %S", argv[i]);
+ }
+ }
+
+ return result;
+}
+
+void
+mrb_init_range(mrb_state *mrb)
+{
+ struct RClass *r;
+
+ r = mrb_define_class(mrb, "Range", mrb->object_class); /* 15.2.14 */
+ mrb->range_class = r;
+ MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE);
+
+ mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */
+ mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */
+ mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */
+ mrb_define_method(mrb, r, "===", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */
+ mrb_define_method(mrb, r, "exclude_end?", mrb_range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */
+ mrb_define_method(mrb, r, "first", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */
+ mrb_define_method(mrb, r, "include?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */
+ mrb_define_method(mrb, r, "initialize", mrb_range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */
+ mrb_define_method(mrb, r, "last", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */
+ mrb_define_method(mrb, r, "member?", mrb_range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */
+
+ mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */
+ mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */
+ mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */
+ mrb_define_method(mrb, r, "initialize_copy", range_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.14.4.15(x) */
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/state.c b/web/server/h2o/libh2o/deps/mruby/src/state.c
new file mode 100644
index 00000000..039d67d5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/state.c
@@ -0,0 +1,303 @@
+/*
+** state.c - mrb_state open/close functions
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/irep.h>
+#include <mruby/variable.h>
+#include <mruby/debug.h>
+#include <mruby/string.h>
+
+void mrb_init_core(mrb_state*);
+void mrb_init_mrbgems(mrb_state*);
+
+void mrb_gc_init(mrb_state*, mrb_gc *gc);
+void mrb_gc_destroy(mrb_state*, mrb_gc *gc);
+
+static mrb_value
+inspect_main(mrb_state *mrb, mrb_value mod)
+{
+ return mrb_str_new_lit(mrb, "main");
+}
+
+MRB_API mrb_state*
+mrb_open_core(mrb_allocf f, void *ud)
+{
+ static const mrb_state mrb_state_zero = { 0 };
+ static const struct mrb_context mrb_context_zero = { 0 };
+ mrb_state *mrb;
+
+ mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud);
+ if (mrb == NULL) return NULL;
+
+ *mrb = mrb_state_zero;
+ mrb->allocf_ud = ud;
+ mrb->allocf = f;
+ mrb->atexit_stack_len = 0;
+
+ mrb_gc_init(mrb, &mrb->gc);
+ mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
+ *mrb->c = mrb_context_zero;
+ mrb->root_c = mrb->c;
+
+ mrb_init_core(mrb);
+
+ return mrb;
+}
+
+void*
+mrb_default_allocf(mrb_state *mrb, void *p, size_t size, void *ud)
+{
+ if (size == 0) {
+ free(p);
+ return NULL;
+ }
+ else {
+ return realloc(p, size);
+ }
+}
+
+struct alloca_header {
+ struct alloca_header *next;
+ char buf[];
+};
+
+MRB_API void*
+mrb_alloca(mrb_state *mrb, size_t size)
+{
+ struct alloca_header *p;
+
+ p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size);
+ p->next = mrb->mems;
+ mrb->mems = p;
+ return (void*)p->buf;
+}
+
+static void
+mrb_alloca_free(mrb_state *mrb)
+{
+ struct alloca_header *p;
+ struct alloca_header *tmp;
+
+ if (mrb == NULL) return;
+ p = mrb->mems;
+
+ while (p) {
+ tmp = p;
+ p = p->next;
+ mrb_free(mrb, tmp);
+ }
+}
+
+MRB_API mrb_state*
+mrb_open(void)
+{
+ mrb_state *mrb = mrb_open_allocf(mrb_default_allocf, NULL);
+
+ return mrb;
+}
+
+MRB_API mrb_state*
+mrb_open_allocf(mrb_allocf f, void *ud)
+{
+ mrb_state *mrb = mrb_open_core(f, ud);
+
+ if (mrb == NULL) {
+ return NULL;
+ }
+
+#ifndef DISABLE_GEMS
+ mrb_init_mrbgems(mrb);
+ mrb_gc_arena_restore(mrb, 0);
+#endif
+ return mrb;
+}
+
+void mrb_free_symtbl(mrb_state *mrb);
+
+void
+mrb_irep_incref(mrb_state *mrb, mrb_irep *irep)
+{
+ irep->refcnt++;
+}
+
+void
+mrb_irep_decref(mrb_state *mrb, mrb_irep *irep)
+{
+ irep->refcnt--;
+ if (irep->refcnt == 0) {
+ mrb_irep_free(mrb, irep);
+ }
+}
+
+void
+mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
+{
+ int i;
+
+ if (!(irep->flags & MRB_ISEQ_NO_FREE))
+ mrb_free(mrb, irep->iseq);
+ if (irep->pool) for (i=0; i<irep->plen; i++) {
+ if (mrb_type(irep->pool[i]) == MRB_TT_STRING) {
+ mrb_gc_free_str(mrb, RSTRING(irep->pool[i]));
+ mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
+ }
+#ifdef MRB_WORD_BOXING
+ else if (mrb_type(irep->pool[i]) == MRB_TT_FLOAT) {
+ mrb_free(mrb, mrb_obj_ptr(irep->pool[i]));
+ }
+#endif
+ }
+ mrb_free(mrb, irep->pool);
+ mrb_free(mrb, irep->syms);
+ for (i=0; i<irep->rlen; i++) {
+ mrb_irep_decref(mrb, irep->reps[i]);
+ }
+ if (irep->outer)
+ mrb_irep_decref(mrb, irep->outer);
+ mrb_free(mrb, irep->reps);
+ mrb_free(mrb, irep->lv);
+ if (irep->own_filename) {
+ mrb_free(mrb, (void *)irep->filename);
+ }
+ mrb_free(mrb, irep->lines);
+ mrb_debug_info_free(mrb, irep->debug_info);
+ mrb_free(mrb, irep);
+}
+
+mrb_value
+mrb_str_pool(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+ struct RString *ns;
+ char *ptr;
+ mrb_int len;
+
+ ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString));
+ ns->tt = MRB_TT_STRING;
+ ns->c = mrb->string_class;
+
+ if (RSTR_NOFREE_P(s)) {
+ ns->flags = MRB_STR_NOFREE;
+ ns->as.heap.ptr = s->as.heap.ptr;
+ ns->as.heap.len = s->as.heap.len;
+ ns->as.heap.aux.capa = 0;
+ }
+ else {
+ ns->flags = 0;
+ if (RSTR_EMBED_P(s)) {
+ ptr = s->as.ary;
+ len = RSTR_EMBED_LEN(s);
+ }
+ else {
+ ptr = s->as.heap.ptr;
+ len = s->as.heap.len;
+ }
+
+ if (len < RSTRING_EMBED_LEN_MAX) {
+ RSTR_SET_EMBED_FLAG(ns);
+ RSTR_SET_EMBED_LEN(ns, len);
+ if (ptr) {
+ memcpy(ns->as.ary, ptr, len);
+ }
+ ns->as.ary[len] = '\0';
+ }
+ else {
+ ns->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
+ ns->as.heap.len = len;
+ ns->as.heap.aux.capa = len;
+ if (ptr) {
+ memcpy(ns->as.heap.ptr, ptr, len);
+ }
+ ns->as.heap.ptr[len] = '\0';
+ }
+ }
+ return mrb_obj_value(ns);
+}
+
+void mrb_free_backtrace(mrb_state *mrb);
+
+MRB_API void
+mrb_free_context(mrb_state *mrb, struct mrb_context *c)
+{
+ if (!c) return;
+ mrb_free(mrb, c->stbase);
+ mrb_free(mrb, c->cibase);
+ mrb_free(mrb, c->rescue);
+ mrb_free(mrb, c->ensure);
+ mrb_free(mrb, c);
+}
+
+MRB_API void
+mrb_close(mrb_state *mrb)
+{
+ if (!mrb) return;
+ if (mrb->atexit_stack_len > 0) {
+ mrb_int i;
+ for (i = mrb->atexit_stack_len; i > 0; --i) {
+ mrb->atexit_stack[i - 1](mrb);
+ }
+#ifndef MRB_FIXED_STATE_ATEXIT_STACK
+ mrb_free(mrb, mrb->atexit_stack);
+#endif
+ }
+
+ /* free */
+ mrb_gc_free_gv(mrb);
+ mrb_free_context(mrb, mrb->root_c);
+ mrb_free_symtbl(mrb);
+ mrb_alloca_free(mrb);
+ mrb_gc_destroy(mrb, &mrb->gc);
+ mrb_free(mrb, mrb);
+}
+
+MRB_API mrb_irep*
+mrb_add_irep(mrb_state *mrb)
+{
+ static const mrb_irep mrb_irep_zero = { 0 };
+ mrb_irep *irep;
+
+ irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
+ *irep = mrb_irep_zero;
+ irep->refcnt = 1;
+ irep->own_filename = FALSE;
+
+ return irep;
+}
+
+MRB_API mrb_value
+mrb_top_self(mrb_state *mrb)
+{
+ if (!mrb->top_self) {
+ mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class);
+ mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE());
+ mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE());
+ }
+ return mrb_obj_value(mrb->top_self);
+}
+
+MRB_API void
+mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f)
+{
+#ifdef MRB_FIXED_STATE_ATEXIT_STACK
+ if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit");
+ }
+#else
+ size_t stack_size;
+
+ stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1);
+ if (mrb->atexit_stack_len == 0) {
+ mrb->atexit_stack = (mrb_atexit_func*)mrb_malloc(mrb, stack_size);
+ }
+ else {
+ mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size);
+ }
+#endif
+
+ mrb->atexit_stack[mrb->atexit_stack_len++] = f;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/string.c b/web/server/h2o/libh2o/deps/mruby/src/string.c
new file mode 100644
index 00000000..01d706fa
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/string.c
@@ -0,0 +1,3013 @@
+/*
+** string.c - String class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifdef _MSC_VER
+# define _CRT_NONSTDC_NO_DEPRECATE
+#endif
+
+#include <float.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/re.h>
+
+typedef struct mrb_shared_string {
+ mrb_bool nofree : 1;
+ int refcnt;
+ char *ptr;
+ mrb_int len;
+} mrb_shared_string;
+
+const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+#define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class))
+
+static struct RString*
+str_new_static(mrb_state *mrb, const char *p, size_t len)
+{
+ struct RString *s;
+
+ if (len >= MRB_INT_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
+ }
+ s = mrb_obj_alloc_string(mrb);
+ s->as.heap.len = (mrb_int)len;
+ s->as.heap.aux.capa = 0; /* nofree */
+ s->as.heap.ptr = (char *)p;
+ s->flags = MRB_STR_NOFREE;
+
+ return s;
+}
+
+static struct RString*
+str_new(mrb_state *mrb, const char *p, size_t len)
+{
+ struct RString *s;
+
+ if (p && mrb_ro_data_p(p)) {
+ return str_new_static(mrb, p, len);
+ }
+ s = mrb_obj_alloc_string(mrb);
+ if (len < RSTRING_EMBED_LEN_MAX) {
+ RSTR_SET_EMBED_FLAG(s);
+ RSTR_SET_EMBED_LEN(s, len);
+ if (p) {
+ memcpy(s->as.ary, p, len);
+ }
+ }
+ else {
+ if (len >= MRB_INT_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
+ }
+ s->as.heap.len = (mrb_int)len;
+ s->as.heap.aux.capa = (mrb_int)len;
+ s->as.heap.ptr = (char *)mrb_malloc(mrb, len+1);
+ if (p) {
+ memcpy(s->as.heap.ptr, p, len);
+ }
+ }
+ RSTR_PTR(s)[len] = '\0';
+ return s;
+}
+
+static inline void
+str_with_class(mrb_state *mrb, struct RString *s, mrb_value obj)
+{
+ s->c = mrb_str_ptr(obj)->c;
+}
+
+static mrb_value
+mrb_str_new_empty(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = str_new(mrb, 0, 0);
+
+ str_with_class(mrb, s, str);
+ return mrb_obj_value(s);
+}
+
+MRB_API mrb_value
+mrb_str_new_capa(mrb_state *mrb, size_t capa)
+{
+ struct RString *s;
+
+ s = mrb_obj_alloc_string(mrb);
+
+ if (capa >= MRB_INT_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string capacity size too big");
+ }
+ s->as.heap.len = 0;
+ s->as.heap.aux.capa = (mrb_int)capa;
+ s->as.heap.ptr = (char *)mrb_malloc(mrb, capa+1);
+ RSTR_PTR(s)[0] = '\0';
+
+ return mrb_obj_value(s);
+}
+
+#ifndef MRB_STR_BUF_MIN_SIZE
+# define MRB_STR_BUF_MIN_SIZE 128
+#endif
+
+MRB_API mrb_value
+mrb_str_buf_new(mrb_state *mrb, size_t capa)
+{
+ if (capa < MRB_STR_BUF_MIN_SIZE) {
+ capa = MRB_STR_BUF_MIN_SIZE;
+ }
+ return mrb_str_new_capa(mrb, capa);
+}
+
+static void
+resize_capa(mrb_state *mrb, struct RString *s, size_t capacity)
+{
+#if SIZE_MAX > MRB_INT_MAX
+ mrb_assert(capacity < MRB_INT_MAX);
+#endif
+ if (RSTR_EMBED_P(s)) {
+ if (RSTRING_EMBED_LEN_MAX < capacity) {
+ char *const tmp = (char *)mrb_malloc(mrb, capacity+1);
+ const mrb_int len = RSTR_EMBED_LEN(s);
+ memcpy(tmp, s->as.ary, len);
+ RSTR_UNSET_EMBED_FLAG(s);
+ s->as.heap.ptr = tmp;
+ s->as.heap.len = len;
+ s->as.heap.aux.capa = (mrb_int)capacity;
+ }
+ }
+ else {
+ s->as.heap.ptr = (char*)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
+ s->as.heap.aux.capa = (mrb_int)capacity;
+ }
+}
+
+MRB_API mrb_value
+mrb_str_new(mrb_state *mrb, const char *p, size_t len)
+{
+ return mrb_obj_value(str_new(mrb, p, len));
+}
+
+/*
+ * call-seq: (Caution! NULL string)
+ * String.new(str="") => new_str
+ *
+ * Returns a new string object containing a copy of <i>str</i>.
+ */
+
+MRB_API mrb_value
+mrb_str_new_cstr(mrb_state *mrb, const char *p)
+{
+ struct RString *s;
+ size_t len;
+
+ if (p) {
+ len = strlen(p);
+ }
+ else {
+ len = 0;
+ }
+
+ s = str_new(mrb, p, len);
+
+ return mrb_obj_value(s);
+}
+
+MRB_API mrb_value
+mrb_str_new_static(mrb_state *mrb, const char *p, size_t len)
+{
+ struct RString *s = str_new_static(mrb, p, len);
+ return mrb_obj_value(s);
+}
+
+static void
+str_decref(mrb_state *mrb, mrb_shared_string *shared)
+{
+ shared->refcnt--;
+ if (shared->refcnt == 0) {
+ if (!shared->nofree) {
+ mrb_free(mrb, shared->ptr);
+ }
+ mrb_free(mrb, shared);
+ }
+}
+
+void
+mrb_gc_free_str(mrb_state *mrb, struct RString *str)
+{
+ if (RSTR_EMBED_P(str))
+ /* no code */;
+ else if (RSTR_SHARED_P(str))
+ str_decref(mrb, str->as.heap.aux.shared);
+ else if (!RSTR_NOFREE_P(str))
+ mrb_free(mrb, str->as.heap.ptr);
+}
+
+#ifdef MRB_UTF8_STRING
+static const char utf8len_codepage[256] =
+{
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,
+};
+
+static mrb_int
+utf8len(const char* p, const char* e)
+{
+ mrb_int len;
+ mrb_int i;
+
+ len = utf8len_codepage[(unsigned char)*p];
+ if (p + len > e) return 1;
+ for (i = 1; i < len; ++i)
+ if ((p[i] & 0xc0) != 0x80)
+ return 1;
+ return len;
+}
+
+static mrb_int
+utf8_strlen(mrb_value str, mrb_int len)
+{
+ mrb_int total = 0;
+ char* p = RSTRING_PTR(str);
+ char* e = p;
+ if (RSTRING(str)->flags & MRB_STR_NO_UTF) {
+ return RSTRING_LEN(str);
+ }
+ e += len < 0 ? RSTRING_LEN(str) : len;
+ while (p<e) {
+ p += utf8len(p, e);
+ total++;
+ }
+ if (RSTRING_LEN(str) == total) {
+ RSTRING(str)->flags |= MRB_STR_NO_UTF;
+ }
+ return total;
+}
+
+#define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1)
+
+/* map character index to byte offset index */
+static mrb_int
+chars2bytes(mrb_value s, mrb_int off, mrb_int idx)
+{
+ mrb_int i, b, n;
+ const char *p = RSTRING_PTR(s) + off;
+ const char *e = RSTRING_END(s);
+
+ for (b=i=0; p<e && i<idx; i++) {
+ n = utf8len(p, e);
+ b += n;
+ p += n;
+ }
+ return b;
+}
+
+/* map byte offset to character index */
+static mrb_int
+bytes2chars(char *p, mrb_int bi)
+{
+ mrb_int i, b, n;
+
+ for (b=i=0; b<bi; i++) {
+ n = utf8len_codepage[(unsigned char)*p];
+ b += n;
+ p += n;
+ }
+ if (b != bi) return -1;
+ return i;
+}
+
+#define BYTES_ALIGN_CHECK(pos) if (pos < 0) return mrb_nil_value();
+#else
+#define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
+#define chars2bytes(p, off, ci) (ci)
+#define bytes2chars(p, bi) (bi)
+#define BYTES_ALIGN_CHECK(pos)
+#endif
+
+static inline mrb_int
+mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
+{
+ const unsigned char *x = xs, *xe = xs + m;
+ const unsigned char *y = ys;
+ int i;
+ ptrdiff_t qstable[256];
+
+ /* Preprocessing */
+ for (i = 0; i < 256; ++i)
+ qstable[i] = m + 1;
+ for (; x < xe; ++x)
+ qstable[*x] = xe - x;
+ /* Searching */
+ for (; y + m <= ys + n; y += *(qstable + y[m])) {
+ if (*xs == *y && memcmp(xs, y, m) == 0)
+ return (mrb_int)(y - ys);
+ }
+ return -1;
+}
+
+static mrb_int
+mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n)
+{
+ const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0;
+
+ if (m > n) return -1;
+ else if (m == n) {
+ return memcmp(x0, y0, m) == 0 ? 0 : -1;
+ }
+ else if (m < 1) {
+ return 0;
+ }
+ else if (m == 1) {
+ const unsigned char *ys = (const unsigned char *)memchr(y, *x, n);
+
+ if (ys)
+ return (mrb_int)(ys - y);
+ else
+ return -1;
+ }
+ return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n);
+}
+
+static void
+str_make_shared(mrb_state *mrb, struct RString *s)
+{
+ if (!RSTR_SHARED_P(s)) {
+ mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string));
+
+ shared->refcnt = 1;
+ if (RSTR_EMBED_P(s)) {
+ const mrb_int len = RSTR_EMBED_LEN(s);
+ char *const tmp = (char *)mrb_malloc(mrb, len+1);
+ memcpy(tmp, s->as.ary, len);
+ tmp[len] = '\0';
+ RSTR_UNSET_EMBED_FLAG(s);
+ s->as.heap.ptr = tmp;
+ s->as.heap.len = len;
+ shared->nofree = FALSE;
+ shared->ptr = s->as.heap.ptr;
+ }
+ else if (RSTR_NOFREE_P(s)) {
+ shared->nofree = TRUE;
+ shared->ptr = s->as.heap.ptr;
+ RSTR_UNSET_NOFREE_FLAG(s);
+ }
+ else {
+ shared->nofree = FALSE;
+ if (s->as.heap.aux.capa > s->as.heap.len) {
+ s->as.heap.ptr = shared->ptr = (char *)mrb_realloc(mrb, s->as.heap.ptr, s->as.heap.len+1);
+ }
+ else {
+ shared->ptr = s->as.heap.ptr;
+ }
+ }
+ shared->len = s->as.heap.len;
+ s->as.heap.aux.shared = shared;
+ RSTR_SET_SHARED_FLAG(s);
+ }
+}
+
+static mrb_value
+byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ struct RString *orig, *s;
+ mrb_shared_string *shared;
+
+ orig = mrb_str_ptr(str);
+ if (RSTR_EMBED_P(orig) || RSTR_LEN(orig) == 0) {
+ s = str_new(mrb, orig->as.ary+beg, len);
+ }
+ else {
+ str_make_shared(mrb, orig);
+ shared = orig->as.heap.aux.shared;
+ s = mrb_obj_alloc_string(mrb);
+ s->as.heap.ptr = orig->as.heap.ptr + beg;
+ s->as.heap.len = len;
+ s->as.heap.aux.shared = shared;
+ RSTR_SET_SHARED_FLAG(s);
+ shared->refcnt++;
+ }
+
+ return mrb_obj_value(s);
+}
+#ifdef MRB_UTF8_STRING
+static inline mrb_value
+str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ beg = chars2bytes(str, 0, beg);
+ len = chars2bytes(str, beg, len);
+
+ return byte_subseq(mrb, str, beg, len);
+}
+#else
+#define str_subseq(mrb, str, beg, len) byte_subseq(mrb, str, beg, len)
+#endif
+
+static mrb_value
+str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ mrb_int clen = RSTRING_CHAR_LEN(str);
+
+ if (len < 0) return mrb_nil_value();
+ if (clen == 0) {
+ len = 0;
+ }
+ else if (beg < 0) {
+ beg = clen + beg;
+ }
+ if (beg > clen) return mrb_nil_value();
+ if (beg < 0) {
+ beg += clen;
+ if (beg < 0) return mrb_nil_value();
+ }
+ if (len > clen - beg)
+ len = clen - beg;
+ if (len <= 0) {
+ len = 0;
+ }
+ return str_subseq(mrb, str, beg, len);
+}
+
+MRB_API mrb_int
+mrb_str_index(mrb_state *mrb, mrb_value str, const char *sptr, mrb_int slen, mrb_int offset)
+{
+ mrb_int pos;
+ char *s;
+ mrb_int len;
+
+ len = RSTRING_LEN(str);
+ if (offset < 0) {
+ offset += len;
+ if (offset < 0) return -1;
+ }
+ if (len - offset < slen) return -1;
+ s = RSTRING_PTR(str);
+ if (offset) {
+ s += offset;
+ }
+ if (slen == 0) return offset;
+ /* need proceed one character at a time */
+ len = RSTRING_LEN(str) - offset;
+ pos = mrb_memsearch(sptr, slen, s, len);
+ if (pos < 0) return pos;
+ return pos + offset;
+}
+
+static mrb_int
+str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset)
+{
+ const char *ptr;
+ mrb_int len;
+
+ ptr = RSTRING_PTR(str2);
+ len = RSTRING_LEN(str2);
+
+ return mrb_str_index(mrb, str, ptr, len, offset);
+}
+
+static void
+check_frozen(mrb_state *mrb, struct RString *s)
+{
+ if (MRB_FROZEN_P(s)) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
+ }
+}
+
+static mrb_value
+str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
+{
+ long len;
+
+ check_frozen(mrb, s1);
+ if (s1 == s2) return mrb_obj_value(s1);
+ s1->flags &= ~MRB_STR_NO_UTF;
+ s1->flags |= s2->flags&MRB_STR_NO_UTF;
+ len = RSTR_LEN(s2);
+ if (RSTR_SHARED_P(s1)) {
+ str_decref(mrb, s1->as.heap.aux.shared);
+ }
+ else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) {
+ mrb_free(mrb, s1->as.heap.ptr);
+ }
+
+ RSTR_UNSET_NOFREE_FLAG(s1);
+
+ if (RSTR_SHARED_P(s2)) {
+L_SHARE:
+ RSTR_UNSET_EMBED_FLAG(s1);
+ s1->as.heap.ptr = s2->as.heap.ptr;
+ s1->as.heap.len = len;
+ s1->as.heap.aux.shared = s2->as.heap.aux.shared;
+ RSTR_SET_SHARED_FLAG(s1);
+ s1->as.heap.aux.shared->refcnt++;
+ }
+ else {
+ if (len <= RSTRING_EMBED_LEN_MAX) {
+ RSTR_UNSET_SHARED_FLAG(s1);
+ RSTR_SET_EMBED_FLAG(s1);
+ memcpy(s1->as.ary, RSTR_PTR(s2), len);
+ RSTR_SET_EMBED_LEN(s1, len);
+ }
+ else {
+ str_make_shared(mrb, s2);
+ goto L_SHARE;
+ }
+ }
+
+ return mrb_obj_value(s1);
+}
+
+static mrb_int
+str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
+{
+ char *s, *sbeg, *t;
+ struct RString *ps = mrb_str_ptr(str);
+ mrb_int len = RSTRING_LEN(sub);
+
+ /* substring longer than string */
+ if (RSTR_LEN(ps) < len) return -1;
+ if (RSTR_LEN(ps) - pos < len) {
+ pos = RSTR_LEN(ps) - len;
+ }
+ sbeg = RSTR_PTR(ps);
+ s = RSTR_PTR(ps) + pos;
+ t = RSTRING_PTR(sub);
+ if (len) {
+ while (sbeg <= s) {
+ if (memcmp(s, t, len) == 0) {
+ return (mrb_int)(s - RSTR_PTR(ps));
+ }
+ s--;
+ }
+ return -1;
+ }
+ else {
+ return pos;
+ }
+}
+
+MRB_API mrb_int
+mrb_str_strlen(mrb_state *mrb, struct RString *s)
+{
+ mrb_int i, max = RSTR_LEN(s);
+ char *p = RSTR_PTR(s);
+
+ if (!p) return 0;
+ for (i=0; i<max; i++) {
+ if (p[i] == '\0') {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
+ }
+ }
+ return max;
+}
+
+#ifdef _WIN32
+#include <windows.h>
+
+char*
+mrb_utf8_from_locale(const char *str, int len)
+{
+ wchar_t* wcsp;
+ char* mbsp;
+ int mbssize, wcssize;
+
+ if (len == 0)
+ return strdup("");
+ if (len == -1)
+ len = (int)strlen(str);
+ wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0);
+ wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
+ if (!wcsp)
+ return NULL;
+ wcssize = MultiByteToWideChar(GetACP(), 0, str, len, wcsp, wcssize + 1);
+ wcsp[wcssize] = 0;
+
+ mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
+ mbsp = (char*) malloc((mbssize + 1));
+ if (!mbsp) {
+ free(wcsp);
+ return NULL;
+ }
+ mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
+ mbsp[mbssize] = 0;
+ free(wcsp);
+ return mbsp;
+}
+
+char*
+mrb_locale_from_utf8(const char *utf8, int len)
+{
+ wchar_t* wcsp;
+ char* mbsp;
+ int mbssize, wcssize;
+
+ if (len == 0)
+ return strdup("");
+ if (len == -1)
+ len = (int)strlen(utf8);
+ wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
+ wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
+ if (!wcsp)
+ return NULL;
+ wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1);
+ wcsp[wcssize] = 0;
+ mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
+ mbsp = (char*) malloc((mbssize + 1));
+ if (!mbsp) {
+ free(wcsp);
+ return NULL;
+ }
+ mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
+ mbsp[mbssize] = 0;
+ free(wcsp);
+ return mbsp;
+}
+#endif
+
+MRB_API void
+mrb_str_modify(mrb_state *mrb, struct RString *s)
+{
+ check_frozen(mrb, s);
+ s->flags &= ~MRB_STR_NO_UTF;
+ if (RSTR_SHARED_P(s)) {
+ mrb_shared_string *shared = s->as.heap.aux.shared;
+
+ if (shared->nofree == 0 && shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
+ s->as.heap.ptr = shared->ptr;
+ s->as.heap.aux.capa = shared->len;
+ RSTR_PTR(s)[s->as.heap.len] = '\0';
+ mrb_free(mrb, shared);
+ }
+ else {
+ char *ptr, *p;
+ mrb_int len;
+
+ p = RSTR_PTR(s);
+ len = s->as.heap.len;
+ if (len < RSTRING_EMBED_LEN_MAX) {
+ RSTR_SET_EMBED_FLAG(s);
+ RSTR_SET_EMBED_LEN(s, len);
+ ptr = RSTR_PTR(s);
+ }
+ else {
+ ptr = (char *)mrb_malloc(mrb, (size_t)len + 1);
+ s->as.heap.ptr = ptr;
+ s->as.heap.aux.capa = len;
+ }
+ if (p) {
+ memcpy(ptr, p, len);
+ }
+ ptr[len] = '\0';
+ str_decref(mrb, shared);
+ }
+ RSTR_UNSET_SHARED_FLAG(s);
+ return;
+ }
+ if (RSTR_NOFREE_P(s)) {
+ char *p = s->as.heap.ptr;
+ mrb_int len = s->as.heap.len;
+
+ RSTR_UNSET_NOFREE_FLAG(s);
+ if (len < RSTRING_EMBED_LEN_MAX) {
+ RSTR_SET_EMBED_FLAG(s);
+ RSTR_SET_EMBED_LEN(s, len);
+ }
+ else {
+ s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)len+1);
+ s->as.heap.aux.capa = len;
+ }
+ if (p) {
+ memcpy(RSTR_PTR(s), p, len);
+ }
+ RSTR_PTR(s)[len] = '\0';
+ return;
+ }
+}
+
+MRB_API mrb_value
+mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
+{
+ mrb_int slen;
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ slen = RSTR_LEN(s);
+ if (len != slen) {
+ if (slen < len || slen - len > 256) {
+ resize_capa(mrb, s, len);
+ }
+ RSTR_SET_LEN(s, len);
+ RSTR_PTR(s)[len] = '\0'; /* sentinel */
+ }
+ return str;
+}
+
+MRB_API char*
+mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
+{
+ struct RString *s;
+
+ if (!mrb_string_p(str0)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "expected String");
+ }
+
+ s = str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0));
+ if ((strlen(RSTR_PTR(s)) ^ RSTR_LEN(s)) != 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
+ }
+ return RSTR_PTR(s);
+}
+
+/*
+ * call-seq: (Caution! String("abcd") change)
+ * String("abcdefg") = String("abcd") + String("efg")
+ *
+ * Returns a new string object containing a copy of <i>str</i>.
+ */
+MRB_API void
+mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
+{
+ if (!mrb_string_p(other)) {
+ other = mrb_str_to_str(mrb, other);
+ }
+ mrb_str_cat_str(mrb, self, other);
+}
+
+/*
+ * call-seq: (Caution! String("abcd") remain)
+ * String("abcdefg") = String("abcd") + String("efg")
+ *
+ * Returns a new string object containing a copy of <i>str</i>.
+ */
+MRB_API mrb_value
+mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ struct RString *s = mrb_str_ptr(a);
+ struct RString *s2 = mrb_str_ptr(b);
+ struct RString *t;
+
+ t = str_new(mrb, 0, RSTR_LEN(s) + RSTR_LEN(s2));
+ memcpy(RSTR_PTR(t), RSTR_PTR(s), RSTR_LEN(s));
+ memcpy(RSTR_PTR(t) + RSTR_LEN(s), RSTR_PTR(s2), RSTR_LEN(s2));
+
+ return mrb_obj_value(t);
+}
+
+/* 15.2.10.5.2 */
+
+/*
+ * call-seq: (Caution! String("abcd") remain) for stack_argument
+ * String("abcdefg") = String("abcd") + String("efg")
+ *
+ * Returns a new string object containing a copy of <i>str</i>.
+ */
+static mrb_value
+mrb_str_plus_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ mrb_get_args(mrb, "S", &str);
+ return mrb_str_plus(mrb, self, str);
+}
+
+/* 15.2.10.5.26 */
+/* 15.2.10.5.33 */
+/*
+ * call-seq:
+ * "abcd".size => int
+ *
+ * Returns the length of string.
+ */
+static mrb_value
+mrb_str_size(mrb_state *mrb, mrb_value self)
+{
+ mrb_int len = RSTRING_CHAR_LEN(self);
+ return mrb_fixnum_value(len);
+}
+
+static mrb_value
+mrb_str_bytesize(mrb_state *mrb, mrb_value self)
+{
+ mrb_int len = RSTRING_LEN(self);
+ return mrb_fixnum_value(len);
+}
+
+/* 15.2.10.5.1 */
+/*
+ * call-seq:
+ * str * integer => new_str
+ *
+ * Copy---Returns a new <code>String</code> containing <i>integer</i> copies of
+ * the receiver.
+ *
+ * "Ho! " * 3 #=> "Ho! Ho! Ho! "
+ */
+static mrb_value
+mrb_str_times(mrb_state *mrb, mrb_value self)
+{
+ mrb_int n,len,times;
+ struct RString *str2;
+ char *p;
+
+ mrb_get_args(mrb, "i", &times);
+ if (times < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
+ }
+ if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
+ }
+
+ len = RSTRING_LEN(self)*times;
+ str2 = str_new(mrb, 0, len);
+ str_with_class(mrb, str2, self);
+ p = RSTR_PTR(str2);
+ if (len > 0) {
+ n = RSTRING_LEN(self);
+ memcpy(p, RSTRING_PTR(self), n);
+ while (n <= len/2) {
+ memcpy(p + n, p, n);
+ n *= 2;
+ }
+ memcpy(p + n, p, len-n);
+ }
+ p[RSTR_LEN(str2)] = '\0';
+
+ return mrb_obj_value(str2);
+}
+/* -------------------------------------------------------------- */
+
+#define lesser(a,b) (((a)>(b))?(b):(a))
+
+/* ---------------------------*/
+/*
+ * call-seq:
+ * mrb_value str1 <=> mrb_value str2 => int
+ * > 1
+ * = 0
+ * < -1
+ */
+MRB_API int
+mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2)
+{
+ mrb_int len;
+ mrb_int retval;
+ struct RString *s1 = mrb_str_ptr(str1);
+ struct RString *s2 = mrb_str_ptr(str2);
+
+ len = lesser(RSTR_LEN(s1), RSTR_LEN(s2));
+ retval = memcmp(RSTR_PTR(s1), RSTR_PTR(s2), len);
+ if (retval == 0) {
+ if (RSTR_LEN(s1) == RSTR_LEN(s2)) return 0;
+ if (RSTR_LEN(s1) > RSTR_LEN(s2)) return 1;
+ return -1;
+ }
+ if (retval > 0) return 1;
+ return -1;
+}
+
+/* 15.2.10.5.3 */
+
+/*
+ * call-seq:
+ * str <=> other_str => -1, 0, +1
+ *
+ * Comparison---Returns -1 if <i>other_str</i> is less than, 0 if
+ * <i>other_str</i> is equal to, and +1 if <i>other_str</i> is greater than
+ * <i>str</i>. If the strings are of different lengths, and the strings are
+ * equal when compared up to the shortest length, then the longer string is
+ * considered greater than the shorter one. If the variable <code>$=</code> is
+ * <code>false</code>, the comparison is based on comparing the binary values
+ * of each character in the string. In older versions of Ruby, setting
+ * <code>$=</code> allowed case-insensitive comparisons; this is now deprecated
+ * in favor of using <code>String#casecmp</code>.
+ *
+ * <code><=></code> is the basis for the methods <code><</code>,
+ * <code><=</code>, <code>></code>, <code>>=</code>, and <code>between?</code>,
+ * included from module <code>Comparable</code>. The method
+ * <code>String#==</code> does not use <code>Comparable#==</code>.
+ *
+ * "abcdef" <=> "abcde" #=> 1
+ * "abcdef" <=> "abcdef" #=> 0
+ * "abcdef" <=> "abcdefg" #=> -1
+ * "abcdef" <=> "ABCDEF" #=> 1
+ */
+static mrb_value
+mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
+{
+ mrb_value str2;
+ mrb_int result;
+
+ mrb_get_args(mrb, "o", &str2);
+ if (!mrb_string_p(str2)) {
+ if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_s"))) {
+ return mrb_nil_value();
+ }
+ else if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "<=>"))) {
+ return mrb_nil_value();
+ }
+ else {
+ mrb_value tmp = mrb_funcall(mrb, str2, "<=>", 1, str1);
+
+ if (!mrb_nil_p(tmp)) return mrb_nil_value();
+ if (!mrb_fixnum_p(tmp)) {
+ return mrb_funcall(mrb, mrb_fixnum_value(0), "-", 1, tmp);
+ }
+ result = -mrb_fixnum(tmp);
+ }
+ }
+ else {
+ result = mrb_str_cmp(mrb, str1, str2);
+ }
+ return mrb_fixnum_value(result);
+}
+
+static mrb_bool
+str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
+{
+ const mrb_int len = RSTRING_LEN(str1);
+
+ if (len != RSTRING_LEN(str2)) return FALSE;
+ if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), (size_t)len) == 0)
+ return TRUE;
+ return FALSE;
+}
+
+MRB_API mrb_bool
+mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
+{
+ if (mrb_immediate_p(str2)) return FALSE;
+ if (!mrb_string_p(str2)) {
+ if (mrb_nil_p(str2)) return FALSE;
+ if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) {
+ return FALSE;
+ }
+ str2 = mrb_funcall(mrb, str2, "to_str", 0);
+ return mrb_equal(mrb, str2, str1);
+ }
+ return str_eql(mrb, str1, str2);
+}
+
+/* 15.2.10.5.4 */
+/*
+ * call-seq:
+ * str == obj => true or false
+ *
+ * Equality---
+ * If <i>obj</i> is not a <code>String</code>, returns <code>false</code>.
+ * Otherwise, returns <code>false</code> or <code>true</code>
+ *
+ * caution:if <i>str</i> <code><=></code> <i>obj</i> returns zero.
+ */
+static mrb_value
+mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
+{
+ mrb_value str2;
+
+ mrb_get_args(mrb, "o", &str2);
+
+ return mrb_bool_value(mrb_str_equal(mrb, str1, str2));
+}
+/* ---------------------------------- */
+MRB_API mrb_value
+mrb_str_to_str(mrb_state *mrb, mrb_value str)
+{
+ mrb_value s;
+
+ if (!mrb_string_p(str)) {
+ s = mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
+ if (mrb_nil_p(s)) {
+ s = mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_s");
+ }
+ return s;
+ }
+ return str;
+}
+
+MRB_API const char*
+mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr)
+{
+ mrb_value str = mrb_str_to_str(mrb, ptr);
+ return RSTRING_PTR(str);
+}
+
+MRB_API mrb_int
+mrb_string_value_len(mrb_state *mrb, mrb_value ptr)
+{
+ mrb_value str = mrb_str_to_str(mrb, ptr);
+ return RSTRING_LEN(str);
+}
+
+void
+mrb_noregexp(mrb_state *mrb, mrb_value self)
+{
+ mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented");
+}
+
+void
+mrb_regexp_check(mrb_state *mrb, mrb_value obj)
+{
+ if (mrb_regexp_p(mrb, obj)) {
+ mrb_noregexp(mrb, obj);
+ }
+}
+
+MRB_API mrb_value
+mrb_str_dup(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+ struct RString *dup = str_new(mrb, 0, 0);
+
+ str_with_class(mrb, dup, str);
+ return str_replace(mrb, dup, s);
+}
+
+static mrb_value
+mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx)
+{
+ mrb_int idx;
+
+ mrb_regexp_check(mrb, indx);
+ switch (mrb_type(indx)) {
+ case MRB_TT_FIXNUM:
+ idx = mrb_fixnum(indx);
+
+num_index:
+ str = str_substr(mrb, str, idx, 1);
+ if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value();
+ return str;
+
+ case MRB_TT_STRING:
+ if (str_index_str(mrb, str, indx, 0) != -1)
+ return mrb_str_dup(mrb, indx);
+ return mrb_nil_value();
+
+ case MRB_TT_RANGE:
+ goto range_arg;
+
+ default:
+ indx = mrb_Integer(mrb, indx);
+ if (mrb_nil_p(indx)) {
+ range_arg:
+ {
+ mrb_int beg, len;
+
+ len = RSTRING_CHAR_LEN(str);
+ switch (mrb_range_beg_len(mrb, indx, &beg, &len, len, TRUE)) {
+ case 1:
+ return str_subseq(mrb, str, beg, len);
+ case 2:
+ return mrb_nil_value();
+ default:
+ break;
+ }
+ }
+ mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Fixnum");
+ }
+ idx = mrb_fixnum(indx);
+ goto num_index;
+ }
+ return mrb_nil_value(); /* not reached */
+}
+
+/* 15.2.10.5.6 */
+/* 15.2.10.5.34 */
+/*
+ * call-seq:
+ * str[fixnum] => fixnum or nil
+ * str[fixnum, fixnum] => new_str or nil
+ * str[range] => new_str or nil
+ * str[regexp] => new_str or nil
+ * str[regexp, fixnum] => new_str or nil
+ * str[other_str] => new_str or nil
+ * str.slice(fixnum) => fixnum or nil
+ * str.slice(fixnum, fixnum) => new_str or nil
+ * str.slice(range) => new_str or nil
+ * str.slice(other_str) => new_str or nil
+ *
+ * Element Reference---If passed a single <code>Fixnum</code>, returns the code
+ * of the character at that position. If passed two <code>Fixnum</code>
+ * objects, returns a substring starting at the offset given by the first, and
+ * a length given by the second. If given a range, a substring containing
+ * characters at offsets given by the range is returned. In all three cases, if
+ * an offset is negative, it is counted from the end of <i>str</i>. Returns
+ * <code>nil</code> if the initial offset falls outside the string, the length
+ * is negative, or the beginning of the range is greater than the end.
+ *
+ * If a <code>String</code> is given, that string is returned if it occurs in
+ * <i>str</i>. In both cases, <code>nil</code> is returned if there is no
+ * match.
+ *
+ * a = "hello there"
+ * a[1] #=> 101(1.8.7) "e"(1.9.2)
+ * a[1.1] #=> "e"(1.9.2)
+ * a[1,3] #=> "ell"
+ * a[1..3] #=> "ell"
+ * a[-3,2] #=> "er"
+ * a[-4..-2] #=> "her"
+ * a[12..-1] #=> nil
+ * a[-2..-4] #=> ""
+ * a["lo"] #=> "lo"
+ * a["bye"] #=> nil
+ */
+static mrb_value
+mrb_str_aref_m(mrb_state *mrb, mrb_value str)
+{
+ mrb_value a1, a2;
+ int argc;
+
+ argc = mrb_get_args(mrb, "o|o", &a1, &a2);
+ if (argc == 2) {
+ mrb_int n1, n2;
+
+ mrb_regexp_check(mrb, a1);
+ mrb_get_args(mrb, "ii", &n1, &n2);
+ return str_substr(mrb, str, n1, n2);
+ }
+ if (argc != 1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc));
+ }
+ return mrb_str_aref(mrb, str, a1);
+}
+
+/* 15.2.10.5.8 */
+/*
+ * call-seq:
+ * str.capitalize! => str or nil
+ *
+ * Modifies <i>str</i> by converting the first character to uppercase and the
+ * remainder to lowercase. Returns <code>nil</code> if no changes are made.
+ *
+ * a = "hello"
+ * a.capitalize! #=> "Hello"
+ * a #=> "Hello"
+ * a.capitalize! #=> nil
+ */
+static mrb_value
+mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
+{
+ char *p, *pend;
+ mrb_bool modify = FALSE;
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ if (RSTR_LEN(s) == 0 || !RSTR_PTR(s)) return mrb_nil_value();
+ p = RSTR_PTR(s); pend = RSTR_PTR(s) + RSTR_LEN(s);
+ if (ISLOWER(*p)) {
+ *p = TOUPPER(*p);
+ modify = TRUE;
+ }
+ while (++p < pend) {
+ if (ISUPPER(*p)) {
+ *p = TOLOWER(*p);
+ modify = TRUE;
+ }
+ }
+ if (modify) return str;
+ return mrb_nil_value();
+}
+
+/* 15.2.10.5.7 */
+/*
+ * call-seq:
+ * str.capitalize => new_str
+ *
+ * Returns a copy of <i>str</i> with the first character converted to uppercase
+ * and the remainder to lowercase.
+ *
+ * "hello".capitalize #=> "Hello"
+ * "HELLO".capitalize #=> "Hello"
+ * "123ABC".capitalize #=> "123abc"
+ */
+static mrb_value
+mrb_str_capitalize(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_capitalize_bang(mrb, str);
+ return str;
+}
+
+/* 15.2.10.5.10 */
+/*
+ * call-seq:
+ * str.chomp!(separator="\n") => str or nil
+ *
+ * Modifies <i>str</i> in place as described for <code>String#chomp</code>,
+ * returning <i>str</i>, or <code>nil</code> if no modifications were made.
+ */
+static mrb_value
+mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
+{
+ mrb_value rs;
+ mrb_int newline;
+ char *p, *pp;
+ mrb_int rslen;
+ mrb_int len;
+ mrb_int argc;
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ argc = mrb_get_args(mrb, "|S", &rs);
+ len = RSTR_LEN(s);
+ if (argc == 0) {
+ if (len == 0) return mrb_nil_value();
+ smart_chomp:
+ if (RSTR_PTR(s)[len-1] == '\n') {
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
+ if (RSTR_LEN(s) > 0 &&
+ RSTR_PTR(s)[RSTR_LEN(s)-1] == '\r') {
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
+ }
+ }
+ else if (RSTR_PTR(s)[len-1] == '\r') {
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
+ }
+ else {
+ return mrb_nil_value();
+ }
+ RSTR_PTR(s)[RSTR_LEN(s)] = '\0';
+ return str;
+ }
+
+ if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value();
+ p = RSTR_PTR(s);
+ rslen = RSTRING_LEN(rs);
+ if (rslen == 0) {
+ while (len>0 && p[len-1] == '\n') {
+ len--;
+ if (len>0 && p[len-1] == '\r')
+ len--;
+ }
+ if (len < RSTR_LEN(s)) {
+ RSTR_SET_LEN(s, len);
+ p[len] = '\0';
+ return str;
+ }
+ return mrb_nil_value();
+ }
+ if (rslen > len) return mrb_nil_value();
+ newline = RSTRING_PTR(rs)[rslen-1];
+ if (rslen == 1 && newline == '\n')
+ newline = RSTRING_PTR(rs)[rslen-1];
+ if (rslen == 1 && newline == '\n')
+ goto smart_chomp;
+
+ pp = p + len - rslen;
+ if (p[len-1] == newline &&
+ (rslen <= 1 ||
+ memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
+ RSTR_SET_LEN(s, len - rslen);
+ p[RSTR_LEN(s)] = '\0';
+ return str;
+ }
+ return mrb_nil_value();
+}
+
+/* 15.2.10.5.9 */
+/*
+ * call-seq:
+ * str.chomp(separator="\n") => new_str
+ *
+ * Returns a new <code>String</code> with the given record separator removed
+ * from the end of <i>str</i> (if present). If <code>$/</code> has not been
+ * changed from the default Ruby record separator, then <code>chomp</code> also
+ * removes carriage return characters (that is it will remove <code>\n</code>,
+ * <code>\r</code>, and <code>\r\n</code>).
+ *
+ * "hello".chomp #=> "hello"
+ * "hello\n".chomp #=> "hello"
+ * "hello\r\n".chomp #=> "hello"
+ * "hello\n\r".chomp #=> "hello\n"
+ * "hello\r".chomp #=> "hello"
+ * "hello \n there".chomp #=> "hello \n there"
+ * "hello".chomp("llo") #=> "he"
+ */
+static mrb_value
+mrb_str_chomp(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_chomp_bang(mrb, str);
+ return str;
+}
+
+/* 15.2.10.5.12 */
+/*
+ * call-seq:
+ * str.chop! => str or nil
+ *
+ * Processes <i>str</i> as for <code>String#chop</code>, returning <i>str</i>,
+ * or <code>nil</code> if <i>str</i> is the empty string. See also
+ * <code>String#chomp!</code>.
+ */
+static mrb_value
+mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ if (RSTR_LEN(s) > 0) {
+ mrb_int len;
+#ifdef MRB_UTF8_STRING
+ const char* t = RSTR_PTR(s), *p = t;
+ const char* e = p + RSTR_LEN(s);
+ while (p<e) {
+ mrb_int clen = utf8len(p, e);
+ if (p + clen>=e) break;
+ p += clen;
+ }
+ len = p - t;
+#else
+ len = RSTR_LEN(s) - 1;
+#endif
+ if (RSTR_PTR(s)[len] == '\n') {
+ if (len > 0 &&
+ RSTR_PTR(s)[len-1] == '\r') {
+ len--;
+ }
+ }
+ RSTR_SET_LEN(s, len);
+ RSTR_PTR(s)[len] = '\0';
+ return str;
+ }
+ return mrb_nil_value();
+}
+
+/* 15.2.10.5.11 */
+/*
+ * call-seq:
+ * str.chop => new_str
+ *
+ * Returns a new <code>String</code> with the last character removed. If the
+ * string ends with <code>\r\n</code>, both characters are removed. Applying
+ * <code>chop</code> to an empty string returns an empty
+ * string. <code>String#chomp</code> is often a safer alternative, as it leaves
+ * the string unchanged if it doesn't end in a record separator.
+ *
+ * "string\r\n".chop #=> "string"
+ * "string\n\r".chop #=> "string\n"
+ * "string\n".chop #=> "string"
+ * "string".chop #=> "strin"
+ * "x".chop #=> ""
+ */
+static mrb_value
+mrb_str_chop(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+ str = mrb_str_dup(mrb, self);
+ mrb_str_chop_bang(mrb, str);
+ return str;
+}
+
+/* 15.2.10.5.14 */
+/*
+ * call-seq:
+ * str.downcase! => str or nil
+ *
+ * Downcases the contents of <i>str</i>, returning <code>nil</code> if no
+ * changes were made.
+ */
+static mrb_value
+mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
+{
+ char *p, *pend;
+ mrb_bool modify = FALSE;
+ struct RString *s = mrb_str_ptr(str);
+
+ mrb_str_modify(mrb, s);
+ p = RSTR_PTR(s);
+ pend = RSTR_PTR(s) + RSTR_LEN(s);
+ while (p < pend) {
+ if (ISUPPER(*p)) {
+ *p = TOLOWER(*p);
+ modify = TRUE;
+ }
+ p++;
+ }
+
+ if (modify) return str;
+ return mrb_nil_value();
+}
+
+/* 15.2.10.5.13 */
+/*
+ * call-seq:
+ * str.downcase => new_str
+ *
+ * Returns a copy of <i>str</i> with all uppercase letters replaced with their
+ * lowercase counterparts. The operation is locale insensitive---only
+ * characters 'A' to 'Z' are affected.
+ *
+ * "hEllO".downcase #=> "hello"
+ */
+static mrb_value
+mrb_str_downcase(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_downcase_bang(mrb, str);
+ return str;
+}
+
+/* 15.2.10.5.16 */
+/*
+ * call-seq:
+ * str.empty? => true or false
+ *
+ * Returns <code>true</code> if <i>str</i> has a length of zero.
+ *
+ * "hello".empty? #=> false
+ * "".empty? #=> true
+ */
+static mrb_value
+mrb_str_empty_p(mrb_state *mrb, mrb_value self)
+{
+ struct RString *s = mrb_str_ptr(self);
+
+ return mrb_bool_value(RSTR_LEN(s) == 0);
+}
+
+/* 15.2.10.5.17 */
+/*
+ * call-seq:
+ * str.eql?(other) => true or false
+ *
+ * Two strings are equal if the have the same length and content.
+ */
+static mrb_value
+mrb_str_eql(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str2;
+ mrb_bool eql_p;
+
+ mrb_get_args(mrb, "o", &str2);
+ eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2);
+
+ return mrb_bool_value(eql_p);
+}
+
+MRB_API mrb_value
+mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
+{
+ return str_substr(mrb, str, beg, len);
+}
+
+mrb_int
+mrb_str_hash(mrb_state *mrb, mrb_value str)
+{
+ /* 1-8-7 */
+ struct RString *s = mrb_str_ptr(str);
+ mrb_int len = RSTR_LEN(s);
+ char *p = RSTR_PTR(s);
+ uint64_t key = 0;
+
+ while (len--) {
+ key = key*65599 + *p;
+ p++;
+ }
+ return (mrb_int)(key + (key>>5));
+}
+
+/* 15.2.10.5.20 */
+/*
+ * call-seq:
+ * str.hash => fixnum
+ *
+ * Return a hash based on the string's length and content.
+ */
+static mrb_value
+mrb_str_hash_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_int key = mrb_str_hash(mrb, self);
+ return mrb_fixnum_value(key);
+}
+
+/* 15.2.10.5.21 */
+/*
+ * call-seq:
+ * str.include? other_str => true or false
+ * str.include? fixnum => true or false
+ *
+ * Returns <code>true</code> if <i>str</i> contains the given string or
+ * character.
+ *
+ * "hello".include? "lo" #=> true
+ * "hello".include? "ol" #=> false
+ * "hello".include? ?h #=> true
+ */
+static mrb_value
+mrb_str_include(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str2;
+
+ mrb_get_args(mrb, "S", &str2);
+ if (str_index_str(mrb, self, str2, 0) < 0)
+ return mrb_bool_value(FALSE);
+ return mrb_bool_value(TRUE);
+}
+
+/* 15.2.10.5.22 */
+/*
+ * call-seq:
+ * str.index(substring [, offset]) => fixnum or nil
+ * str.index(fixnum [, offset]) => fixnum or nil
+ * str.index(regexp [, offset]) => fixnum or nil
+ *
+ * Returns the index of the first occurrence of the given
+ * <i>substring</i>,
+ * character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>.
+ * Returns
+ * <code>nil</code> if not found.
+ * If the second parameter is present, it
+ * specifies the position in the string to begin the search.
+ *
+ * "hello".index('e') #=> 1
+ * "hello".index('lo') #=> 3
+ * "hello".index('a') #=> nil
+ * "hello".index(101) #=> 1(101=0x65='e')
+ * "hello".index(/[aeiou]/, -3) #=> 4
+ */
+static mrb_value
+mrb_str_index_m(mrb_state *mrb, mrb_value str)
+{
+ mrb_value *argv;
+ mrb_int argc;
+ mrb_value sub;
+ mrb_int pos, clen;
+
+ mrb_get_args(mrb, "*!", &argv, &argc);
+ if (argc == 2) {
+ mrb_get_args(mrb, "oi", &sub, &pos);
+ }
+ else {
+ pos = 0;
+ if (argc > 0)
+ sub = argv[0];
+ else
+ sub = mrb_nil_value();
+ }
+ mrb_regexp_check(mrb, sub);
+ clen = RSTRING_CHAR_LEN(str);
+ if (pos < 0) {
+ pos += clen;
+ if (pos < 0) {
+ return mrb_nil_value();
+ }
+ }
+ if (pos > clen) return mrb_nil_value();
+ pos = chars2bytes(str, 0, pos);
+
+ switch (mrb_type(sub)) {
+ default: {
+ mrb_value tmp;
+
+ tmp = mrb_check_string_type(mrb, sub);
+ if (mrb_nil_p(tmp)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
+ }
+ sub = tmp;
+ }
+ /* fall through */
+ case MRB_TT_STRING:
+ pos = str_index_str(mrb, str, sub, pos);
+ break;
+ }
+
+ if (pos == -1) return mrb_nil_value();
+ pos = bytes2chars(RSTRING_PTR(str), pos);
+ BYTES_ALIGN_CHECK(pos);
+ return mrb_fixnum_value(pos);
+}
+
+#define STR_REPLACE_SHARED_MIN 10
+
+/* 15.2.10.5.24 */
+/* 15.2.10.5.28 */
+/*
+ * call-seq:
+ * str.replace(other_str) => str
+ *
+ * s = "hello" #=> "hello"
+ * s.replace "world" #=> "world"
+ */
+static mrb_value
+mrb_str_replace(mrb_state *mrb, mrb_value str)
+{
+ mrb_value str2;
+
+ mrb_get_args(mrb, "S", &str2);
+ return str_replace(mrb, mrb_str_ptr(str), mrb_str_ptr(str2));
+}
+
+/* 15.2.10.5.23 */
+/*
+ * call-seq:
+ * String.new(str="") => new_str
+ *
+ * Returns a new string object containing a copy of <i>str</i>.
+ */
+static mrb_value
+mrb_str_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str2;
+
+ if (mrb_get_args(mrb, "|S", &str2) == 0) {
+ struct RString *s = str_new(mrb, 0, 0);
+ str2 = mrb_obj_value(s);
+ }
+ str_replace(mrb, mrb_str_ptr(self), mrb_str_ptr(str2));
+ return self;
+}
+
+/* 15.2.10.5.25 */
+/* 15.2.10.5.41 */
+/*
+ * call-seq:
+ * str.intern => symbol
+ * str.to_sym => symbol
+ *
+ * Returns the <code>Symbol</code> corresponding to <i>str</i>, creating the
+ * symbol if it did not previously exist. See <code>Symbol#id2name</code>.
+ *
+ * "Koala".intern #=> :Koala
+ * s = 'cat'.to_sym #=> :cat
+ * s == :cat #=> true
+ * s = '@cat'.to_sym #=> :@cat
+ * s == :@cat #=> true
+ *
+ * This can also be used to create symbols that cannot be represented using the
+ * <code>:xxx</code> notation.
+ *
+ * 'cat and dog'.to_sym #=> :"cat and dog"
+ */
+MRB_API mrb_value
+mrb_str_intern(mrb_state *mrb, mrb_value self)
+{
+ return mrb_symbol_value(mrb_intern_str(mrb, self));
+}
+/* ---------------------------------- */
+MRB_API mrb_value
+mrb_obj_as_string(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value str;
+
+ if (mrb_string_p(obj)) {
+ return obj;
+ }
+ str = mrb_funcall(mrb, obj, "to_s", 0);
+ if (!mrb_string_p(str))
+ return mrb_any_to_s(mrb, obj);
+ return str;
+}
+
+MRB_API mrb_value
+mrb_ptr_to_str(mrb_state *mrb, void *p)
+{
+ struct RString *p_str;
+ char *p1;
+ char *p2;
+ uintptr_t n = (uintptr_t)p;
+
+ p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4);
+ p1 = RSTR_PTR(p_str);
+ *p1++ = '0';
+ *p1++ = 'x';
+ p2 = p1;
+
+ do {
+ *p2++ = mrb_digitmap[n % 16];
+ n /= 16;
+ } while (n > 0);
+ *p2 = '\0';
+ RSTR_SET_LEN(p_str, (mrb_int)(p2 - RSTR_PTR(p_str)));
+
+ while (p1 < p2) {
+ const char c = *p1;
+ *p1++ = *--p2;
+ *p2 = c;
+ }
+
+ return mrb_obj_value(p_str);
+}
+
+MRB_API mrb_value
+mrb_string_type(mrb_state *mrb, mrb_value str)
+{
+ return mrb_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
+}
+
+MRB_API mrb_value
+mrb_check_string_type(mrb_state *mrb, mrb_value str)
+{
+ return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str");
+}
+
+/* 15.2.10.5.30 */
+/*
+ * call-seq:
+ * str.reverse! => str
+ *
+ * Reverses <i>str</i> in place.
+ */
+static mrb_value
+mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
+{
+#ifdef MRB_UTF8_STRING
+ mrb_int utf8_len = RSTRING_CHAR_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
+
+ if (utf8_len == len) goto bytes;
+ if (utf8_len > 1) {
+ char *buf;
+ char *p, *e, *r;
+
+ mrb_str_modify(mrb, mrb_str_ptr(str));
+ len = RSTRING_LEN(str);
+ buf = (char*)mrb_malloc(mrb, (size_t)len);
+ p = buf;
+ e = buf + len;
+
+ memcpy(buf, RSTRING_PTR(str), len);
+ r = RSTRING_PTR(str) + len;
+
+ while (p<e) {
+ mrb_int clen = utf8len(p, e);
+ r -= clen;
+ memcpy(r, p, clen);
+ p += clen;
+ }
+ mrb_free(mrb, buf);
+ }
+ return str;
+
+ bytes:
+#endif
+ {
+ struct RString *s = mrb_str_ptr(str);
+ char *p, *e;
+ char c;
+
+ mrb_str_modify(mrb, s);
+ if (RSTR_LEN(s) > 1) {
+ p = RSTR_PTR(s);
+ e = p + RSTR_LEN(s) - 1;
+ while (p < e) {
+ c = *p;
+ *p++ = *e;
+ *e-- = c;
+ }
+ }
+ return str;
+ }
+}
+
+/* ---------------------------------- */
+/* 15.2.10.5.29 */
+/*
+ * call-seq:
+ * str.reverse => new_str
+ *
+ * Returns a new string with the characters from <i>str</i> in reverse order.
+ *
+ * "stressed".reverse #=> "desserts"
+ */
+static mrb_value
+mrb_str_reverse(mrb_state *mrb, mrb_value str)
+{
+ mrb_value str2 = mrb_str_dup(mrb, str);
+ mrb_str_reverse_bang(mrb, str2);
+ return str2;
+}
+
+/* 15.2.10.5.31 */
+/*
+ * call-seq:
+ * str.rindex(substring [, fixnum]) => fixnum or nil
+ * str.rindex(fixnum [, fixnum]) => fixnum or nil
+ * str.rindex(regexp [, fixnum]) => fixnum or nil
+ *
+ * Returns the index of the last occurrence of the given <i>substring</i>,
+ * character (<i>fixnum</i>), or pattern (<i>regexp</i>) in <i>str</i>. Returns
+ * <code>nil</code> if not found. If the second parameter is present, it
+ * specifies the position in the string to end the search---characters beyond
+ * this point will not be considered.
+ *
+ * "hello".rindex('e') #=> 1
+ * "hello".rindex('l') #=> 3
+ * "hello".rindex('a') #=> nil
+ * "hello".rindex(101) #=> 1
+ * "hello".rindex(/[aeiou]/, -2) #=> 1
+ */
+static mrb_value
+mrb_str_rindex(mrb_state *mrb, mrb_value str)
+{
+ mrb_value *argv;
+ mrb_int argc;
+ mrb_value sub;
+ mrb_int pos, len = RSTRING_CHAR_LEN(str);
+
+ mrb_get_args(mrb, "*!", &argv, &argc);
+ if (argc == 2) {
+ mrb_get_args(mrb, "oi", &sub, &pos);
+ if (pos < 0) {
+ pos += len;
+ if (pos < 0) {
+ mrb_regexp_check(mrb, sub);
+ return mrb_nil_value();
+ }
+ }
+ if (pos > len) pos = len;
+ }
+ else {
+ pos = len;
+ if (argc > 0)
+ sub = argv[0];
+ else
+ sub = mrb_nil_value();
+ }
+ pos = chars2bytes(str, 0, pos);
+ mrb_regexp_check(mrb, sub);
+
+ switch (mrb_type(sub)) {
+ default: {
+ mrb_value tmp;
+
+ tmp = mrb_check_string_type(mrb, sub);
+ if (mrb_nil_p(tmp)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub);
+ }
+ sub = tmp;
+ }
+ /* fall through */
+ case MRB_TT_STRING:
+ pos = str_rindex(mrb, str, sub, pos);
+ if (pos >= 0) {
+ pos = bytes2chars(RSTRING_PTR(str), pos);
+ BYTES_ALIGN_CHECK(pos);
+ return mrb_fixnum_value(pos);
+ }
+ break;
+
+ } /* end of switch (TYPE(sub)) */
+ return mrb_nil_value();
+}
+
+/* 15.2.10.5.35 */
+
+/*
+ * call-seq:
+ * str.split(pattern="\n", [limit]) => anArray
+ *
+ * Divides <i>str</i> into substrings based on a delimiter, returning an array
+ * of these substrings.
+ *
+ * If <i>pattern</i> is a <code>String</code>, then its contents are used as
+ * the delimiter when splitting <i>str</i>. If <i>pattern</i> is a single
+ * space, <i>str</i> is split on whitespace, with leading whitespace and runs
+ * of contiguous whitespace characters ignored.
+ *
+ * If <i>pattern</i> is a <code>Regexp</code>, <i>str</i> is divided where the
+ * pattern matches. Whenever the pattern matches a zero-length string,
+ * <i>str</i> is split into individual characters.
+ *
+ * If <i>pattern</i> is omitted, the value of <code>$;</code> is used. If
+ * <code>$;</code> is <code>nil</code> (which is the default), <i>str</i> is
+ * split on whitespace as if ' ' were specified.
+ *
+ * If the <i>limit</i> parameter is omitted, trailing null fields are
+ * suppressed. If <i>limit</i> is a positive number, at most that number of
+ * fields will be returned (if <i>limit</i> is <code>1</code>, the entire
+ * string is returned as the only entry in an array). If negative, there is no
+ * limit to the number of fields returned, and trailing null fields are not
+ * suppressed.
+ *
+ * " now's the time".split #=> ["now's", "the", "time"]
+ * " now's the time".split(' ') #=> ["now's", "the", "time"]
+ * " now's the time".split(/ /) #=> ["", "now's", "", "the", "time"]
+ * "hello".split(//) #=> ["h", "e", "l", "l", "o"]
+ * "hello".split(//, 3) #=> ["h", "e", "llo"]
+ *
+ * "mellow yellow".split("ello") #=> ["m", "w y", "w"]
+ * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"]
+ * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"]
+ * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""]
+ */
+
+static mrb_value
+mrb_str_split_m(mrb_state *mrb, mrb_value str)
+{
+ int argc;
+ mrb_value spat = mrb_nil_value();
+ enum {awk, string, regexp} split_type = string;
+ mrb_int i = 0;
+ mrb_int beg;
+ mrb_int end;
+ mrb_int lim = 0;
+ mrb_bool lim_p;
+ mrb_value result, tmp;
+
+ argc = mrb_get_args(mrb, "|oi", &spat, &lim);
+ lim_p = (lim > 0 && argc == 2);
+ if (argc == 2) {
+ if (lim == 1) {
+ if (RSTRING_LEN(str) == 0)
+ return mrb_ary_new_capa(mrb, 0);
+ return mrb_ary_new_from_values(mrb, 1, &str);
+ }
+ i = 1;
+ }
+
+ if (argc == 0 || mrb_nil_p(spat)) {
+ split_type = awk;
+ }
+ else {
+ if (mrb_string_p(spat)) {
+ split_type = string;
+ if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
+ split_type = awk;
+ }
+ }
+ else {
+ mrb_noregexp(mrb, str);
+ }
+ }
+
+ result = mrb_ary_new(mrb);
+ beg = 0;
+ if (split_type == awk) {
+ mrb_bool skip = TRUE;
+ mrb_int idx = 0;
+ mrb_int str_len = RSTRING_LEN(str);
+ unsigned int c;
+ int ai = mrb_gc_arena_save(mrb);
+
+ idx = end = beg;
+ while (idx < str_len) {
+ c = (unsigned char)RSTRING_PTR(str)[idx++];
+ if (skip) {
+ if (ISSPACE(c)) {
+ beg = idx;
+ }
+ else {
+ end = idx;
+ skip = FALSE;
+ if (lim_p && lim <= i) break;
+ }
+ }
+ else if (ISSPACE(c)) {
+ mrb_ary_push(mrb, result, byte_subseq(mrb, str, beg, end-beg));
+ mrb_gc_arena_restore(mrb, ai);
+ skip = TRUE;
+ beg = idx;
+ if (lim_p) ++i;
+ }
+ else {
+ end = idx;
+ }
+ }
+ }
+ else if (split_type == string) {
+ mrb_int str_len = RSTRING_LEN(str);
+ mrb_int pat_len = RSTRING_LEN(spat);
+ mrb_int idx = 0;
+ int ai = mrb_gc_arena_save(mrb);
+
+ while (idx < str_len) {
+ if (pat_len > 0) {
+ end = mrb_memsearch(RSTRING_PTR(spat), pat_len, RSTRING_PTR(str)+idx, str_len - idx);
+ if (end < 0) break;
+ }
+ else {
+ end = chars2bytes(str, idx, 1);
+ }
+ mrb_ary_push(mrb, result, byte_subseq(mrb, str, idx, end));
+ mrb_gc_arena_restore(mrb, ai);
+ idx += end + pat_len;
+ if (lim_p && lim <= ++i) break;
+ }
+ beg = idx;
+ }
+ else {
+ mrb_noregexp(mrb, str);
+ }
+ if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) {
+ if (RSTRING_LEN(str) == beg) {
+ tmp = mrb_str_new_empty(mrb, str);
+ }
+ else {
+ tmp = byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
+ }
+ mrb_ary_push(mrb, result, tmp);
+ }
+ if (!lim_p && lim == 0) {
+ mrb_int len;
+ while ((len = RARRAY_LEN(result)) > 0 &&
+ (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
+ mrb_ary_pop(mrb, result);
+ }
+
+ return result;
+}
+
+MRB_API mrb_value
+mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, int base, int badcheck)
+{
+ const char *p = str;
+ const char *pend = str + len;
+ char sign = 1;
+ int c;
+ uint64_t n = 0;
+ mrb_int val;
+
+#define conv_digit(c) \
+ (ISDIGIT(c) ? ((c) - '0') : \
+ ISLOWER(c) ? ((c) - 'a' + 10) : \
+ ISUPPER(c) ? ((c) - 'A' + 10) : \
+ -1)
+
+ if (!p) {
+ if (badcheck) goto bad;
+ return mrb_fixnum_value(0);
+ }
+ while (p<pend && ISSPACE(*p))
+ p++;
+
+ if (p[0] == '+') {
+ p++;
+ }
+ else if (p[0] == '-') {
+ p++;
+ sign = 0;
+ }
+ if (base <= 0) {
+ if (p[0] == '0') {
+ switch (p[1]) {
+ case 'x': case 'X':
+ base = 16;
+ break;
+ case 'b': case 'B':
+ base = 2;
+ break;
+ case 'o': case 'O':
+ base = 8;
+ break;
+ case 'd': case 'D':
+ base = 10;
+ break;
+ default:
+ base = 8;
+ break;
+ }
+ }
+ else if (base < -1) {
+ base = -base;
+ }
+ else {
+ base = 10;
+ }
+ }
+ switch (base) {
+ case 2:
+ if (p[0] == '0' && (p[1] == 'b'||p[1] == 'B')) {
+ p += 2;
+ }
+ break;
+ case 3:
+ break;
+ case 8:
+ if (p[0] == '0' && (p[1] == 'o'||p[1] == 'O')) {
+ p += 2;
+ }
+ case 4: case 5: case 6: case 7:
+ break;
+ case 10:
+ if (p[0] == '0' && (p[1] == 'd'||p[1] == 'D')) {
+ p += 2;
+ }
+ case 9: case 11: case 12: case 13: case 14: case 15:
+ break;
+ case 16:
+ if (p[0] == '0' && (p[1] == 'x'||p[1] == 'X')) {
+ p += 2;
+ }
+ break;
+ default:
+ if (base < 2 || 36 < base) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
+ }
+ break;
+ } /* end of switch (base) { */
+ if (p>=pend) {
+ if (badcheck) goto bad;
+ return mrb_fixnum_value(0);
+ }
+ if (*p == '0') { /* squeeze preceding 0s */
+ p++;
+ while (p<pend) {
+ c = *p++;
+ if (c == '_') {
+ if (p<pend && *p == '_') {
+ if (badcheck) goto bad;
+ break;
+ }
+ continue;
+ }
+ if (c != '0') {
+ p--;
+ break;
+ }
+ }
+ if (*(p - 1) == '0')
+ p--;
+ }
+ if (p == pend) {
+ if (badcheck) goto bad;
+ return mrb_fixnum_value(0);
+ }
+ for ( ;p<pend;p++) {
+ if (*p == '_') {
+ p++;
+ if (p==pend) {
+ if (badcheck) goto bad;
+ continue;
+ }
+ if (*p == '_') {
+ if (badcheck) goto bad;
+ break;
+ }
+ }
+ if (badcheck && *p == '\0') {
+ goto nullbyte;
+ }
+ c = conv_digit(*p);
+ if (c < 0 || c >= base) {
+ break;
+ }
+ n *= base;
+ n += c;
+ if (n > (uint64_t)MRB_INT_MAX + (sign ? 0 : 1)) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer",
+ mrb_str_new(mrb, str, pend-str));
+ }
+ }
+ val = (mrb_int)n;
+ if (badcheck) {
+ if (p == str) goto bad; /* no number */
+ while (p<pend && ISSPACE(*p)) p++;
+ if (p<pend) goto bad; /* trailing garbage */
+ }
+
+ return mrb_fixnum_value(sign ? val : -val);
+ nullbyte:
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
+ /* not reached */
+ bad:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%S)",
+ mrb_inspect(mrb, mrb_str_new(mrb, str, pend-str)));
+ /* not reached */
+ return mrb_fixnum_value(0);
+}
+
+MRB_API mrb_value
+mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
+{
+ return mrb_str_len_to_inum(mrb, str, strlen(str), base, badcheck);
+}
+
+MRB_API const char*
+mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr)
+{
+ mrb_value str = mrb_str_to_str(mrb, *ptr);
+ struct RString *ps = mrb_str_ptr(str);
+ mrb_int len = mrb_str_strlen(mrb, ps);
+ char *p = RSTR_PTR(ps);
+
+ if (!p || p[len] != '\0') {
+ if (MRB_FROZEN_P(ps)) {
+ *ptr = str = mrb_str_dup(mrb, str);
+ ps = mrb_str_ptr(str);
+ }
+ mrb_str_modify(mrb, ps);
+ return RSTR_PTR(ps);
+ }
+ return p;
+}
+
+MRB_API mrb_value
+mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck)
+{
+ const char *s;
+ mrb_int len;
+
+ s = mrb_string_value_ptr(mrb, str);
+ len = RSTRING_LEN(str);
+ return mrb_str_len_to_inum(mrb, s, len, base, badcheck);
+}
+
+/* 15.2.10.5.38 */
+/*
+ * call-seq:
+ * str.to_i(base=10) => integer
+ *
+ * Returns the result of interpreting leading characters in <i>str</i> as an
+ * integer base <i>base</i> (between 2 and 36). Extraneous characters past the
+ * end of a valid number are ignored. If there is not a valid number at the
+ * start of <i>str</i>, <code>0</code> is returned. This method never raises an
+ * exception.
+ *
+ * "12345".to_i #=> 12345
+ * "99 red balloons".to_i #=> 99
+ * "0a".to_i #=> 0
+ * "0a".to_i(16) #=> 10
+ * "hello".to_i #=> 0
+ * "1100101".to_i(2) #=> 101
+ * "1100101".to_i(8) #=> 294977
+ * "1100101".to_i(10) #=> 1100101
+ * "1100101".to_i(16) #=> 17826049
+ */
+static mrb_value
+mrb_str_to_i(mrb_state *mrb, mrb_value self)
+{
+ mrb_int base = 10;
+
+ mrb_get_args(mrb, "|i", &base);
+ if (base < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %S", mrb_fixnum_value(base));
+ }
+ return mrb_str_to_inum(mrb, self, base, FALSE);
+}
+
+MRB_API double
+mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck)
+{
+ char *end;
+ char buf[DBL_DIG * 4 + 10];
+ double d;
+
+ enum {max_width = 20};
+
+ if (!p) return 0.0;
+ while (ISSPACE(*p)) p++;
+
+ if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ return 0.0;
+ }
+ d = mrb_float_read(p, &end);
+ if (p == end) {
+ if (badcheck) {
+bad:
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%S)", mrb_str_new_cstr(mrb, p));
+ /* not reached */
+ }
+ return d;
+ }
+ if (*end) {
+ char *n = buf;
+ char *e = buf + sizeof(buf) - 1;
+ char prev = 0;
+
+ while (p < end && n < e) prev = *n++ = *p++;
+ while (*p) {
+ if (*p == '_') {
+ /* remove underscores between digits */
+ if (badcheck) {
+ if (n == buf || !ISDIGIT(prev)) goto bad;
+ ++p;
+ if (!ISDIGIT(*p)) goto bad;
+ }
+ else {
+ while (*++p == '_');
+ continue;
+ }
+ }
+ prev = *p++;
+ if (n < e) *n++ = prev;
+ }
+ *n = '\0';
+ p = buf;
+
+ if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ return 0.0;
+ }
+
+ d = mrb_float_read(p, &end);
+ if (badcheck) {
+ if (!end || p == end) goto bad;
+ while (*end && ISSPACE(*end)) end++;
+ if (*end) goto bad;
+ }
+ }
+ return d;
+}
+
+MRB_API double
+mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck)
+{
+ char *s;
+ mrb_int len;
+
+ str = mrb_str_to_str(mrb, str);
+ s = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+ if (s) {
+ if (badcheck && memchr(s, '\0', len)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte");
+ }
+ if (s[len]) { /* no sentinel somehow */
+ struct RString *temp_str = str_new(mrb, s, len);
+ s = RSTR_PTR(temp_str);
+ }
+ }
+ return mrb_cstr_to_dbl(mrb, s, badcheck);
+}
+
+/* 15.2.10.5.39 */
+/*
+ * call-seq:
+ * str.to_f => float
+ *
+ * Returns the result of interpreting leading characters in <i>str</i> as a
+ * floating point number. Extraneous characters past the end of a valid number
+ * are ignored. If there is not a valid number at the start of <i>str</i>,
+ * <code>0.0</code> is returned. This method never raises an exception.
+ *
+ * "123.45e1".to_f #=> 1234.5
+ * "45.67 degrees".to_f #=> 45.67
+ * "thx1138".to_f #=> 0.0
+ */
+static mrb_value
+mrb_str_to_f(mrb_state *mrb, mrb_value self)
+{
+ return mrb_float_value(mrb, mrb_str_to_dbl(mrb, self, FALSE));
+}
+
+/* 15.2.10.5.40 */
+/*
+ * call-seq:
+ * str.to_s => str
+ * str.to_str => str
+ *
+ * Returns the receiver.
+ */
+static mrb_value
+mrb_str_to_s(mrb_state *mrb, mrb_value self)
+{
+ if (mrb_obj_class(mrb, self) != mrb->string_class) {
+ return mrb_str_dup(mrb, self);
+ }
+ return self;
+}
+
+/* 15.2.10.5.43 */
+/*
+ * call-seq:
+ * str.upcase! => str or nil
+ *
+ * Upcases the contents of <i>str</i>, returning <code>nil</code> if no changes
+ * were made.
+ */
+static mrb_value
+mrb_str_upcase_bang(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+ char *p, *pend;
+ mrb_bool modify = FALSE;
+
+ mrb_str_modify(mrb, s);
+ p = RSTRING_PTR(str);
+ pend = RSTRING_END(str);
+ while (p < pend) {
+ if (ISLOWER(*p)) {
+ *p = TOUPPER(*p);
+ modify = TRUE;
+ }
+ p++;
+ }
+
+ if (modify) return str;
+ return mrb_nil_value();
+}
+
+/* 15.2.10.5.42 */
+/*
+ * call-seq:
+ * str.upcase => new_str
+ *
+ * Returns a copy of <i>str</i> with all lowercase letters replaced with their
+ * uppercase counterparts. The operation is locale insensitive---only
+ * characters 'a' to 'z' are affected.
+ *
+ * "hEllO".upcase #=> "HELLO"
+ */
+static mrb_value
+mrb_str_upcase(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+
+ str = mrb_str_dup(mrb, self);
+ mrb_str_upcase_bang(mrb, str);
+ return str;
+}
+
+#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
+
+/*
+ * call-seq:
+ * str.dump -> new_str
+ *
+ * Produces a version of <i>str</i> with all nonprinting characters replaced by
+ * <code>\nnn</code> notation and all special characters escaped.
+ */
+mrb_value
+mrb_str_dump(mrb_state *mrb, mrb_value str)
+{
+ mrb_int len;
+ const char *p, *pend;
+ char *q;
+ struct RString *result;
+
+ len = 2; /* "" */
+ p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
+ while (p < pend) {
+ unsigned char c = *p++;
+ switch (c) {
+ case '"': case '\\':
+ case '\n': case '\r':
+ case '\t': case '\f':
+ case '\013': case '\010': case '\007': case '\033':
+ len += 2;
+ break;
+
+ case '#':
+ len += IS_EVSTR(p, pend) ? 2 : 1;
+ break;
+
+ default:
+ if (ISPRINT(c)) {
+ len++;
+ }
+ else {
+ len += 4; /* \NNN */
+ }
+ break;
+ }
+ }
+
+ result = str_new(mrb, 0, len);
+ str_with_class(mrb, result, str);
+ p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
+ q = RSTR_PTR(result);
+ *q++ = '"';
+ while (p < pend) {
+ unsigned char c = *p++;
+
+ switch (c) {
+ case '"':
+ case '\\':
+ *q++ = '\\';
+ *q++ = c;
+ break;
+
+ case '\n':
+ *q++ = '\\';
+ *q++ = 'n';
+ break;
+
+ case '\r':
+ *q++ = '\\';
+ *q++ = 'r';
+ break;
+
+ case '\t':
+ *q++ = '\\';
+ *q++ = 't';
+ break;
+
+ case '\f':
+ *q++ = '\\';
+ *q++ = 'f';
+ break;
+
+ case '\013':
+ *q++ = '\\';
+ *q++ = 'v';
+ break;
+
+ case '\010':
+ *q++ = '\\';
+ *q++ = 'b';
+ break;
+
+ case '\007':
+ *q++ = '\\';
+ *q++ = 'a';
+ break;
+
+ case '\033':
+ *q++ = '\\';
+ *q++ = 'e';
+ break;
+
+ case '#':
+ if (IS_EVSTR(p, pend)) *q++ = '\\';
+ *q++ = '#';
+ break;
+
+ default:
+ if (ISPRINT(c)) {
+ *q++ = c;
+ }
+ else {
+ *q++ = '\\';
+ q[2] = '0' + c % 8; c /= 8;
+ q[1] = '0' + c % 8; c /= 8;
+ q[0] = '0' + c % 8;
+ q += 3;
+ }
+ }
+ }
+ *q = '"';
+ return mrb_obj_value(result);
+}
+
+MRB_API mrb_value
+mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
+{
+ struct RString *s = mrb_str_ptr(str);
+ size_t capa;
+ size_t total;
+ ptrdiff_t off = -1;
+
+ if (len == 0) return str;
+ mrb_str_modify(mrb, s);
+ if (ptr >= RSTR_PTR(s) && ptr <= RSTR_PTR(s) + (size_t)RSTR_LEN(s)) {
+ off = ptr - RSTR_PTR(s);
+ }
+
+ capa = RSTR_CAPA(s);
+ total = RSTR_LEN(s)+len;
+ if (total >= MRB_INT_MAX) {
+ size_error:
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
+ }
+ if (capa <= total) {
+ if (capa == 0) capa = 1;
+ while (capa <= total) {
+ if (capa <= MRB_INT_MAX / 2) {
+ capa *= 2;
+ }
+ else {
+ capa = total+1;
+ }
+ }
+ if (capa <= total || capa > MRB_INT_MAX) {
+ goto size_error;
+ }
+ resize_capa(mrb, s, capa);
+ }
+ if (off != -1) {
+ ptr = RSTR_PTR(s) + off;
+ }
+ memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len);
+ mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX);
+ RSTR_SET_LEN(s, total);
+ RSTR_PTR(s)[total] = '\0'; /* sentinel */
+ return str;
+}
+
+MRB_API mrb_value
+mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
+{
+ return mrb_str_cat(mrb, str, ptr, strlen(ptr));
+}
+
+MRB_API mrb_value
+mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2)
+{
+ return mrb_str_cat(mrb, str, RSTRING_PTR(str2), RSTRING_LEN(str2));
+}
+
+MRB_API mrb_value
+mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2)
+{
+ str2 = mrb_str_to_str(mrb, str2);
+ return mrb_str_cat_str(mrb, str1, str2);
+}
+
+#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
+
+/*
+ * call-seq:
+ * str.inspect -> string
+ *
+ * Returns a printable version of _str_, surrounded by quote marks,
+ * with special characters escaped.
+ *
+ * str = "hello"
+ * str[3] = "\b"
+ * str.inspect #=> "\"hel\\bo\""
+ */
+mrb_value
+mrb_str_inspect(mrb_state *mrb, mrb_value str)
+{
+ const char *p, *pend;
+ char buf[CHAR_ESC_LEN + 1];
+ mrb_value result = mrb_str_new_lit(mrb, "\"");
+
+ p = RSTRING_PTR(str); pend = RSTRING_END(str);
+ for (;p < pend; p++) {
+ unsigned char c, cc;
+#ifdef MRB_UTF8_STRING
+ mrb_int clen;
+
+ clen = utf8len(p, pend);
+ if (clen > 1) {
+ mrb_int i;
+
+ for (i=0; i<clen; i++) {
+ buf[i] = p[i];
+ }
+ mrb_str_cat(mrb, result, buf, clen);
+ p += clen-1;
+ continue;
+ }
+#endif
+ c = *p;
+ if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p+1, pend))) {
+ buf[0] = '\\'; buf[1] = c;
+ mrb_str_cat(mrb, result, buf, 2);
+ continue;
+ }
+ if (ISPRINT(c)) {
+ buf[0] = c;
+ mrb_str_cat(mrb, result, buf, 1);
+ continue;
+ }
+ switch (c) {
+ case '\n': cc = 'n'; break;
+ case '\r': cc = 'r'; break;
+ case '\t': cc = 't'; break;
+ case '\f': cc = 'f'; break;
+ case '\013': cc = 'v'; break;
+ case '\010': cc = 'b'; break;
+ case '\007': cc = 'a'; break;
+ case 033: cc = 'e'; break;
+ default: cc = 0; break;
+ }
+ if (cc) {
+ buf[0] = '\\';
+ buf[1] = (char)cc;
+ mrb_str_cat(mrb, result, buf, 2);
+ continue;
+ }
+ else {
+ buf[0] = '\\';
+ buf[3] = '0' + c % 8; c /= 8;
+ buf[2] = '0' + c % 8; c /= 8;
+ buf[1] = '0' + c % 8;
+ mrb_str_cat(mrb, result, buf, 4);
+ continue;
+ }
+ }
+ mrb_str_cat_lit(mrb, result, "\"");
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * str.bytes -> array of fixnums
+ *
+ * Returns an array of bytes in _str_.
+ *
+ * str = "hello"
+ * str.bytes #=> [104, 101, 108, 108, 111]
+ */
+static mrb_value
+mrb_str_bytes(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+ mrb_value a = mrb_ary_new_capa(mrb, RSTR_LEN(s));
+ unsigned char *p = (unsigned char *)(RSTR_PTR(s)), *pend = p + RSTR_LEN(s);
+
+ while (p < pend) {
+ mrb_ary_push(mrb, a, mrb_fixnum_value(p[0]));
+ p++;
+ }
+ return a;
+}
+
+/* ---------------------------*/
+void
+mrb_init_string(mrb_state *mrb)
+{
+ struct RClass *s;
+
+ mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << 5), "pointer size too big for embedded string");
+
+ mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */
+ MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
+
+ mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */
+ mrb_define_method(mrb, s, "==", mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.2 */
+ mrb_define_method(mrb, s, "+", mrb_str_plus_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.4 */
+ mrb_define_method(mrb, s, "*", mrb_str_times, MRB_ARGS_REQ(1)); /* 15.2.10.5.5 */
+ mrb_define_method(mrb, s, "[]", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.6 */
+ mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, MRB_ARGS_NONE()); /* 15.2.10.5.7 */
+ mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8 */
+ mrb_define_method(mrb, s, "chomp", mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */
+ mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */
+ mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_NONE()); /* 15.2.10.5.11 */
+ mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_NONE()); /* 15.2.10.5.12 */
+ mrb_define_method(mrb, s, "downcase", mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */
+ mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */
+ mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */
+ mrb_define_method(mrb, s, "eql?", mrb_str_eql, MRB_ARGS_REQ(1)); /* 15.2.10.5.17 */
+
+ mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */
+ mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */
+ mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY()); /* 15.2.10.5.22 */
+ mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */
+ mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */
+ mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */
+ mrb_define_method(mrb, s, "length", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.26 */
+ mrb_define_method(mrb, s, "replace", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */
+ mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); /* 15.2.10.5.29 */
+ mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); /* 15.2.10.5.30 */
+ mrb_define_method(mrb, s, "rindex", mrb_str_rindex, MRB_ARGS_ANY()); /* 15.2.10.5.31 */
+ mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.33 */
+ mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */
+ mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */
+
+ mrb_define_method(mrb, s, "to_f", mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.38 */
+ mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */
+ mrb_define_method(mrb, s, "to_s", mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */
+ mrb_define_method(mrb, s, "to_str", mrb_str_to_s, MRB_ARGS_NONE());
+ mrb_define_method(mrb, s, "to_sym", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */
+ mrb_define_method(mrb, s, "upcase", mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */
+ mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */
+ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */
+ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE());
+}
+
+/*
+ * Source code for the "strtod" library procedure.
+ *
+ * Copyright (c) 1988-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ *
+ * RCS: @(#) $Id: strtod.c 11708 2007-02-12 23:01:19Z shyouhei $
+ */
+
+#include <ctype.h>
+#include <errno.h>
+
+static const int maxExponent = 511; /* Largest possible base 10 exponent. Any
+ * exponent larger than this will already
+ * produce underflow or overflow, so there's
+ * no need to worry about additional digits.
+ */
+static const double powersOf10[] = {/* Table giving binary powers of 10. Entry */
+ 10., /* is 10^2^i. Used to convert decimal */
+ 100., /* exponents into floating-point numbers. */
+ 1.0e4,
+ 1.0e8,
+ 1.0e16,
+ 1.0e32,
+ 1.0e64,
+ 1.0e128,
+ 1.0e256
+};
+
+MRB_API double
+mrb_float_read(const char *string, char **endPtr)
+/* const char *string; A decimal ASCII floating-point number,
+ * optionally preceded by white space.
+ * Must have form "-I.FE-X", where I is the
+ * integer part of the mantissa, F is the
+ * fractional part of the mantissa, and X
+ * is the exponent. Either of the signs
+ * may be "+", "-", or omitted. Either I
+ * or F may be omitted, or both. The decimal
+ * point isn't necessary unless F is present.
+ * The "E" may actually be an "e". E and X
+ * may both be omitted (but not just one).
+ */
+/* char **endPtr; If non-NULL, store terminating character's
+ * address here. */
+{
+ int sign, expSign = FALSE;
+ double fraction, dblExp;
+ const double *d;
+ register const char *p;
+ register int c;
+ int exp = 0; /* Exponent read from "EX" field. */
+ int fracExp = 0; /* Exponent that derives from the fractional
+ * part. Under normal circumstatnces, it is
+ * the negative of the number of digits in F.
+ * However, if I is very long, the last digits
+ * of I get dropped (otherwise a long I with a
+ * large negative exponent could cause an
+ * unnecessary overflow on I alone). In this
+ * case, fracExp is incremented one for each
+ * dropped digit. */
+ int mantSize; /* Number of digits in mantissa. */
+ int decPt; /* Number of mantissa digits BEFORE decimal
+ * point. */
+ const char *pExp; /* Temporarily holds location of exponent
+ * in string. */
+
+ /*
+ * Strip off leading blanks and check for a sign.
+ */
+
+ p = string;
+ while (isspace(*p)) {
+ p += 1;
+ }
+ if (*p == '-') {
+ sign = TRUE;
+ p += 1;
+ }
+ else {
+ if (*p == '+') {
+ p += 1;
+ }
+ sign = FALSE;
+ }
+
+ /*
+ * Count the number of digits in the mantissa (including the decimal
+ * point), and also locate the decimal point.
+ */
+
+ decPt = -1;
+ for (mantSize = 0; ; mantSize += 1)
+ {
+ c = *p;
+ if (!isdigit(c)) {
+ if ((c != '.') || (decPt >= 0)) {
+ break;
+ }
+ decPt = mantSize;
+ }
+ p += 1;
+ }
+
+ /*
+ * Now suck up the digits in the mantissa. Use two integers to
+ * collect 9 digits each (this is faster than using floating-point).
+ * If the mantissa has more than 18 digits, ignore the extras, since
+ * they can't affect the value anyway.
+ */
+
+ pExp = p;
+ p -= mantSize;
+ if (decPt < 0) {
+ decPt = mantSize;
+ }
+ else {
+ mantSize -= 1; /* One of the digits was the point. */
+ }
+ if (mantSize > 18) {
+ if (decPt - 18 > 29999) {
+ fracExp = 29999;
+ }
+ else {
+ fracExp = decPt - 18;
+ }
+ mantSize = 18;
+ }
+ else {
+ fracExp = decPt - mantSize;
+ }
+ if (mantSize == 0) {
+ fraction = 0.0;
+ p = string;
+ goto done;
+ }
+ else {
+ int frac1, frac2;
+ frac1 = 0;
+ for ( ; mantSize > 9; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.') {
+ c = *p;
+ p += 1;
+ }
+ frac1 = 10*frac1 + (c - '0');
+ }
+ frac2 = 0;
+ for (; mantSize > 0; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.') {
+ c = *p;
+ p += 1;
+ }
+ frac2 = 10*frac2 + (c - '0');
+ }
+ fraction = (1.0e9 * frac1) + frac2;
+ }
+
+ /*
+ * Skim off the exponent.
+ */
+
+ p = pExp;
+ if ((*p == 'E') || (*p == 'e')) {
+ p += 1;
+ if (*p == '-') {
+ expSign = TRUE;
+ p += 1;
+ }
+ else {
+ if (*p == '+') {
+ p += 1;
+ }
+ expSign = FALSE;
+ }
+ while (isdigit(*p)) {
+ exp = exp * 10 + (*p - '0');
+ if (exp > 19999) {
+ exp = 19999;
+ }
+ p += 1;
+ }
+ }
+ if (expSign) {
+ exp = fracExp - exp;
+ }
+ else {
+ exp = fracExp + exp;
+ }
+
+ /*
+ * Generate a floating-point number that represents the exponent.
+ * Do this by processing the exponent one bit at a time to combine
+ * many powers of 2 of 10. Then combine the exponent with the
+ * fraction.
+ */
+
+ if (exp < 0) {
+ expSign = TRUE;
+ exp = -exp;
+ }
+ else {
+ expSign = FALSE;
+ }
+ if (exp > maxExponent) {
+ exp = maxExponent;
+ errno = ERANGE;
+ }
+ dblExp = 1.0;
+ for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
+ if (exp & 01) {
+ dblExp *= *d;
+ }
+ }
+ if (expSign) {
+ fraction /= dblExp;
+ }
+ else {
+ fraction *= dblExp;
+ }
+
+done:
+ if (endPtr != NULL) {
+ *endPtr = (char *) p;
+ }
+
+ if (sign) {
+ return -fraction;
+ }
+ return fraction;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/symbol.c b/web/server/h2o/libh2o/deps/mruby/src/symbol.c
new file mode 100644
index 00000000..a3ab05c8
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/symbol.c
@@ -0,0 +1,494 @@
+/*
+** symbol.c - Symbol class
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <limits.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/khash.h>
+#include <mruby/string.h>
+#include <mruby/dump.h>
+#include <mruby/class.h>
+
+/* ------------------------------------------------------ */
+typedef struct symbol_name {
+ mrb_bool lit : 1;
+ uint16_t len;
+ const char *name;
+} symbol_name;
+
+static inline khint_t
+sym_hash_func(mrb_state *mrb, mrb_sym s)
+{
+ khint_t h = 0;
+ size_t i, len = mrb->symtbl[s].len;
+ const char *p = mrb->symtbl[s].name;
+
+ for (i=0; i<len; i++) {
+ h = (h << 5) - h + *p++;
+ }
+ return h;
+}
+#define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0)
+
+KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
+KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
+/* ------------------------------------------------------ */
+
+static void
+sym_validate_len(mrb_state *mrb, size_t len)
+{
+ if (len >= RITE_LV_NULL_MARK) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ }
+}
+
+static mrb_sym
+sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
+{
+ khash_t(n2s) *h = mrb->name2sym;
+ symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
+ khiter_t k;
+ mrb_sym sym;
+ char *p;
+
+ sym_validate_len(mrb, len);
+ if (sname) {
+ sname->lit = lit;
+ sname->len = (uint16_t)len;
+ sname->name = name;
+ k = kh_get(n2s, mrb, h, 0);
+ if (k != kh_end(h))
+ return kh_key(h, k);
+ }
+
+ /* registering a new symbol */
+ sym = ++mrb->symidx;
+ if (mrb->symcapa < sym) {
+ if (mrb->symcapa == 0) mrb->symcapa = 100;
+ else mrb->symcapa = (size_t)(mrb->symcapa * 1.2);
+ mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
+ }
+ sname = &mrb->symtbl[sym];
+ sname->len = (uint16_t)len;
+ if (lit || mrb_ro_data_p(name)) {
+ sname->name = name;
+ sname->lit = TRUE;
+ }
+ else {
+ p = (char *)mrb_malloc(mrb, len+1);
+ memcpy(p, name, len);
+ p[len] = 0;
+ sname->name = (const char*)p;
+ sname->lit = FALSE;
+ }
+ kh_put(n2s, mrb, h, sym);
+
+ return sym;
+}
+
+MRB_API mrb_sym
+mrb_intern(mrb_state *mrb, const char *name, size_t len)
+{
+ return sym_intern(mrb, name, len, FALSE);
+}
+
+MRB_API mrb_sym
+mrb_intern_static(mrb_state *mrb, const char *name, size_t len)
+{
+ return sym_intern(mrb, name, len, TRUE);
+}
+
+MRB_API mrb_sym
+mrb_intern_cstr(mrb_state *mrb, const char *name)
+{
+ return mrb_intern(mrb, name, strlen(name));
+}
+
+MRB_API mrb_sym
+mrb_intern_str(mrb_state *mrb, mrb_value str)
+{
+ return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
+}
+
+MRB_API mrb_value
+mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
+{
+ khash_t(n2s) *h = mrb->name2sym;
+ symbol_name *sname = mrb->symtbl;
+ khiter_t k;
+
+ sym_validate_len(mrb, len);
+ sname->len = (uint16_t)len;
+ sname->name = name;
+
+ k = kh_get(n2s, mrb, h, 0);
+ if (k != kh_end(h)) {
+ return mrb_symbol_value(kh_key(h, k));
+ }
+ return mrb_nil_value();
+}
+
+MRB_API mrb_value
+mrb_check_intern_cstr(mrb_state *mrb, const char *name)
+{
+ return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
+}
+
+MRB_API mrb_value
+mrb_check_intern_str(mrb_state *mrb, mrb_value str)
+{
+ return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
+}
+
+/* lenp must be a pointer to a size_t variable */
+MRB_API const char*
+mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
+{
+ if (sym == 0 || mrb->symidx < sym) {
+ if (lenp) *lenp = 0;
+ return NULL;
+ }
+
+ if (lenp) *lenp = mrb->symtbl[sym].len;
+ return mrb->symtbl[sym].name;
+}
+
+void
+mrb_free_symtbl(mrb_state *mrb)
+{
+ mrb_sym i, lim;
+
+ for (i=1, lim=mrb->symidx+1; i<lim; i++) {
+ if (!mrb->symtbl[i].lit) {
+ mrb_free(mrb, (char*)mrb->symtbl[i].name);
+ }
+ }
+ mrb_free(mrb, mrb->symtbl);
+ kh_destroy(n2s, mrb, mrb->name2sym);
+}
+
+void
+mrb_init_symtbl(mrb_state *mrb)
+{
+ mrb->name2sym = kh_init(n2s, mrb);
+}
+
+/**********************************************************************
+ * Document-class: Symbol
+ *
+ * <code>Symbol</code> objects represent names and some strings
+ * inside the Ruby
+ * interpreter. They are generated using the <code>:name</code> and
+ * <code>:"string"</code> literals
+ * syntax, and by the various <code>to_sym</code> methods. The same
+ * <code>Symbol</code> object will be created for a given name or string
+ * for the duration of a program's execution, regardless of the context
+ * or meaning of that name. Thus if <code>Fred</code> is a constant in
+ * one context, a method in another, and a class in a third, the
+ * <code>Symbol</code> <code>:Fred</code> will be the same object in
+ * all three contexts.
+ *
+ * module One
+ * class Fred
+ * end
+ * $f1 = :Fred
+ * end
+ * module Two
+ * Fred = 1
+ * $f2 = :Fred
+ * end
+ * def Fred()
+ * end
+ * $f3 = :Fred
+ * $f1.object_id #=> 2514190
+ * $f2.object_id #=> 2514190
+ * $f3.object_id #=> 2514190
+ *
+ */
+
+
+/* 15.2.11.3.1 */
+/*
+ * call-seq:
+ * sym == obj -> true or false
+ *
+ * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
+ * symbol, returns <code>true</code>.
+ */
+
+static mrb_value
+sym_equal(mrb_state *mrb, mrb_value sym1)
+{
+ mrb_value sym2;
+
+ mrb_get_args(mrb, "o", &sym2);
+
+ return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2));
+}
+
+/* 15.2.11.3.2 */
+/* 15.2.11.3.3 */
+/*
+ * call-seq:
+ * sym.id2name -> string
+ * sym.to_s -> string
+ *
+ * Returns the name or string corresponding to <i>sym</i>.
+ *
+ * :fred.id2name #=> "fred"
+ */
+static mrb_value
+mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
+{
+ mrb_sym id = mrb_symbol(sym);
+ const char *p;
+ mrb_int len;
+
+ p = mrb_sym2name_len(mrb, id, &len);
+ return mrb_str_new_static(mrb, p, len);
+}
+
+/* 15.2.11.3.4 */
+/*
+ * call-seq:
+ * sym.to_sym -> sym
+ * sym.intern -> sym
+ *
+ * In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
+ * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
+ * in this case.
+ */
+
+static mrb_value
+sym_to_sym(mrb_state *mrb, mrb_value sym)
+{
+ return sym;
+}
+
+/* 15.2.11.3.5(x) */
+/*
+ * call-seq:
+ * sym.inspect -> string
+ *
+ * Returns the representation of <i>sym</i> as a symbol literal.
+ *
+ * :fred.inspect #=> ":fred"
+ */
+
+#if __STDC__
+# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+#else /* not __STDC__ */
+/* As in Harbison and Steele. */
+# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
+#endif
+#define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_'))
+
+static mrb_bool
+is_special_global_name(const char* m)
+{
+ switch (*m) {
+ case '~': case '*': case '$': case '?': case '!': case '@':
+ case '/': case '\\': case ';': case ',': case '.': case '=':
+ case ':': case '<': case '>': case '\"':
+ case '&': case '`': case '\'': case '+':
+ case '0':
+ ++m;
+ break;
+ case '-':
+ ++m;
+ if (is_identchar(*m)) m += 1;
+ break;
+ default:
+ if (!ISDIGIT(*m)) return FALSE;
+ do ++m; while (ISDIGIT(*m));
+ break;
+ }
+ return !*m;
+}
+
+static mrb_bool
+symname_p(const char *name)
+{
+ const char *m = name;
+ mrb_bool localid = FALSE;
+
+ if (!m) return FALSE;
+ switch (*m) {
+ case '\0':
+ return FALSE;
+
+ case '$':
+ if (is_special_global_name(++m)) return TRUE;
+ goto id;
+
+ case '@':
+ if (*++m == '@') ++m;
+ goto id;
+
+ case '<':
+ switch (*++m) {
+ case '<': ++m; break;
+ case '=': if (*++m == '>') ++m; break;
+ default: break;
+ }
+ break;
+
+ case '>':
+ switch (*++m) {
+ case '>': case '=': ++m; break;
+ default: break;
+ }
+ break;
+
+ case '=':
+ switch (*++m) {
+ case '~': ++m; break;
+ case '=': if (*++m == '=') ++m; break;
+ default: return FALSE;
+ }
+ break;
+
+ case '*':
+ if (*++m == '*') ++m;
+ break;
+ case '!':
+ switch (*++m) {
+ case '=': case '~': ++m;
+ }
+ break;
+ case '+': case '-':
+ if (*++m == '@') ++m;
+ break;
+ case '|':
+ if (*++m == '|') ++m;
+ break;
+ case '&':
+ if (*++m == '&') ++m;
+ break;
+
+ case '^': case '/': case '%': case '~': case '`':
+ ++m;
+ break;
+
+ case '[':
+ if (*++m != ']') return FALSE;
+ if (*++m == '=') ++m;
+ break;
+
+ default:
+ localid = !ISUPPER(*m);
+id:
+ if (*m != '_' && !ISALPHA(*m)) return FALSE;
+ while (is_identchar(*m)) m += 1;
+ if (localid) {
+ switch (*m) {
+ case '!': case '?': case '=': ++m;
+ default: break;
+ }
+ }
+ break;
+ }
+ return *m ? FALSE : TRUE;
+}
+
+static mrb_value
+sym_inspect(mrb_state *mrb, mrb_value sym)
+{
+ mrb_value str;
+ const char *name;
+ mrb_int len;
+ mrb_sym id = mrb_symbol(sym);
+ char *sp;
+
+ name = mrb_sym2name_len(mrb, id, &len);
+ str = mrb_str_new(mrb, 0, len+1);
+ sp = RSTRING_PTR(str);
+ RSTRING_PTR(str)[0] = ':';
+ memcpy(sp+1, name, len);
+ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
+ if (!symname_p(name) || strlen(name) != (size_t)len) {
+ str = mrb_str_dump(mrb, str);
+ sp = RSTRING_PTR(str);
+ sp[0] = ':';
+ sp[1] = '"';
+ }
+ return str;
+}
+
+MRB_API mrb_value
+mrb_sym2str(mrb_state *mrb, mrb_sym sym)
+{
+ mrb_int len;
+ const char *name = mrb_sym2name_len(mrb, sym, &len);
+
+ if (!name) return mrb_undef_value(); /* can't happen */
+ return mrb_str_new_static(mrb, name, len);
+}
+
+MRB_API const char*
+mrb_sym2name(mrb_state *mrb, mrb_sym sym)
+{
+ mrb_int len;
+ const char *name = mrb_sym2name_len(mrb, sym, &len);
+
+ if (!name) return NULL;
+ if (symname_p(name) && strlen(name) == (size_t)len) {
+ return name;
+ }
+ else {
+ mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len));
+ return RSTRING_PTR(str);
+ }
+}
+
+#define lesser(a,b) (((a)>(b))?(b):(a))
+
+static mrb_value
+sym_cmp(mrb_state *mrb, mrb_value s1)
+{
+ mrb_value s2;
+ mrb_sym sym1, sym2;
+
+ mrb_get_args(mrb, "o", &s2);
+ if (mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value();
+ sym1 = mrb_symbol(s1);
+ sym2 = mrb_symbol(s2);
+ if (sym1 == sym2) return mrb_fixnum_value(0);
+ else {
+ const char *p1, *p2;
+ int retval;
+ mrb_int len, len1, len2;
+
+ p1 = mrb_sym2name_len(mrb, sym1, &len1);
+ p2 = mrb_sym2name_len(mrb, sym2, &len2);
+ len = lesser(len1, len2);
+ retval = memcmp(p1, p2, len);
+ if (retval == 0) {
+ if (len1 == len2) return mrb_fixnum_value(0);
+ if (len1 > len2) return mrb_fixnum_value(1);
+ return mrb_fixnum_value(-1);
+ }
+ if (retval > 0) return mrb_fixnum_value(1);
+ return mrb_fixnum_value(-1);
+ }
+}
+
+void
+mrb_init_symbol(mrb_state *mrb)
+{
+ struct RClass *sym;
+
+ mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */
+ MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL);
+ mrb_undef_class_method(mrb, sym, "new");
+
+ mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */
+ mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */
+ mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */
+ mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
+ mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
+ mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/value_array.h b/web/server/h2o/libh2o/deps/mruby/src/value_array.h
new file mode 100644
index 00000000..bc5f28b0
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/value_array.h
@@ -0,0 +1,27 @@
+#ifndef MRB_VALUE_ARRAY_H__
+#define MRB_VALUE_ARRAY_H__
+
+#include <mruby.h>
+
+static inline void
+value_move(mrb_value *s1, const mrb_value *s2, size_t n)
+{
+ if (s1 > s2 && s1 < s2 + n)
+ {
+ s1 += n;
+ s2 += n;
+ while (n-- > 0) {
+ *--s1 = *--s2;
+ }
+ }
+ else if (s1 != s2) {
+ while (n-- > 0) {
+ *s1++ = *s2++;
+ }
+ }
+ else {
+ /* nothing to do. */
+ }
+}
+
+#endif /* MRB_VALUE_ARRAY_H__ */
diff --git a/web/server/h2o/libh2o/deps/mruby/src/variable.c b/web/server/h2o/libh2o/deps/mruby/src/variable.c
new file mode 100644
index 00000000..50fc7068
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/variable.c
@@ -0,0 +1,987 @@
+/*
+** variable.c - mruby variables
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/string.h>
+
+typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
+
+#include <mruby/khash.h>
+
+#ifndef MRB_IVHASH_INIT_SIZE
+#define MRB_IVHASH_INIT_SIZE KHASH_MIN_SIZE
+#endif
+
+KHASH_DECLARE(iv, mrb_sym, mrb_value, TRUE)
+KHASH_DEFINE(iv, mrb_sym, mrb_value, TRUE, kh_int_hash_func, kh_int_hash_equal)
+
+/* Instance variable table structure */
+typedef struct iv_tbl {
+ khash_t(iv) h;
+} iv_tbl;
+
+/*
+ * Creates the instance variable table.
+ *
+ * Parameters
+ * mrb
+ * Returns
+ * the instance variable table.
+ */
+static iv_tbl*
+iv_new(mrb_state *mrb)
+{
+ return (iv_tbl*)kh_init_size(iv, mrb, MRB_IVHASH_INIT_SIZE);
+}
+
+/*
+ * Set the value for the symbol in the instance variable table.
+ *
+ * Parameters
+ * mrb
+ * t the instance variable table to be set in.
+ * sym the symbol to be used as the key.
+ * val the value to be set.
+ */
+static void
+iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
+{
+ khash_t(iv) *h = &t->h;
+ khiter_t k;
+
+ k = kh_put(iv, mrb, h, sym);
+ kh_value(h, k) = val;
+}
+
+/*
+ * Get a value for a symbol from the instance variable table.
+ *
+ * Parameters
+ * mrb
+ * t the variable table to be searched.
+ * sym the symbol to be used as the key.
+ * vp the value pointer. Receives the value if the specified symbol is
+ * contained in the instance variable table.
+ * Returns
+ * true if the specified symbol is contained in the instance variable table.
+ */
+static mrb_bool
+iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
+{
+ khash_t(iv) *h = &t->h;
+ khiter_t k;
+
+ k = kh_get(iv, mrb, h, sym);
+ if (k != kh_end(h)) {
+ if (vp) *vp = kh_value(h, k);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Deletes the value for the symbol from the instance variable table.
+ *
+ * Parameters
+ * t the variable table to be searched.
+ * sym the symbol to be used as the key.
+ * vp the value pointer. Receive the deleted value if the symbol is
+ * contained in the instance variable table.
+ * Returns
+ * true if the specified symbol is contained in the instance variable table.
+ */
+static mrb_bool
+iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
+{
+ if (t == NULL) return FALSE;
+ else {
+ khash_t(iv) *h = &t->h;
+ khiter_t k;
+
+ k = kh_get(iv, mrb, h, sym);
+ if (k != kh_end(h)) {
+ mrb_value val = kh_value(h, k);
+ kh_del(iv, mrb, h, k);
+ if (vp) *vp = val;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static mrb_bool
+iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
+{
+ if (t == NULL) {
+ return TRUE;
+ }
+ else {
+ khash_t(iv) *h = &t->h;
+ khiter_t k;
+ int n;
+
+ for (k = kh_begin(h); k != kh_end(h); k++) {
+ if (kh_exist(h, k)) {
+ n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
+ if (n > 0) return FALSE;
+ if (n < 0) {
+ kh_del(iv, mrb, h, k);
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+static size_t
+iv_size(mrb_state *mrb, iv_tbl *t)
+{
+ if (t) {
+ return kh_size(&t->h);
+ }
+ return 0;
+}
+
+static iv_tbl*
+iv_copy(mrb_state *mrb, iv_tbl *t)
+{
+ return (iv_tbl*)kh_copy(iv, mrb, &t->h);
+}
+
+static void
+iv_free(mrb_state *mrb, iv_tbl *t)
+{
+ kh_destroy(iv, mrb, &t->h);
+}
+
+static int
+iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ mrb_gc_mark_value(mrb, v);
+ return 0;
+}
+
+static void
+mark_tbl(mrb_state *mrb, iv_tbl *t)
+{
+ if (t) {
+ iv_foreach(mrb, t, iv_mark_i, 0);
+ }
+}
+
+void
+mrb_gc_mark_gv(mrb_state *mrb)
+{
+ mark_tbl(mrb, mrb->globals);
+}
+
+void
+mrb_gc_free_gv(mrb_state *mrb)
+{
+ if (mrb->globals)
+ iv_free(mrb, mrb->globals);
+}
+
+void
+mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj)
+{
+ mark_tbl(mrb, obj->iv);
+}
+
+size_t
+mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj)
+{
+ return iv_size(mrb, obj->iv);
+}
+
+void
+mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj)
+{
+ if (obj->iv) {
+ iv_free(mrb, obj->iv);
+ }
+}
+
+mrb_value
+mrb_vm_special_get(mrb_state *mrb, mrb_sym i)
+{
+ return mrb_fixnum_value(0);
+}
+
+void
+mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v)
+{
+}
+
+static mrb_bool
+obj_iv_p(mrb_value obj)
+{
+ switch (mrb_type(obj)) {
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
+ case MRB_TT_HASH:
+ case MRB_TT_DATA:
+ case MRB_TT_EXCEPTION:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+MRB_API mrb_value
+mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
+{
+ mrb_value v;
+
+ if (obj->iv && iv_get(mrb, obj->iv, sym, &v))
+ return v;
+ return mrb_nil_value();
+}
+
+MRB_API mrb_value
+mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
+{
+ if (obj_iv_p(obj)) {
+ return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym);
+ }
+ return mrb_nil_value();
+}
+
+MRB_API void
+mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
+{
+ iv_tbl *t = obj->iv;
+
+ if (MRB_FROZEN_P(obj)) {
+ mrb_raisef(mrb, E_RUNTIME_ERROR, "can't modify frozen %S", mrb_obj_value(obj));
+ }
+ if (!t) {
+ t = obj->iv = iv_new(mrb);
+ }
+ mrb_write_barrier(mrb, (struct RBasic*)obj);
+ iv_put(mrb, t, sym, v);
+}
+
+MRB_API void
+mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
+{
+ if (obj_iv_p(obj)) {
+ mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
+ }
+ else {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable");
+ }
+}
+
+MRB_API mrb_bool
+mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
+{
+ iv_tbl *t;
+
+ t = obj->iv;
+ if (t) {
+ return iv_get(mrb, t, sym, NULL);
+ }
+ return FALSE;
+}
+
+MRB_API mrb_bool
+mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
+{
+ if (!obj_iv_p(obj)) return FALSE;
+ return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
+}
+
+#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
+
+MRB_API mrb_bool
+mrb_iv_p(mrb_state *mrb, mrb_sym iv_name)
+{
+ const char *s;
+ mrb_int i, len;
+
+ s = mrb_sym2name_len(mrb, iv_name, &len);
+ if (len < 2) return FALSE;
+ if (s[0] != '@') return FALSE;
+ if (s[1] == '@') return FALSE;
+ for (i=1; i<len; i++) {
+ if (!identchar(s[i])) return FALSE;
+ }
+ return TRUE;
+}
+
+MRB_API void
+mrb_iv_check(mrb_state *mrb, mrb_sym iv_name)
+{
+ if (!mrb_iv_p(mrb, iv_name)) {
+ mrb_name_error(mrb, iv_name, "'%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name));
+ }
+}
+
+MRB_API void
+mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
+{
+ struct RObject *d = mrb_obj_ptr(dest);
+ struct RObject *s = mrb_obj_ptr(src);
+
+ if (d->iv) {
+ iv_free(mrb, d->iv);
+ d->iv = 0;
+ }
+ if (s->iv) {
+ mrb_write_barrier(mrb, (struct RBasic*)d);
+ d->iv = iv_copy(mrb, s->iv);
+ }
+}
+
+static int
+inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ mrb_value str = *(mrb_value*)p;
+ const char *s;
+ mrb_int len;
+ mrb_value ins;
+ char *sp = RSTRING_PTR(str);
+
+ /* need not to show internal data */
+ if (sp[0] == '-') { /* first element */
+ sp[0] = '#';
+ mrb_str_cat_lit(mrb, str, " ");
+ }
+ else {
+ mrb_str_cat_lit(mrb, str, ", ");
+ }
+ s = mrb_sym2name_len(mrb, sym, &len);
+ mrb_str_cat(mrb, str, s, len);
+ mrb_str_cat_lit(mrb, str, "=");
+ if (mrb_type(v) == MRB_TT_OBJECT) {
+ ins = mrb_any_to_s(mrb, v);
+ }
+ else {
+ ins = mrb_inspect(mrb, v);
+ }
+ mrb_str_cat_str(mrb, str, ins);
+ return 0;
+}
+
+mrb_value
+mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
+{
+ iv_tbl *t = obj->iv;
+ size_t len = iv_size(mrb, t);
+
+ if (len > 0) {
+ const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
+ mrb_value str = mrb_str_new_capa(mrb, 30);
+
+ mrb_str_cat_lit(mrb, str, "-<");
+ mrb_str_cat_cstr(mrb, str, cn);
+ mrb_str_cat_lit(mrb, str, ":");
+ mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));
+
+ iv_foreach(mrb, t, inspect_i, &str);
+ mrb_str_cat_lit(mrb, str, ">");
+ return str;
+ }
+ return mrb_any_to_s(mrb, mrb_obj_value(obj));
+}
+
+MRB_API mrb_value
+mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
+{
+ if (obj_iv_p(obj)) {
+ iv_tbl *t = mrb_obj_ptr(obj)->iv;
+ mrb_value val;
+
+ if (t && iv_del(mrb, t, sym, &val)) {
+ return val;
+ }
+ }
+ return mrb_undef_value();
+}
+
+mrb_value
+mrb_vm_iv_get(mrb_state *mrb, mrb_sym sym)
+{
+ /* get self */
+ return mrb_iv_get(mrb, mrb->c->stack[0], sym);
+}
+
+void
+mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
+{
+ /* get self */
+ mrb_iv_set(mrb, mrb->c->stack[0], sym, v);
+}
+
+static int
+iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ mrb_value ary;
+ const char* s;
+ mrb_int len;
+
+ ary = *(mrb_value*)p;
+ s = mrb_sym2name_len(mrb, sym, &len);
+ if (len > 1 && s[0] == '@' && s[1] != '@') {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
+ }
+ return 0;
+}
+
+/* 15.3.1.3.23 */
+/*
+ * call-seq:
+ * obj.instance_variables -> array
+ *
+ * Returns an array of instance variable names for the receiver. Note
+ * that simply defining an accessor does not create the corresponding
+ * instance variable.
+ *
+ * class Fred
+ * attr_accessor :a1
+ * def initialize
+ * @iv = 3
+ * end
+ * end
+ * Fred.new.instance_variables #=> [:@iv]
+ */
+mrb_value
+mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+
+ ary = mrb_ary_new(mrb);
+ if (obj_iv_p(self) && mrb_obj_ptr(self)->iv) {
+ iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary);
+ }
+ return ary;
+}
+
+static int
+cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ mrb_value ary;
+ const char* s;
+ mrb_int len;
+
+ ary = *(mrb_value*)p;
+ s = mrb_sym2name_len(mrb, sym, &len);
+ if (len > 2 && s[0] == '@' && s[1] == '@') {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
+ }
+ return 0;
+}
+
+/* 15.2.2.4.19 */
+/*
+ * call-seq:
+ * mod.class_variables -> array
+ *
+ * Returns an array of the names of class variables in <i>mod</i>.
+ *
+ * class One
+ * @@var1 = 1
+ * end
+ * class Two < One
+ * @@var2 = 2
+ * end
+ * One.class_variables #=> [:@@var1]
+ * Two.class_variables #=> [:@@var2]
+ */
+mrb_value
+mrb_mod_class_variables(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value ary;
+ struct RClass *c;
+
+ ary = mrb_ary_new(mrb);
+ c = mrb_class_ptr(mod);
+ while (c) {
+ if (c->iv) {
+ iv_foreach(mrb, c->iv, cv_i, &ary);
+ }
+ c = c->super;
+ }
+ return ary;
+}
+
+MRB_API mrb_value
+mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym)
+{
+ struct RClass * cls = c;
+ mrb_value v;
+ int given = FALSE;
+
+ while (c) {
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ given = TRUE;
+ }
+ c = c->super;
+ }
+ if (given) return v;
+ if (cls && cls->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)cls,
+ mrb_intern_lit(mrb, "__attached__"));
+ c = mrb_class_ptr(klass);
+ if (c->tt == MRB_TT_CLASS || c->tt == MRB_TT_MODULE) {
+ given = FALSE;
+ while (c) {
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ given = TRUE;
+ }
+ c = c->super;
+ }
+ if (given) return v;
+ }
+ }
+ mrb_name_error(mrb, sym, "uninitialized class variable %S in %S",
+ mrb_sym2str(mrb, sym), mrb_obj_value(cls));
+ /* not reached */
+ return mrb_nil_value();
+}
+
+MRB_API mrb_value
+mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
+{
+ return mrb_mod_cv_get(mrb, mrb_class_ptr(mod), sym);
+}
+
+MRB_API void
+mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
+{
+ struct RClass * cls = c;
+
+ while (c) {
+ if (c->iv) {
+ iv_tbl *t = c->iv;
+
+ if (iv_get(mrb, t, sym, NULL)) {
+ mrb_write_barrier(mrb, (struct RBasic*)c);
+ iv_put(mrb, t, sym, v);
+ return;
+ }
+ }
+ c = c->super;
+ }
+
+ if (cls && cls->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+
+ klass = mrb_obj_iv_get(mrb, (struct RObject*)cls,
+ mrb_intern_lit(mrb, "__attached__"));
+ switch (mrb_type(klass)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
+ c = mrb_class_ptr(klass);
+ break;
+ default:
+ c = cls;
+ break;
+ }
+ }
+ else{
+ c = cls;
+ }
+
+ if (!c->iv) {
+ c->iv = iv_new(mrb);
+ }
+
+ mrb_write_barrier(mrb, (struct RBasic*)c);
+ iv_put(mrb, c->iv, sym, v);
+}
+
+MRB_API void
+mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
+{
+ mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
+}
+
+MRB_API mrb_bool
+mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym)
+{
+ while (c) {
+ if (c->iv) {
+ iv_tbl *t = c->iv;
+ if (iv_get(mrb, t, sym, NULL)) return TRUE;
+ }
+ c = c->super;
+ }
+
+ return FALSE;
+}
+
+MRB_API mrb_bool
+mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
+{
+ return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym);
+}
+
+mrb_value
+mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
+{
+ struct RClass *c = mrb->c->ci->proc->target_class;
+
+ if (!c) c = mrb->c->ci->target_class;
+
+ return mrb_mod_cv_get(mrb, c, sym);
+}
+
+void
+mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
+{
+ struct RClass *c = mrb->c->ci->proc->target_class;
+
+ if (!c) c = mrb->c->ci->target_class;
+ mrb_mod_cv_set(mrb, c, sym, v);
+}
+
+static void
+mod_const_check(mrb_state *mrb, mrb_value mod)
+{
+ switch (mrb_type(mod)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
+ break;
+ default:
+ mrb_raise(mrb, E_TYPE_ERROR, "constant look-up for non class/module");
+ break;
+ }
+}
+
+static mrb_value
+const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
+{
+ struct RClass *c = base;
+ mrb_value v;
+ iv_tbl *t;
+ mrb_bool retry = FALSE;
+ mrb_value name;
+
+L_RETRY:
+ while (c) {
+ if (c->iv) {
+ t = c->iv;
+ if (iv_get(mrb, t, sym, &v))
+ return v;
+ }
+ c = c->super;
+ }
+ if (!retry && base && base->tt == MRB_TT_MODULE) {
+ c = mrb->object_class;
+ retry = TRUE;
+ goto L_RETRY;
+ }
+ name = mrb_symbol_value(sym);
+ return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name);
+}
+
+MRB_API mrb_value
+mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
+{
+ mod_const_check(mrb, mod);
+ return const_get(mrb, mrb_class_ptr(mod), sym);
+}
+
+mrb_value
+mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
+{
+ struct RClass *c = mrb->c->ci->proc->target_class;
+ struct RClass *c2;
+ mrb_value v;
+ mrb_irep *irep;
+
+ if (!c) c = mrb->c->ci->target_class;
+ mrb_assert(c != NULL);
+
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ return v;
+ }
+ c2 = c;
+ while (c2 && c2->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)c2,
+ mrb_intern_lit(mrb, "__attached__"));
+ c2 = mrb_class_ptr(klass);
+ }
+ if (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE) c = c2;
+ mrb_assert(!MRB_PROC_CFUNC_P(mrb->c->ci->proc));
+ irep = mrb->c->ci->proc->body.irep;
+ while (irep) {
+ if (irep->target_class) {
+ c2 = irep->target_class;
+ if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) {
+ return v;
+ }
+ }
+ irep = irep->outer;
+ }
+ return const_get(mrb, c, sym);
+}
+
+MRB_API void
+mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
+{
+ mod_const_check(mrb, mod);
+ if (mrb_type(v) == MRB_TT_CLASS || mrb_type(v) == MRB_TT_MODULE) {
+ mrb_class_name_class(mrb, mrb_class_ptr(mod), mrb_class_ptr(v), sym);
+ }
+ mrb_iv_set(mrb, mod, sym, v);
+}
+
+void
+mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
+{
+ struct RClass *c = mrb->c->ci->proc->target_class;
+
+ if (!c) c = mrb->c->ci->target_class;
+ mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
+}
+
+MRB_API void
+mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym)
+{
+ mod_const_check(mrb, mod);
+ mrb_iv_remove(mrb, mod, sym);
+}
+
+MRB_API void
+mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v)
+{
+ mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v);
+}
+
+MRB_API void
+mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val)
+{
+ mrb_define_const(mrb, mrb->object_class, name, val);
+}
+
+static int
+const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ mrb_value ary;
+ const char* s;
+ mrb_int len;
+
+ ary = *(mrb_value*)p;
+ s = mrb_sym2name_len(mrb, sym, &len);
+ if (len >= 1 && ISUPPER(s[0])) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
+ }
+ return 0;
+}
+
+/* 15.2.2.4.24 */
+/*
+ * call-seq:
+ * mod.constants -> array
+ *
+ * Returns an array of all names of contants defined in the receiver.
+ */
+mrb_value
+mrb_mod_constants(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value ary;
+ mrb_bool inherit = TRUE;
+ struct RClass *c = mrb_class_ptr(mod);
+
+ mrb_get_args(mrb, "|b", &inherit);
+ ary = mrb_ary_new(mrb);
+ while (c) {
+ if (c->iv) {
+ iv_foreach(mrb, c->iv, const_i, &ary);
+ }
+ if (!inherit) break;
+ c = c->super;
+ if (c == mrb->object_class) break;
+ }
+ return ary;
+}
+
+MRB_API mrb_value
+mrb_gv_get(mrb_state *mrb, mrb_sym sym)
+{
+ mrb_value v;
+
+ if (!mrb->globals) {
+ return mrb_nil_value();
+ }
+ if (iv_get(mrb, mrb->globals, sym, &v))
+ return v;
+ return mrb_nil_value();
+}
+
+MRB_API void
+mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
+{
+ iv_tbl *t;
+
+ if (!mrb->globals) {
+ t = mrb->globals = iv_new(mrb);
+ }
+ else {
+ t = mrb->globals;
+ }
+ iv_put(mrb, t, sym, v);
+}
+
+MRB_API void
+mrb_gv_remove(mrb_state *mrb, mrb_sym sym)
+{
+ if (!mrb->globals) {
+ return;
+ }
+ iv_del(mrb, mrb->globals, sym, NULL);
+}
+
+static int
+gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ mrb_value ary;
+
+ ary = *(mrb_value*)p;
+ mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
+ return 0;
+}
+
+/* 15.3.1.2.4 */
+/* 15.3.1.3.14 */
+/*
+ * call-seq:
+ * global_variables -> array
+ *
+ * Returns an array of the names of global variables.
+ *
+ * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
+ */
+mrb_value
+mrb_f_global_variables(mrb_state *mrb, mrb_value self)
+{
+ iv_tbl *t = mrb->globals;
+ mrb_value ary = mrb_ary_new(mrb);
+ size_t i;
+ char buf[3];
+
+ if (t) {
+ iv_foreach(mrb, t, gv_i, &ary);
+ }
+ buf[0] = '$';
+ buf[2] = 0;
+ for (i = 1; i <= 9; ++i) {
+ buf[1] = (char)(i + '0');
+ mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf, 2)));
+ }
+ return ary;
+}
+
+static mrb_bool
+mrb_const_defined_0(mrb_state *mrb, mrb_value mod, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
+{
+ struct RClass *klass = mrb_class_ptr(mod);
+ struct RClass *tmp;
+ mrb_bool mod_retry = 0;
+
+ tmp = klass;
+retry:
+ while (tmp) {
+ if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) {
+ return TRUE;
+ }
+ if (!recurse && (klass != mrb->object_class)) break;
+ tmp = tmp->super;
+ }
+ if (!exclude && !mod_retry && (klass->tt == MRB_TT_MODULE)) {
+ mod_retry = 1;
+ tmp = mrb->object_class;
+ goto retry;
+ }
+ return FALSE;
+}
+
+MRB_API mrb_bool
+mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym id)
+{
+ return mrb_const_defined_0(mrb, mod, id, TRUE, TRUE);
+}
+
+MRB_API mrb_bool
+mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id)
+{
+ return mrb_const_defined_0(mrb, mod, id, TRUE, FALSE);
+}
+
+MRB_API mrb_value
+mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id)
+{
+ return mrb_iv_get(mrb, obj, id);
+}
+
+struct csym_arg {
+ struct RClass *c;
+ mrb_sym sym;
+};
+
+static int
+csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
+{
+ struct csym_arg *a = (struct csym_arg*)p;
+ struct RClass *c = a->c;
+
+ if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
+ a->sym = sym;
+ return 1; /* stop iteration */
+ }
+ return 0;
+}
+
+static mrb_sym
+find_class_sym(mrb_state *mrb, struct RClass *outer, struct RClass *c)
+{
+ struct csym_arg arg;
+
+ if (!outer) return 0;
+ arg.c = c;
+ arg.sym = 0;
+ iv_foreach(mrb, outer->iv, csym_i, &arg);
+ return arg.sym;
+}
+
+mrb_value
+mrb_class_find_path(mrb_state *mrb, struct RClass *c)
+{
+ mrb_value outer, path;
+ mrb_sym name;
+ const char *str;
+ mrb_int len;
+ mrb_sym osym = mrb_intern_lit(mrb, "__outer__");
+
+ outer = mrb_obj_iv_get(mrb, (struct RObject*)c, osym);
+ if (mrb_nil_p(outer)) return outer;
+ name = find_class_sym(mrb, mrb_class_ptr(outer), c);
+ if (name == 0) return mrb_nil_value();
+ str = mrb_class_name(mrb, mrb_class_ptr(outer));
+ path = mrb_str_new_capa(mrb, 40);
+ mrb_str_cat_cstr(mrb, path, str);
+ mrb_str_cat_cstr(mrb, path, "::");
+
+ str = mrb_sym2name_len(mrb, name, &len);
+ mrb_str_cat(mrb, path, str, len);
+ iv_del(mrb, c->iv, osym, NULL);
+ iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path);
+ return path;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/version.c b/web/server/h2o/libh2o/deps/mruby/src/version.c
new file mode 100644
index 00000000..350bc167
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/version.c
@@ -0,0 +1,17 @@
+#include <mruby.h>
+#include <mruby/variable.h>
+
+void
+mrb_init_version(mrb_state* mrb)
+{
+ mrb_value mruby_version = mrb_str_new_lit(mrb, MRUBY_VERSION);
+
+ mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION));
+ mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE));
+ mrb_define_global_const(mrb, "RUBY_ENGINE_VERSION", mruby_version);
+ mrb_define_global_const(mrb, "MRUBY_VERSION", mruby_version);
+ mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO));
+ mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE));
+ mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION));
+ mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT));
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/src/vm.c b/web/server/h2o/libh2o/deps/mruby/src/vm.c
new file mode 100644
index 00000000..f413211e
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/src/vm.c
@@ -0,0 +1,2909 @@
+/*
+** vm.c - virtual machine for mruby
+**
+** See Copyright Notice in mruby.h
+*/
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <math.h>
+#include <mruby.h>
+#include <mruby/array.h>
+#include <mruby/class.h>
+#include <mruby/hash.h>
+#include <mruby/irep.h>
+#include <mruby/numeric.h>
+#include <mruby/proc.h>
+#include <mruby/range.h>
+#include <mruby/string.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
+#include <mruby/opcode.h>
+#include "value_array.h"
+#include <mruby/throw.h>
+
+#ifdef MRB_DISABLE_STDIO
+#if defined(__cplusplus)
+extern "C" {
+#endif
+void abort(void);
+#if defined(__cplusplus)
+} /* extern "C" { */
+#endif
+#endif
+
+#define STACK_INIT_SIZE 128
+#define CALLINFO_INIT_SIZE 32
+
+#ifndef ENSURE_STACK_INIT_SIZE
+#define ENSURE_STACK_INIT_SIZE 16
+#endif
+
+#ifndef RESCUE_STACK_INIT_SIZE
+#define RESCUE_STACK_INIT_SIZE 16
+#endif
+
+/* Define amount of linear stack growth. */
+#ifndef MRB_STACK_GROWTH
+#define MRB_STACK_GROWTH 128
+#endif
+
+/* Maximum mrb_funcall() depth. Should be set lower on memory constrained systems. */
+#ifndef MRB_FUNCALL_DEPTH_MAX
+#define MRB_FUNCALL_DEPTH_MAX 512
+#endif
+
+/* Maximum stack depth. Should be set lower on memory constrained systems.
+The value below allows about 60000 recursive calls in the simplest case. */
+#ifndef MRB_STACK_MAX
+#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH)
+#endif
+
+#ifdef VM_DEBUG
+# define DEBUG(x) (x)
+#else
+# define DEBUG(x)
+#endif
+
+
+#ifndef MRB_GC_FIXED_ARENA
+static void
+mrb_gc_arena_shrink(mrb_state *mrb, int idx)
+{
+ mrb_gc *gc = &mrb->gc;
+ int capa = gc->arena_capa;
+
+ if (idx < capa / 4) {
+ capa >>= 2;
+ if (capa < MRB_GC_ARENA_SIZE) {
+ capa = MRB_GC_ARENA_SIZE;
+ }
+ if (capa != gc->arena_capa) {
+ gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
+ gc->arena_capa = capa;
+ }
+ }
+}
+#else
+#define mrb_gc_arena_shrink(mrb,idx)
+#endif
+
+#define CALL_MAXARGS 127
+
+void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
+
+static inline void
+stack_clear(mrb_value *from, size_t count)
+{
+#ifndef MRB_NAN_BOXING
+ const mrb_value mrb_value_zero = { { 0 } };
+
+ while (count-- > 0) {
+ *from++ = mrb_value_zero;
+ }
+#else
+ while (count-- > 0) {
+ SET_NIL_VALUE(*from);
+ from++;
+ }
+#endif
+}
+
+static inline void
+stack_copy(mrb_value *dst, const mrb_value *src, size_t size)
+{
+ while (size-- > 0) {
+ *dst++ = *src++;
+ }
+}
+
+static void
+stack_init(mrb_state *mrb)
+{
+ struct mrb_context *c = mrb->c;
+
+ /* mrb_assert(mrb->stack == NULL); */
+ c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
+ c->stend = c->stbase + STACK_INIT_SIZE;
+ c->stack = c->stbase;
+
+ /* mrb_assert(ci == NULL); */
+ c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
+ c->ciend = c->cibase + CALLINFO_INIT_SIZE;
+ c->ci = c->cibase;
+ c->ci->target_class = mrb->object_class;
+ c->ci->stackent = c->stack;
+}
+
+static inline void
+envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t size)
+{
+ mrb_callinfo *ci = mrb->c->cibase;
+
+ if (newbase == oldbase) return;
+ while (ci <= mrb->c->ci) {
+ struct REnv *e = ci->env;
+ mrb_value *st;
+
+ if (e && MRB_ENV_STACK_SHARED_P(e) &&
+ (st = e->stack) && oldbase <= st && st < oldbase+size) {
+ ptrdiff_t off = e->stack - oldbase;
+
+ e->stack = newbase + off;
+ }
+ ci->stackent = newbase + (ci->stackent - oldbase);
+ ci++;
+ }
+}
+
+/** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */
+
+static void
+stack_extend_alloc(mrb_state *mrb, int room)
+{
+ mrb_value *oldbase = mrb->c->stbase;
+ mrb_value *newstack;
+ size_t oldsize = mrb->c->stend - mrb->c->stbase;
+ size_t size = oldsize;
+ size_t off = mrb->c->stack - mrb->c->stbase;
+
+ if (off > size) size = off;
+#ifdef MRB_STACK_EXTEND_DOUBLING
+ if (room <= size)
+ size *= 2;
+ else
+ size += room;
+#else
+ /* Use linear stack growth.
+ It is slightly slower than doubling the stack space,
+ but it saves memory on small devices. */
+ if (room <= MRB_STACK_GROWTH)
+ size += MRB_STACK_GROWTH;
+ else
+ size += room;
+#endif
+
+ newstack = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
+ if (newstack == NULL) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
+ }
+ stack_clear(&(newstack[oldsize]), size - oldsize);
+ envadjust(mrb, oldbase, newstack, size);
+ mrb->c->stbase = newstack;
+ mrb->c->stack = mrb->c->stbase + off;
+ mrb->c->stend = mrb->c->stbase + size;
+
+ /* Raise an exception if the new stack size will be too large,
+ to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
+ if (size > MRB_STACK_MAX) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
+ }
+}
+
+static inline void
+stack_extend(mrb_state *mrb, int room)
+{
+ if (mrb->c->stack + room >= mrb->c->stend) {
+ stack_extend_alloc(mrb, room);
+ }
+}
+
+static inline struct REnv*
+uvenv(mrb_state *mrb, int up)
+{
+ struct REnv *e = mrb->c->ci->proc->env;
+
+ while (up--) {
+ if (!e) return NULL;
+ e = (struct REnv*)e->c;
+ }
+ return e;
+}
+
+static inline mrb_bool
+is_strict(mrb_state *mrb, struct REnv *e)
+{
+ ptrdiff_t cioff = e->cioff;
+
+ if (MRB_ENV_STACK_SHARED_P(e) && e->cxt.c->cibase[cioff].proc &&
+ MRB_PROC_STRICT_P(e->cxt.c->cibase[cioff].proc)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static inline struct REnv*
+top_env(mrb_state *mrb, struct RProc *proc)
+{
+ struct REnv *e = proc->env;
+
+ if (is_strict(mrb, e)) return e;
+ while (e->c) {
+ e = (struct REnv*)e->c;
+ if (is_strict(mrb, e)) return e;
+ }
+ return e;
+}
+
+#define CI_ACC_SKIP -1
+#define CI_ACC_DIRECT -2
+#define CI_ACC_RESUMED -3
+
+static inline mrb_callinfo*
+cipush(mrb_state *mrb)
+{
+ struct mrb_context *c = mrb->c;
+ static const mrb_callinfo ci_zero = { 0 };
+ mrb_callinfo *ci = c->ci;
+
+ int ridx = ci->ridx;
+
+ if (ci + 1 == c->ciend) {
+ ptrdiff_t size = ci - c->cibase;
+
+ c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2);
+ c->ci = c->cibase + size;
+ c->ciend = c->cibase + size * 2;
+ }
+ ci = ++c->ci;
+ *ci = ci_zero;
+ ci->epos = mrb->c->eidx;
+ ci->ridx = ridx;
+
+ return ci;
+}
+
+MRB_API void
+mrb_env_unshare(mrb_state *mrb, struct REnv *e)
+{
+ if (e == NULL) return;
+ else {
+ size_t len = (size_t)MRB_ENV_STACK_LEN(e);
+ ptrdiff_t cioff = e->cioff;
+ mrb_value *p;
+
+ if (!MRB_ENV_STACK_SHARED_P(e)) return;
+ if (e->cxt.c != mrb->c) return;
+ if (e->cioff == 0 && e->cxt.c == mrb->root_c) return;
+ MRB_ENV_UNSHARE_STACK(e);
+ if (!e->c) {
+ /* save block argument position (negated) */
+ e->cioff = -e->cxt.c->cibase[cioff].argc-1;
+ if (e->cioff == 0) e->cioff = -2; /* blkarg position for vararg (1:args, 2:blk) */
+ }
+ e->cxt.mid = e->cxt.c->cibase[cioff].mid;
+ p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
+ if (len > 0) {
+ stack_copy(p, e->stack, len);
+ }
+ e->stack = p;
+ mrb_write_barrier(mrb, (struct RBasic *)e);
+ }
+}
+
+static inline void
+cipop(mrb_state *mrb)
+{
+ struct mrb_context *c = mrb->c;
+ struct REnv *env = c->ci->env;
+
+ c->ci--;
+ mrb_env_unshare(mrb, env);
+}
+
+void mrb_exc_set(mrb_state *mrb, mrb_value exc);
+
+static void
+ecall(mrb_state *mrb, int i)
+{
+ struct RProc *p;
+ mrb_callinfo *ci = mrb->c->ci;
+ mrb_value *self = mrb->c->stack;
+ struct RObject *exc;
+ ptrdiff_t cioff;
+ int ai = mrb_gc_arena_save(mrb);
+
+ if (i<0) return;
+ if (ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
+ }
+ p = mrb->c->ensure[i];
+ if (!p) return;
+ mrb->c->ensure[i] = NULL;
+ cioff = ci - mrb->c->cibase;
+ ci = cipush(mrb);
+ ci->stackent = mrb->c->stack;
+ ci->mid = ci[-1].mid;
+ ci->acc = CI_ACC_SKIP;
+ ci->argc = 0;
+ ci->proc = p;
+ ci->nregs = p->body.irep->nregs;
+ ci->target_class = p->target_class;
+ mrb->c->stack = mrb->c->stack + ci[-1].nregs;
+ exc = mrb->exc; mrb->exc = 0;
+ if (exc) {
+ mrb_gc_protect(mrb, mrb_obj_value(exc));
+ }
+ mrb_run(mrb, p, *self);
+ mrb->c->ci = mrb->c->cibase + cioff;
+ if (!mrb->exc) mrb->exc = exc;
+ mrb_gc_arena_restore(mrb, ai);
+}
+
+#ifndef MRB_FUNCALL_ARGC_MAX
+#define MRB_FUNCALL_ARGC_MAX 16
+#endif
+
+MRB_API mrb_value
+mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...)
+{
+ mrb_value argv[MRB_FUNCALL_ARGC_MAX];
+ va_list ap;
+ mrb_int i;
+ mrb_sym mid = mrb_intern_cstr(mrb, name);
+
+ if (argc > MRB_FUNCALL_ARGC_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")");
+ }
+
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++) {
+ argv[i] = va_arg(ap, mrb_value);
+ }
+ va_end(ap);
+ return mrb_funcall_argv(mrb, self, mid, argc, argv);
+}
+
+MRB_API mrb_value
+mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
+{
+ mrb_value val;
+
+ if (!mrb->jmp) {
+ struct mrb_jmpbuf c_jmp;
+ ptrdiff_t nth_ci = mrb->c->ci - mrb->c->cibase;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ /* recursive call */
+ val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
+ mrb->jmp = 0;
+ }
+ MRB_CATCH(&c_jmp) { /* error */
+ while (nth_ci < (mrb->c->ci - mrb->c->cibase)) {
+ mrb->c->stack = mrb->c->ci->stackent;
+ cipop(mrb);
+ }
+ mrb->jmp = 0;
+ val = mrb_obj_value(mrb->exc);
+ }
+ MRB_END_EXC(&c_jmp);
+ mrb->jmp = 0;
+ }
+ else {
+ struct RProc *p;
+ struct RClass *c;
+ mrb_callinfo *ci;
+ int n;
+ ptrdiff_t voff = -1;
+
+ if (!mrb->c->stack) {
+ stack_init(mrb);
+ }
+ n = mrb->c->ci->nregs;
+ if (argc < 0) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
+ }
+ c = mrb_class(mrb, self);
+ p = mrb_method_search_vm(mrb, &c, mid);
+ if (!p) {
+ mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
+ mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
+ p = mrb_method_search_vm(mrb, &c, missing);
+ if (!p) {
+ mrb_method_missing(mrb, mid, self, args);
+ }
+ mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
+ stack_extend(mrb, n+2);
+ mrb->c->stack[n+1] = args;
+ argc = -1;
+ }
+ if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
+ }
+ ci = cipush(mrb);
+ ci->mid = mid;
+ ci->proc = p;
+ ci->stackent = mrb->c->stack;
+ ci->argc = argc;
+ ci->target_class = c;
+ mrb->c->stack = mrb->c->stack + n;
+ if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
+ voff = argv - mrb->c->stbase;
+ }
+ if (MRB_PROC_CFUNC_P(p)) {
+ ci->nregs = argc + 2;
+ stack_extend(mrb, ci->nregs);
+ }
+ else if (argc >= CALL_MAXARGS) {
+ mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
+ stack_extend(mrb, ci->nregs);
+ mrb->c->stack[1] = args;
+ ci->argc = -1;
+ argc = 1;
+ }
+ else {
+ if (argc < 0) argc = 1;
+ ci->nregs = p->body.irep->nregs + argc;
+ stack_extend(mrb, ci->nregs);
+ }
+ if (voff >= 0) {
+ argv = mrb->c->stbase + voff;
+ }
+ mrb->c->stack[0] = self;
+ if (ci->argc > 0) {
+ stack_copy(mrb->c->stack+1, argv, argc);
+ }
+ mrb->c->stack[argc+1] = blk;
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ int ai = mrb_gc_arena_save(mrb);
+
+ ci->acc = CI_ACC_DIRECT;
+ val = p->body.func(mrb, self);
+ mrb->c->stack = mrb->c->ci->stackent;
+ cipop(mrb);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ else {
+ ci->acc = CI_ACC_SKIP;
+ val = mrb_run(mrb, p, self);
+ }
+ }
+ mrb_gc_protect(mrb, val);
+ return val;
+}
+
+MRB_API mrb_value
+mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv)
+{
+ return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value());
+}
+
+mrb_value
+mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+
+ mrb->c->stack[0] = self;
+ ci->proc = p;
+ ci->target_class = p->target_class;
+ if (MRB_PROC_CFUNC_P(p)) {
+ return p->body.func(mrb, self);
+ }
+ ci->nregs = p->body.irep->nregs;
+ stack_extend(mrb, (ci->argc < 0 && ci->nregs < 3) ? 3 : ci->nregs);
+
+ ci = cipush(mrb);
+ ci->nregs = 0;
+ ci->target_class = 0;
+ ci->pc = p->body.irep->iseq;
+ ci->stackent = mrb->c->stack;
+ ci->acc = 0;
+
+ return self;
+}
+
+/* 15.3.1.3.4 */
+/* 15.3.1.3.44 */
+/*
+ * call-seq:
+ * obj.send(symbol [, args...]) -> obj
+ * obj.__send__(symbol [, args...]) -> obj
+ *
+ * Invokes the method identified by _symbol_, passing it any
+ * arguments specified. You can use <code>__send__</code> if the name
+ * +send+ clashes with an existing method in _obj_.
+ *
+ * class Klass
+ * def hello(*args)
+ * "Hello " + args.join(' ')
+ * end
+ * end
+ * k = Klass.new
+ * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
+ */
+MRB_API mrb_value
+mrb_f_send(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym name;
+ mrb_value block, *argv, *regs;
+ mrb_int argc, i, len;
+ struct RProc *p;
+ struct RClass *c;
+ mrb_callinfo *ci;
+
+ mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
+ ci = mrb->c->ci;
+ if (ci->acc < 0) {
+ funcall:
+ return mrb_funcall_with_block(mrb, self, name, argc, argv, block);
+ }
+
+ c = mrb_class(mrb, self);
+ p = mrb_method_search_vm(mrb, &c, name);
+
+ if (!p) { /* call method_mising */
+ goto funcall;
+ }
+
+ ci->mid = name;
+ ci->target_class = c;
+ regs = mrb->c->stack+1;
+ /* remove first symbol from arguments */
+ if (ci->argc >= 0) {
+ for (i=0,len=ci->argc; i<len; i++) {
+ regs[i] = regs[i+1];
+ }
+ ci->argc--;
+ }
+ else { /* variable length arguments */
+ mrb_ary_shift(mrb, regs[0]);
+ }
+
+ return mrb_exec_irep(mrb, self, p);
+}
+
+static mrb_value
+eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
+{
+ struct RProc *p;
+ mrb_callinfo *ci;
+
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ ci = mrb->c->ci;
+ if (ci->acc == CI_ACC_DIRECT) {
+ ci->target_class = c;
+ return mrb_yield_cont(mrb, blk, self, 1, &self);
+ }
+ ci->target_class = c;
+ p = mrb_proc_ptr(blk);
+ ci->proc = p;
+ ci->argc = 1;
+ ci->mid = ci[-1].mid;
+ if (MRB_PROC_CFUNC_P(p)) {
+ stack_extend(mrb, 3);
+ mrb->c->stack[0] = self;
+ mrb->c->stack[1] = self;
+ mrb->c->stack[2] = mrb_nil_value();
+ return p->body.func(mrb, self);
+ }
+ ci->nregs = p->body.irep->nregs;
+ stack_extend(mrb, (ci->nregs < 3) ? 3 : ci->nregs);
+ mrb->c->stack[0] = self;
+ mrb->c->stack[1] = self;
+ mrb->c->stack[2] = mrb_nil_value();
+ ci = cipush(mrb);
+ ci->nregs = 0;
+ ci->target_class = 0;
+ ci->pc = p->body.irep->iseq;
+ ci->stackent = mrb->c->stack;
+ ci->acc = 0;
+
+ return self;
+}
+
+/* 15.2.2.4.35 */
+/*
+ * call-seq:
+ * mod.class_eval {| | block } -> obj
+ * mod.module_eval {| | block } -> obj
+ *
+ * Evaluates block in the context of _mod_. This can
+ * be used to add methods to a class. <code>module_eval</code> returns
+ * the result of evaluating its argument.
+ */
+mrb_value
+mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value a, b;
+
+ if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
+ }
+ return eval_under(mrb, mod, b, mrb_class_ptr(mod));
+}
+
+/* 15.3.1.3.18 */
+/*
+ * call-seq:
+ * obj.instance_eval {| | block } -> obj
+ *
+ * Evaluates the given block,within the context of the receiver (_obj_).
+ * In order to set the context, the variable +self+ is set to _obj_ while
+ * the code is executing, giving the code access to _obj_'s
+ * instance variables. In the version of <code>instance_eval</code>
+ * that takes a +String+, the optional second and third
+ * parameters supply a filename and starting line number that are used
+ * when reporting compilation errors.
+ *
+ * class KlassWithSecret
+ * def initialize
+ * @secret = 99
+ * end
+ * end
+ * k = KlassWithSecret.new
+ * k.instance_eval { @secret } #=> 99
+ */
+mrb_value
+mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
+{
+ mrb_value a, b;
+ mrb_value cv;
+ struct RClass *c;
+
+ if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
+ }
+ switch (mrb_type(self)) {
+ case MRB_TT_SYMBOL:
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ c = 0;
+ break;
+ default:
+ cv = mrb_singleton_class(mrb, self);
+ c = mrb_class_ptr(cv);
+ break;
+ }
+ return eval_under(mrb, self, b, c);
+}
+
+MRB_API mrb_value
+mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
+{
+ struct RProc *p;
+ mrb_sym mid = mrb->c->ci->mid;
+ mrb_callinfo *ci;
+ int n = mrb->c->ci->nregs;
+ mrb_value val;
+
+ if (mrb_nil_p(b)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ if (mrb->c->ci - mrb->c->cibase > MRB_FUNCALL_DEPTH_MAX) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
+ }
+ p = mrb_proc_ptr(b);
+ ci = cipush(mrb);
+ ci->mid = mid;
+ ci->proc = p;
+ ci->stackent = mrb->c->stack;
+ ci->argc = argc;
+ ci->target_class = c;
+ ci->acc = CI_ACC_SKIP;
+ mrb->c->stack = mrb->c->stack + n;
+ ci->nregs = MRB_PROC_CFUNC_P(p) ? argc+2 : p->body.irep->nregs;
+ stack_extend(mrb, ci->nregs);
+
+ mrb->c->stack[0] = self;
+ if (argc > 0) {
+ stack_copy(mrb->c->stack+1, argv, argc);
+ }
+ mrb->c->stack[argc+1] = mrb_nil_value();
+
+ if (MRB_PROC_CFUNC_P(p)) {
+ val = p->body.func(mrb, self);
+ mrb->c->stack = mrb->c->ci->stackent;
+ }
+ else {
+ ptrdiff_t cioff = mrb->c->ci - mrb->c->cibase;
+ val = mrb_run(mrb, p, self);
+ mrb->c->ci = mrb->c->cibase + cioff;
+ }
+ cipop(mrb);
+ return val;
+}
+
+MRB_API mrb_value
+mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
+{
+ struct RProc *p = mrb_proc_ptr(b);
+
+ return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class);
+}
+
+MRB_API mrb_value
+mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
+{
+ struct RProc *p = mrb_proc_ptr(b);
+
+ return mrb_yield_with_class(mrb, b, 1, &arg, p->env->stack[0], p->target_class);
+}
+
+mrb_value
+mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb_value *argv)
+{
+ struct RProc *p;
+ mrb_callinfo *ci;
+
+ if (mrb_nil_p(b)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ if (mrb_type(b) != MRB_TT_PROC) {
+ mrb_raise(mrb, E_TYPE_ERROR, "not a block");
+ }
+
+ p = mrb_proc_ptr(b);
+ ci = mrb->c->ci;
+
+ stack_extend(mrb, 3);
+ mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv);
+ mrb->c->stack[2] = mrb_nil_value();
+ ci->argc = -1;
+ return mrb_exec_irep(mrb, self, p);
+}
+
+mrb_value
+mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
+{
+ struct RProc *proc;
+ mrb_irep *irep;
+ mrb_value ary;
+ struct RClass *c;
+
+ mrb_get_args(mrb, "");
+ ary = mrb_ary_new(mrb);
+ proc = mrb->c->ci[-1].proc; /* callee proc */
+ c = proc->target_class;
+ mrb_ary_push(mrb, ary, mrb_obj_value(c));
+ mrb_assert(!MRB_PROC_CFUNC_P(proc));
+ irep = proc->body.irep;
+ while (irep) {
+ if (irep->target_class && irep->target_class != c) {
+ c = irep->target_class;
+ mrb_ary_push(mrb, ary, mrb_obj_value(c));
+ }
+ irep = irep->outer;
+ }
+ return ary;
+}
+
+static struct RBreak*
+break_new(mrb_state *mrb, struct RProc *p, mrb_value val)
+{
+ struct RBreak *brk;
+
+ brk = (struct RBreak*)mrb_obj_alloc(mrb, MRB_TT_BREAK, NULL);
+ brk->iv = NULL;
+ brk->proc = p;
+ brk->val = val;
+
+ return brk;
+}
+
+typedef enum {
+ LOCALJUMP_ERROR_RETURN = 0,
+ LOCALJUMP_ERROR_BREAK = 1,
+ LOCALJUMP_ERROR_YIELD = 2
+} localjump_error_kind;
+
+static void
+localjump_error(mrb_state *mrb, localjump_error_kind kind)
+{
+ char kind_str[3][7] = { "return", "break", "yield" };
+ char kind_str_len[] = { 6, 5, 5 };
+ static const char lead[] = "unexpected ";
+ mrb_value msg;
+ mrb_value exc;
+
+ msg = mrb_str_new_capa(mrb, sizeof(lead) + 7);
+ mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1);
+ mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]);
+ exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
+ mrb_exc_set(mrb, exc);
+}
+
+static void
+argnum_error(mrb_state *mrb, mrb_int num)
+{
+ mrb_value exc;
+ mrb_value str;
+ mrb_int argc = mrb->c->ci->argc;
+
+ if (argc < 0) {
+ mrb_value args = mrb->c->stack[1];
+ if (mrb_array_p(args)) {
+ argc = RARRAY_LEN(args);
+ }
+ }
+ if (mrb->c->ci->mid) {
+ str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)",
+ mrb_sym2str(mrb, mrb->c->ci->mid),
+ mrb_fixnum_value(argc), mrb_fixnum_value(num));
+ }
+ else {
+ str = mrb_format(mrb, "wrong number of arguments (%S for %S)",
+ mrb_fixnum_value(argc), mrb_fixnum_value(num));
+ }
+ exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str);
+ mrb_exc_set(mrb, exc);
+}
+
+void
+irep_uplink(mrb_state *mrb, mrb_irep *outer, mrb_irep *irep)
+{
+ if (irep->outer != outer) {
+ if (irep->outer) {
+ mrb_irep_decref(mrb, irep->outer);
+ }
+ irep->outer = outer;
+ mrb_irep_incref(mrb, outer);
+ }
+}
+
+#define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc;
+#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0;
+#ifdef MRB_ENABLE_DEBUG_HOOK
+#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
+#else
+#define CODE_FETCH_HOOK(mrb, irep, pc, regs)
+#endif
+
+#ifdef MRB_BYTECODE_DECODE_OPTION
+#define BYTECODE_DECODER(x) ((mrb)->bytecode_decoder)?(mrb)->bytecode_decoder((mrb), (x)):(x)
+#else
+#define BYTECODE_DECODER(x) (x)
+#endif
+
+
+#if defined __GNUC__ || defined __clang__ || defined __INTEL_COMPILER
+#define DIRECT_THREADED
+#endif
+
+#ifndef DIRECT_THREADED
+
+#define INIT_DISPATCH for (;;) { i = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) {
+#define CASE(op) case op:
+#define NEXT pc++; break
+#define JUMP break
+#define END_DISPATCH }}
+
+#else
+
+#define INIT_DISPATCH JUMP; return mrb_nil_value();
+#define CASE(op) L_ ## op:
+#define NEXT i=BYTECODE_DECODER(*++pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
+#define JUMP i=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)]
+
+#define END_DISPATCH
+
+#endif
+
+MRB_API mrb_value
+mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
+{
+ mrb_irep *irep = proc->body.irep;
+ mrb_value result;
+ struct mrb_context *c = mrb->c;
+ ptrdiff_t cioff = c->ci - c->cibase;
+ unsigned int nregs = irep->nregs;
+
+ if (!c->stack) {
+ stack_init(mrb);
+ }
+ if (stack_keep > nregs)
+ nregs = stack_keep;
+ stack_extend(mrb, nregs);
+ stack_clear(c->stack + stack_keep, nregs - stack_keep);
+ c->stack[0] = self;
+ result = mrb_vm_exec(mrb, proc, irep->iseq);
+ if (c->ci - c->cibase > cioff) {
+ c->ci = c->cibase + cioff;
+ }
+ if (mrb->c != c) {
+ if (mrb->c->fib) {
+ mrb_write_barrier(mrb, (struct RBasic*)mrb->c->fib);
+ }
+ mrb->c = c;
+ }
+ return result;
+}
+
+MRB_API mrb_value
+mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
+{
+ /* mrb_assert(mrb_proc_cfunc_p(proc)) */
+ mrb_irep *irep = proc->body.irep;
+ mrb_value *pool = irep->pool;
+ mrb_sym *syms = irep->syms;
+ mrb_code i;
+ int ai = mrb_gc_arena_save(mrb);
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+
+#ifdef DIRECT_THREADED
+ static void *optable[] = {
+ &&L_OP_NOP, &&L_OP_MOVE,
+ &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL,
+ &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF,
+ &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL,
+ &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV,
+ &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST,
+ &&L_OP_GETUPVAR, &&L_OP_SETUPVAR,
+ &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT,
+ &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP,
+ &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND,
+ &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER,
+ &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH,
+ &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV,
+ &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE,
+ &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST,
+ &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH,
+ &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS,
+ &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC,
+ &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS,
+ &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR,
+ };
+#endif
+
+ mrb_bool exc_catched = FALSE;
+RETRY_TRY_BLOCK:
+
+ MRB_TRY(&c_jmp) {
+
+ if (exc_catched) {
+ exc_catched = FALSE;
+ if (mrb->exc && mrb->exc->tt == MRB_TT_BREAK)
+ goto L_BREAK;
+ goto L_RAISE;
+ }
+ mrb->jmp = &c_jmp;
+ mrb->c->ci->proc = proc;
+ mrb->c->ci->nregs = irep->nregs;
+
+#define regs (mrb->c->stack)
+ INIT_DISPATCH {
+ CASE(OP_NOP) {
+ /* do nothing */
+ NEXT;
+ }
+
+ CASE(OP_MOVE) {
+ /* A B R(A) := R(B) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ regs[a] = regs[b];
+ NEXT;
+ }
+
+ CASE(OP_LOADL) {
+ /* A Bx R(A) := Pool(Bx) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+#ifdef MRB_WORD_BOXING
+ mrb_value val = pool[bx];
+ if (mrb_float_p(val)) {
+ val = mrb_float_value(mrb, mrb_float(val));
+ }
+ regs[a] = val;
+#else
+ regs[a] = pool[bx];
+#endif
+ NEXT;
+ }
+
+ CASE(OP_LOADI) {
+ /* A sBx R(A) := sBx */
+ SET_INT_VALUE(regs[GETARG_A(i)], GETARG_sBx(i));
+ NEXT;
+ }
+
+ CASE(OP_LOADSYM) {
+ /* A Bx R(A) := Syms(Bx) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ SET_SYM_VALUE(regs[a], syms[bx]);
+ NEXT;
+ }
+
+ CASE(OP_LOADSELF) {
+ /* A R(A) := self */
+ int a = GETARG_A(i);
+ regs[a] = regs[0];
+ NEXT;
+ }
+
+ CASE(OP_LOADT) {
+ /* A R(A) := true */
+ int a = GETARG_A(i);
+ SET_TRUE_VALUE(regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_LOADF) {
+ /* A R(A) := false */
+ int a = GETARG_A(i);
+ SET_FALSE_VALUE(regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETGLOBAL) {
+ /* A Bx R(A) := getglobal(Syms(Bx)) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_value val = mrb_gv_get(mrb, syms[bx]);
+ regs[a] = val;
+ NEXT;
+ }
+
+ CASE(OP_SETGLOBAL) {
+ /* A Bx setglobal(Syms(Bx), R(A)) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_gv_set(mrb, syms[bx], regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETSPECIAL) {
+ /* A Bx R(A) := Special[Bx] */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_value val = mrb_vm_special_get(mrb, bx);
+ regs[a] = val;
+ NEXT;
+ }
+
+ CASE(OP_SETSPECIAL) {
+ /* A Bx Special[Bx] := R(A) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_vm_special_set(mrb, bx, regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETIV) {
+ /* A Bx R(A) := ivget(Bx) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_value val = mrb_vm_iv_get(mrb, syms[bx]);
+ regs[a] = val;
+ NEXT;
+ }
+
+ CASE(OP_SETIV) {
+ /* A Bx ivset(Syms(Bx),R(A)) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_vm_iv_set(mrb, syms[bx], regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETCV) {
+ /* A Bx R(A) := cvget(Syms(Bx)) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_value val;
+ ERR_PC_SET(mrb, pc);
+ val = mrb_vm_cv_get(mrb, syms[bx]);
+ ERR_PC_CLR(mrb);
+ regs[a] = val;
+ NEXT;
+ }
+
+ CASE(OP_SETCV) {
+ /* A Bx cvset(Syms(Bx),R(A)) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_vm_cv_set(mrb, syms[bx], regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETCONST) {
+ /* A Bx R(A) := constget(Syms(Bx)) */
+ mrb_value val;
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_sym sym = syms[bx];
+
+ ERR_PC_SET(mrb, pc);
+ val = mrb_vm_const_get(mrb, sym);
+ ERR_PC_CLR(mrb);
+ regs[a] = val;
+ NEXT;
+ }
+
+ CASE(OP_SETCONST) {
+ /* A Bx constset(Syms(Bx),R(A)) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_vm_const_set(mrb, syms[bx], regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETMCNST) {
+ /* A Bx R(A) := R(A)::Syms(Bx) */
+ mrb_value val;
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+
+ ERR_PC_SET(mrb, pc);
+ val = mrb_const_get(mrb, regs[a], syms[bx]);
+ ERR_PC_CLR(mrb);
+ regs[a] = val;
+ NEXT;
+ }
+
+ CASE(OP_SETMCNST) {
+ /* A Bx R(A+1)::Syms(Bx) := R(A) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_const_set(mrb, regs[a+1], syms[bx], regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_GETUPVAR) {
+ /* A B C R(A) := uvget(B,C) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ mrb_value *regs_a = regs + a;
+ struct REnv *e = uvenv(mrb, c);
+
+ if (!e) {
+ *regs_a = mrb_nil_value();
+ }
+ else {
+ *regs_a = e->stack[b];
+ }
+ NEXT;
+ }
+
+ CASE(OP_SETUPVAR) {
+ /* A B C uvset(B,C,R(A)) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+
+ struct REnv *e = uvenv(mrb, c);
+
+ if (e) {
+ mrb_value *regs_a = regs + a;
+
+ if (b < MRB_ENV_STACK_LEN(e)) {
+ e->stack[b] = *regs_a;
+ mrb_write_barrier(mrb, (struct RBasic*)e);
+ }
+ }
+ NEXT;
+ }
+
+ CASE(OP_JMP) {
+ /* sBx pc+=sBx */
+ int sbx = GETARG_sBx(i);
+ pc += sbx;
+ JUMP;
+ }
+
+ CASE(OP_JMPIF) {
+ /* A sBx if R(A) pc+=sBx */
+ int a = GETARG_A(i);
+ int sbx = GETARG_sBx(i);
+ if (mrb_test(regs[a])) {
+ pc += sbx;
+ JUMP;
+ }
+ NEXT;
+ }
+
+ CASE(OP_JMPNOT) {
+ /* A sBx if !R(A) pc+=sBx */
+ int a = GETARG_A(i);
+ int sbx = GETARG_sBx(i);
+ if (!mrb_test(regs[a])) {
+ pc += sbx;
+ JUMP;
+ }
+ NEXT;
+ }
+
+ CASE(OP_ONERR) {
+ /* sBx pc+=sBx on exception */
+ int sbx = GETARG_sBx(i);
+ if (mrb->c->rsize <= mrb->c->ci->ridx) {
+ if (mrb->c->rsize == 0) mrb->c->rsize = RESCUE_STACK_INIT_SIZE;
+ else mrb->c->rsize *= 2;
+ mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize);
+ }
+ mrb->c->rescue[mrb->c->ci->ridx++] = pc + sbx;
+ NEXT;
+ }
+
+ CASE(OP_RESCUE) {
+ /* A B R(A) := exc; clear(exc); R(B) := matched (bool) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ mrb_value exc;
+
+ if (c == 0) {
+ exc = mrb_obj_value(mrb->exc);
+ mrb->exc = 0;
+ }
+ else { /* continued; exc taken from R(A) */
+ exc = regs[a];
+ }
+ if (b != 0) {
+ mrb_value e = regs[b];
+ struct RClass *ec;
+
+ switch (mrb_type(e)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ break;
+ default:
+ {
+ mrb_value exc;
+
+ exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR,
+ "class or module required for rescue clause");
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ }
+ ec = mrb_class_ptr(e);
+ regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec));
+ }
+ if (a != 0 && c == 0) {
+ regs[a] = exc;
+ }
+ NEXT;
+ }
+
+ CASE(OP_POPERR) {
+ /* A A.times{rescue_pop()} */
+ int a = GETARG_A(i);
+
+ mrb->c->ci->ridx -= a;
+ NEXT;
+ }
+
+ CASE(OP_RAISE) {
+ /* A raise(R(A)) */
+ int a = GETARG_A(i);
+
+ mrb_exc_set(mrb, regs[a]);
+ goto L_RAISE;
+ }
+
+ CASE(OP_EPUSH) {
+ /* Bx ensure_push(SEQ[Bx]) */
+ int bx = GETARG_Bx(i);
+ struct RProc *p;
+
+ p = mrb_closure_new(mrb, irep->reps[bx]);
+ /* push ensure_stack */
+ if (mrb->c->esize <= mrb->c->eidx+1) {
+ if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE;
+ else mrb->c->esize *= 2;
+ mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize);
+ }
+ mrb->c->ensure[mrb->c->eidx++] = p;
+ mrb->c->ensure[mrb->c->eidx] = NULL;
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_EPOP) {
+ /* A A.times{ensure_pop().call} */
+ int a = GETARG_A(i);
+ mrb_callinfo *ci = mrb->c->ci;
+ int n, epos = ci->epos;
+
+ for (n=0; n<a && mrb->c->eidx > epos; n++) {
+ ecall(mrb, --mrb->c->eidx);
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ NEXT;
+ }
+
+ CASE(OP_LOADNIL) {
+ /* A R(A) := nil */
+ int a = GETARG_A(i);
+
+ SET_NIL_VALUE(regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_SENDB) {
+ /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
+ /* fall through */
+ };
+
+ L_SEND:
+ CASE(OP_SEND) {
+ /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
+ int a = GETARG_A(i);
+ int n = GETARG_C(i);
+ int argc = (n == CALL_MAXARGS) ? -1 : n;
+ int bidx = (argc < 0) ? a+2 : a+n+1;
+ struct RProc *m;
+ struct RClass *c;
+ mrb_callinfo *ci = mrb->c->ci;
+ mrb_value recv, blk;
+ mrb_sym mid = syms[GETARG_B(i)];
+
+ mrb_assert(bidx < ci->nregs);
+
+ recv = regs[a];
+ if (GET_OPCODE(i) != OP_SENDB) {
+ SET_NIL_VALUE(regs[bidx]);
+ blk = regs[bidx];
+ }
+ else {
+ blk = regs[bidx];
+ if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
+ blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
+ /* The stack might have been reallocated during mrb_convert_type(),
+ see #3622 */
+ regs[bidx] = blk;
+ }
+ }
+ c = mrb_class(mrb, recv);
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (!m) {
+ mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
+ m = mrb_method_search_vm(mrb, &c, missing);
+ if (!m) {
+ mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1);
+ ERR_PC_SET(mrb, pc);
+ mrb_method_missing(mrb, mid, recv, args);
+ }
+ if (argc >= 0) {
+ if (a+2 >= irep->nregs) {
+ stack_extend(mrb, a+3);
+ }
+ regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1);
+ regs[a+2] = blk;
+ argc = -1;
+ }
+ mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(mid));
+ mid = missing;
+ }
+
+ /* push callinfo */
+ ci = cipush(mrb);
+ ci->mid = mid;
+ ci->proc = m;
+ ci->stackent = mrb->c->stack;
+ ci->target_class = c;
+ ci->argc = argc;
+
+ ci->pc = pc + 1;
+ ci->acc = a;
+
+ /* prepare stack */
+ mrb->c->stack += a;
+
+ if (MRB_PROC_CFUNC_P(m)) {
+ ci->nregs = (argc < 0) ? 3 : n+2;
+ recv = m->body.func(mrb, recv);
+ mrb_gc_arena_restore(mrb, ai);
+ mrb_gc_arena_shrink(mrb, ai);
+ if (mrb->exc) goto L_RAISE;
+ ci = mrb->c->ci;
+ if (GET_OPCODE(i) == OP_SENDB) {
+ if (mrb_type(blk) == MRB_TT_PROC) {
+ struct RProc *p = mrb_proc_ptr(blk);
+ if (p && !MRB_PROC_STRICT_P(p) && p->env == ci[-1].env) {
+ p->flags |= MRB_PROC_ORPHAN;
+ }
+ }
+ }
+ if (!ci->target_class) { /* return from context modifying method (resume/yield) */
+ if (ci->acc == CI_ACC_RESUMED) {
+ mrb->jmp = prev_jmp;
+ return recv;
+ }
+ else {
+ mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
+ proc = ci[-1].proc;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ }
+ }
+ mrb->c->stack[0] = recv;
+ /* pop stackpos */
+ mrb->c->stack = ci->stackent;
+ pc = ci->pc;
+ cipop(mrb);
+ JUMP;
+ }
+ else {
+ /* setup environment for calling method */
+ proc = mrb->c->ci->proc = m;
+ irep = m->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ ci->nregs = irep->nregs;
+ stack_extend(mrb, (argc < 0 && ci->nregs < 3) ? 3 : ci->nregs);
+ pc = irep->iseq;
+ JUMP;
+ }
+ }
+
+ CASE(OP_FSEND) {
+ /* A B C R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */
+ /* not implemented yet */
+ NEXT;
+ }
+
+ CASE(OP_CALL) {
+ /* A R(A) := self.call(frame.argc, frame.argv) */
+ mrb_callinfo *ci;
+ mrb_value recv = mrb->c->stack[0];
+ struct RProc *m = mrb_proc_ptr(recv);
+
+ /* replace callinfo */
+ ci = mrb->c->ci;
+ ci->target_class = m->target_class;
+ ci->proc = m;
+ if (m->env) {
+ mrb_sym mid;
+
+ if (MRB_ENV_STACK_SHARED_P(m->env)) {
+ mid = m->env->cxt.c->cibase[m->env->cioff].mid;
+ }
+ else {
+ mid = m->env->cxt.mid;
+ }
+ if (mid) ci->mid = mid;
+ if (!m->env->stack) {
+ m->env->stack = mrb->c->stack;
+ }
+ }
+
+ /* prepare stack */
+ if (MRB_PROC_CFUNC_P(m)) {
+ recv = m->body.func(mrb, recv);
+ mrb_gc_arena_restore(mrb, ai);
+ mrb_gc_arena_shrink(mrb, ai);
+ if (mrb->exc) goto L_RAISE;
+ /* pop stackpos */
+ ci = mrb->c->ci;
+ mrb->c->stack = ci->stackent;
+ regs[ci->acc] = recv;
+ pc = ci->pc;
+ cipop(mrb);
+ irep = mrb->c->ci->proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ JUMP;
+ }
+ else {
+ /* setup environment for calling method */
+ proc = m;
+ irep = m->body.irep;
+ if (!irep) {
+ mrb->c->stack[0] = mrb_nil_value();
+ goto L_RETURN;
+ }
+ pool = irep->pool;
+ syms = irep->syms;
+ ci->nregs = irep->nregs;
+ stack_extend(mrb, ci->nregs);
+ if (ci->argc < 0) {
+ if (irep->nregs > 3) {
+ stack_clear(regs+3, irep->nregs-3);
+ }
+ }
+ else if (ci->argc+2 < irep->nregs) {
+ stack_clear(regs+ci->argc+2, irep->nregs-ci->argc-2);
+ }
+ if (m->env) {
+ regs[0] = m->env->stack[0];
+ }
+ pc = irep->iseq;
+ JUMP;
+ }
+ }
+
+ CASE(OP_SUPER) {
+ /* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
+ int a = GETARG_A(i);
+ int n = GETARG_C(i);
+ int argc = (n == CALL_MAXARGS) ? -1 : n;
+ int bidx = (argc < 0) ? a+2 : a+n+1;
+ struct RProc *m;
+ struct RClass *c;
+ mrb_callinfo *ci = mrb->c->ci;
+ mrb_value recv, blk;
+ mrb_sym mid = ci->mid;
+
+ mrb_assert(bidx < ci->nregs);
+
+ if (mid == 0 || !ci->target_class) {
+ mrb_value exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ recv = regs[0];
+ blk = regs[bidx];
+ if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
+ blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
+ /* The stack or ci stack might have been reallocated during
+ mrb_convert_type(), see #3622 and #3784 */
+ regs[bidx] = blk;
+ ci = mrb->c->ci;
+ }
+ c = ci->target_class->super;
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (!m) {
+ mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
+ m = mrb_method_search_vm(mrb, &c, missing);
+ if (!m) {
+ mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1);
+ ERR_PC_SET(mrb, pc);
+ mrb_method_missing(mrb, mid, recv, args);
+ }
+ mid = missing;
+ if (argc >= 0) {
+ if (a+2 >= ci->nregs) {
+ stack_extend(mrb, a+3);
+ }
+ regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1);
+ regs[a+2] = blk;
+ argc = -1;
+ }
+ mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid));
+ }
+
+ /* push callinfo */
+ ci = cipush(mrb);
+ ci->mid = mid;
+ ci->proc = m;
+ ci->stackent = mrb->c->stack;
+ ci->target_class = c;
+ ci->pc = pc + 1;
+ ci->argc = argc;
+
+ /* prepare stack */
+ mrb->c->stack += a;
+ mrb->c->stack[0] = recv;
+
+ if (MRB_PROC_CFUNC_P(m)) {
+ mrb_value v;
+ ci->nregs = (argc < 0) ? 3 : n+2;
+ v = m->body.func(mrb, recv);
+ mrb_gc_arena_restore(mrb, ai);
+ if (mrb->exc) goto L_RAISE;
+ ci = mrb->c->ci;
+ if (!ci->target_class) { /* return from context modifying method (resume/yield) */
+ if (ci->acc == CI_ACC_RESUMED) {
+ mrb->jmp = prev_jmp;
+ return v;
+ }
+ else {
+ mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc));
+ proc = ci[-1].proc;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ }
+ }
+ mrb->c->stack[0] = v;
+ /* pop stackpos */
+ mrb->c->stack = ci->stackent;
+ pc = ci->pc;
+ cipop(mrb);
+ JUMP;
+ }
+ else {
+ /* fill callinfo */
+ ci->acc = a;
+
+ /* setup environment for calling method */
+ ci->proc = m;
+ irep = m->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ ci->nregs = irep->nregs;
+ stack_extend(mrb, (argc < 0 && ci->nregs < 3) ? 3 : ci->nregs);
+ pc = irep->iseq;
+ JUMP;
+ }
+ }
+
+ CASE(OP_ARGARY) {
+ /* A Bx R(A) := argument array (16=6:1:5:4) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ int m1 = (bx>>10)&0x3f;
+ int r = (bx>>9)&0x1;
+ int m2 = (bx>>4)&0x1f;
+ int lv = (bx>>0)&0xf;
+ mrb_value *stack;
+
+ if (mrb->c->ci->mid == 0 || mrb->c->ci->target_class == NULL) {
+ mrb_value exc;
+
+ L_NOSUPER:
+ exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method");
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ if (lv == 0) stack = regs + 1;
+ else {
+ struct REnv *e = uvenv(mrb, lv-1);
+ if (!e) goto L_NOSUPER;
+ if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+1)
+ goto L_NOSUPER;
+ stack = e->stack + 1;
+ }
+ if (r == 0) {
+ regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack);
+ }
+ else {
+ mrb_value *pp = NULL;
+ struct RArray *rest;
+ int len = 0;
+
+ if (mrb_array_p(stack[m1])) {
+ struct RArray *ary = mrb_ary_ptr(stack[m1]);
+
+ pp = ARY_PTR(ary);
+ len = ARY_LEN(ary);
+ }
+ regs[a] = mrb_ary_new_capa(mrb, m1+len+m2);
+ rest = mrb_ary_ptr(regs[a]);
+ if (m1 > 0) {
+ stack_copy(ARY_PTR(rest), stack, m1);
+ }
+ if (len > 0) {
+ stack_copy(ARY_PTR(rest)+m1, pp, len);
+ }
+ if (m2 > 0) {
+ stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2);
+ }
+ ARY_SET_LEN(rest, m1+len+m2);
+ }
+ regs[a+1] = stack[m1+r+m2];
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_ENTER) {
+ /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
+ /* number of optional arguments times OP_JMP should follow */
+ mrb_aspec ax = GETARG_Ax(i);
+ int m1 = MRB_ASPEC_REQ(ax);
+ int o = MRB_ASPEC_OPT(ax);
+ int r = MRB_ASPEC_REST(ax);
+ int m2 = MRB_ASPEC_POST(ax);
+ /* unused
+ int k = MRB_ASPEC_KEY(ax);
+ int kd = MRB_ASPEC_KDICT(ax);
+ int b = MRB_ASPEC_BLOCK(ax);
+ */
+ int argc = mrb->c->ci->argc;
+ mrb_value *argv = regs+1;
+ mrb_value *argv0 = argv;
+ int len = m1 + o + r + m2;
+ mrb_value *blk = &argv[argc < 0 ? 1 : argc];
+
+ if (argc < 0) {
+ struct RArray *ary = mrb_ary_ptr(regs[1]);
+ argv = ARY_PTR(ary);
+ argc = ARY_LEN(ary);
+ mrb_gc_protect(mrb, regs[1]);
+ }
+ if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) {
+ if (argc >= 0) {
+ if (argc < m1 + m2 || (r == 0 && argc > len)) {
+ argnum_error(mrb, m1+m2);
+ goto L_RAISE;
+ }
+ }
+ }
+ else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) {
+ mrb_gc_protect(mrb, argv[0]);
+ argc = RARRAY_LEN(argv[0]);
+ argv = RARRAY_PTR(argv[0]);
+ }
+ if (argc < len) {
+ int mlen = m2;
+ if (argc < m1+m2) {
+ if (m1 < argc)
+ mlen = argc - m1;
+ else
+ mlen = 0;
+ }
+ regs[len+1] = *blk; /* move block */
+ SET_NIL_VALUE(regs[argc+1]);
+ if (argv0 != argv) {
+ value_move(&regs[1], argv, argc-mlen); /* m1 + o */
+ }
+ if (argc < m1) {
+ stack_clear(&regs[argc+1], m1-argc);
+ }
+ if (mlen) {
+ value_move(&regs[len-m2+1], &argv[argc-mlen], mlen);
+ }
+ if (mlen < m2) {
+ stack_clear(&regs[len-m2+mlen+1], m2-mlen);
+ }
+ if (r) {
+ regs[m1+o+1] = mrb_ary_new_capa(mrb, 0);
+ }
+ if (o == 0 || argc < m1+m2) pc++;
+ else
+ pc += argc - m1 - m2 + 1;
+ }
+ else {
+ int rnum = 0;
+ if (argv0 != argv) {
+ regs[len+1] = *blk; /* move block */
+ value_move(&regs[1], argv, m1+o);
+ }
+ if (r) {
+ rnum = argc-m1-o-m2;
+ regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o);
+ }
+ if (m2) {
+ if (argc-m2 > m1) {
+ value_move(&regs[m1+o+r+1], &argv[m1+o+rnum], m2);
+ }
+ }
+ if (argv0 == argv) {
+ regs[len+1] = *blk; /* move block */
+ }
+ pc += o + 1;
+ }
+ mrb->c->ci->argc = len;
+ /* clear local (but non-argument) variables */
+ if (irep->nlocals-len-2 > 0) {
+ stack_clear(&regs[len+2], irep->nlocals-len-2);
+ }
+ JUMP;
+ }
+
+ CASE(OP_KARG) {
+ /* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
+ /* if C == 2; raise unless kdict.empty? */
+ /* OP_JMP should follow to skip init code */
+ NEXT;
+ }
+
+ CASE(OP_KDICT) {
+ /* A C R(A) := kdict */
+ NEXT;
+ }
+
+ L_RETURN:
+ i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL);
+ /* fall through */
+ CASE(OP_RETURN) {
+ /* A B return R(A) (B=normal,in-block return/break) */
+ mrb_callinfo *ci;
+
+ ci = mrb->c->ci;
+ if (ci->mid) {
+ mrb_value blk;
+
+ if (ci->argc < 0) {
+ blk = regs[2];
+ }
+ else {
+ blk = regs[ci->argc+1];
+ }
+ if (mrb_type(blk) == MRB_TT_PROC) {
+ struct RProc *p = mrb_proc_ptr(blk);
+
+ if (!MRB_PROC_STRICT_P(p) &&
+ ci > mrb->c->cibase && p->env == ci[-1].env) {
+ p->flags |= MRB_PROC_ORPHAN;
+ }
+ }
+ }
+
+ if (mrb->exc) {
+ mrb_callinfo *ci0;
+ mrb_value *stk;
+
+ L_RAISE:
+ ci0 = ci = mrb->c->ci;
+ if (ci == mrb->c->cibase) {
+ if (ci->ridx == 0) goto L_FTOP;
+ goto L_RESCUE;
+ }
+ stk = mrb->c->stack;
+ while (ci[0].ridx == ci[-1].ridx) {
+ cipop(mrb);
+ mrb->c->stack = ci->stackent;
+ if (ci->acc == CI_ACC_SKIP && prev_jmp) {
+ mrb->jmp = prev_jmp;
+ MRB_THROW(prev_jmp);
+ }
+ ci = mrb->c->ci;
+ if (ci == mrb->c->cibase) {
+ mrb->c->stack = stk;
+ if (ci->ridx == 0) {
+ L_FTOP: /* fiber top */
+ if (mrb->c == mrb->root_c) {
+ mrb->c->stack = mrb->c->stbase;
+ goto L_STOP;
+ }
+ else {
+ struct mrb_context *c = mrb->c;
+
+ if (c->fib) {
+ mrb_write_barrier(mrb, (struct RBasic*)c->fib);
+ }
+ mrb->c = c->prev;
+ c->prev = NULL;
+ goto L_RAISE;
+ }
+ }
+ break;
+ }
+ /* call ensure only when we skip this callinfo */
+ if (ci[0].ridx == ci[-1].ridx) {
+ mrb_value *org_stbase = mrb->c->stbase;
+ while (mrb->c->eidx > ci->epos) {
+ ecall(mrb, --mrb->c->eidx);
+ ci = mrb->c->ci;
+ if (org_stbase != mrb->c->stbase) {
+ stk = mrb->c->stack;
+ }
+ }
+ }
+ }
+ L_RESCUE:
+ if (ci->ridx == 0) goto L_STOP;
+ proc = ci->proc;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ if (ci != ci0) {
+ mrb->c->stack = ci[1].stackent;
+ }
+ stack_extend(mrb, irep->nregs);
+ pc = mrb->c->rescue[--ci->ridx];
+ }
+ else {
+ int acc;
+ mrb_value v;
+
+ v = regs[GETARG_A(i)];
+ mrb_gc_protect(mrb, v);
+ switch (GETARG_B(i)) {
+ case OP_R_RETURN:
+ /* Fall through to OP_R_NORMAL otherwise */
+ if (ci->acc >=0 && proc->env && !MRB_PROC_STRICT_P(proc)) {
+ struct REnv *e = top_env(mrb, proc);
+ mrb_callinfo *ce;
+
+ if (!MRB_ENV_STACK_SHARED_P(e) || e->cxt.c != mrb->c) {
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+
+ ce = mrb->c->cibase + e->cioff;
+ while (ci > ce) {
+ mrb_env_unshare(mrb, ci->env);
+ if (ci->acc < 0) {
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ ci--;
+ }
+ mrb_env_unshare(mrb, ci->env);
+ if (ce == mrb->c->cibase) {
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ mrb->c->stack = mrb->c->ci->stackent;
+ mrb->c->ci = ce;
+ break;
+ }
+ case OP_R_NORMAL:
+ NORMAL_RETURN:
+ if (ci == mrb->c->cibase) {
+ if (!mrb->c->prev) { /* toplevel return */
+ localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
+ goto L_RAISE;
+ }
+ if (mrb->c->prev->ci == mrb->c->prev->cibase) {
+ mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume");
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ while (mrb->c->eidx > 0) {
+ ecall(mrb, --mrb->c->eidx);
+ }
+ /* automatic yield at the end */
+ mrb->c->status = MRB_FIBER_TERMINATED;
+ mrb->c = mrb->c->prev;
+ mrb->c->status = MRB_FIBER_RUNNING;
+ }
+ ci = mrb->c->ci;
+ break;
+ case OP_R_BREAK:
+ if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
+ if (MRB_PROC_ORPHAN_P(proc)) {
+ mrb_value exc;
+
+ L_BREAK_ERROR:
+ exc = mrb_exc_new_str_lit(mrb, E_LOCALJUMP_ERROR,
+ "break from proc-closure");
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ if (!proc->env || !MRB_ENV_STACK_SHARED_P(proc->env)) {
+ goto L_BREAK_ERROR;
+ }
+ if (proc->env->cxt.c != mrb->c) {
+ goto L_BREAK_ERROR;
+ }
+ while (mrb->c->eidx > mrb->c->ci->epos) {
+ ecall(mrb, --mrb->c->eidx);
+ }
+ /* break from fiber block */
+ if (mrb->c->ci == mrb->c->cibase && mrb->c->ci->pc) {
+ struct mrb_context *c = mrb->c;
+
+ mrb->c = c->prev;
+ c->prev = NULL;
+ }
+ ci = mrb->c->ci;
+ if (ci->acc < 0) {
+ mrb_gc_arena_restore(mrb, ai);
+ mrb->c->vmexec = FALSE;
+ mrb->exc = (struct RObject*)break_new(mrb, proc, v);
+ mrb->jmp = prev_jmp;
+ MRB_THROW(prev_jmp);
+ }
+ if (FALSE) {
+ L_BREAK:
+ v = ((struct RBreak*)mrb->exc)->val;
+ proc = ((struct RBreak*)mrb->exc)->proc;
+ mrb->exc = NULL;
+ ci = mrb->c->ci;
+ }
+ mrb->c->stack = ci->stackent;
+ mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1;
+ while (ci > mrb->c->ci) {
+ mrb_env_unshare(mrb, ci->env);
+ if (ci[-1].acc == CI_ACC_SKIP) {
+ mrb->c->ci = ci;
+ goto L_BREAK_ERROR;
+ }
+ ci--;
+ }
+ mrb_env_unshare(mrb, ci->env);
+ break;
+ default:
+ /* cannot happen */
+ break;
+ }
+ while (mrb->c->eidx > mrb->c->ci->epos) {
+ ecall(mrb, --mrb->c->eidx);
+ }
+ if (mrb->c->vmexec && !mrb->c->ci->target_class) {
+ mrb_gc_arena_restore(mrb, ai);
+ mrb->c->vmexec = FALSE;
+ mrb->jmp = prev_jmp;
+ return v;
+ }
+ ci = mrb->c->ci;
+ acc = ci->acc;
+ mrb->c->stack = ci->stackent;
+ cipop(mrb);
+ if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) {
+ mrb_gc_arena_restore(mrb, ai);
+ mrb->jmp = prev_jmp;
+ return v;
+ }
+ pc = ci->pc;
+ DEBUG(fprintf(stderr, "from :%s\n", mrb_sym2name(mrb, ci->mid)));
+ proc = mrb->c->ci->proc;
+ irep = proc->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+
+ regs[acc] = v;
+ mrb_gc_arena_restore(mrb, ai);
+ }
+ JUMP;
+ }
+
+ CASE(OP_TAILCALL) {
+ /* A B C return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */
+ int a = GETARG_A(i);
+ int n = GETARG_C(i);
+ struct RProc *m;
+ struct RClass *c;
+ mrb_callinfo *ci;
+ mrb_value recv;
+ mrb_sym mid = syms[GETARG_B(i)];
+
+ recv = regs[a];
+ c = mrb_class(mrb, recv);
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (!m) {
+ mrb_value sym = mrb_symbol_value(mid);
+ mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
+ m = mrb_method_search_vm(mrb, &c, missing);
+ if (!m) {
+ mrb_value args;
+
+ if (n == CALL_MAXARGS) {
+ args = regs[a+1];
+ }
+ else {
+ args = mrb_ary_new_from_values(mrb, n, regs+a+1);
+ }
+ ERR_PC_SET(mrb, pc);
+ mrb_method_missing(mrb, mid, recv, args);
+ }
+ mid = missing;
+ if (n == CALL_MAXARGS) {
+ mrb_ary_unshift(mrb, regs[a+1], sym);
+ }
+ else {
+ value_move(regs+a+2, regs+a+1, ++n);
+ regs[a+1] = sym;
+ }
+ }
+
+ /* replace callinfo */
+ ci = mrb->c->ci;
+ ci->mid = mid;
+ ci->target_class = c;
+ if (n == CALL_MAXARGS) {
+ ci->argc = -1;
+ }
+ else {
+ ci->argc = n;
+ }
+
+ /* move stack */
+ value_move(mrb->c->stack, &regs[a], ci->argc+1);
+
+ if (MRB_PROC_CFUNC_P(m)) {
+ mrb_value v = m->body.func(mrb, recv);
+ mrb->c->stack[0] = v;
+ mrb_gc_arena_restore(mrb, ai);
+ goto L_RETURN;
+ }
+ else {
+ /* setup environment for calling method */
+ irep = m->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ if (ci->argc < 0) {
+ stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
+ }
+ else {
+ stack_extend(mrb, irep->nregs);
+ }
+ pc = irep->iseq;
+ }
+ JUMP;
+ }
+
+ CASE(OP_BLKPUSH) {
+ /* A Bx R(A) := block (16=6:1:5:4) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ int m1 = (bx>>10)&0x3f;
+ int r = (bx>>9)&0x1;
+ int m2 = (bx>>4)&0x1f;
+ int lv = (bx>>0)&0xf;
+ mrb_value *stack;
+
+ if (lv == 0) stack = regs + 1;
+ else {
+ struct REnv *e = uvenv(mrb, lv-1);
+ if (!e || e->cioff == 0 ||
+ (!MRB_ENV_STACK_SHARED_P(e) && e->cxt.mid == 0) ||
+ MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) {
+ localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
+ goto L_RAISE;
+ }
+ stack = e->stack + 1;
+ }
+ if (mrb_nil_p(stack[m1+r+m2])) {
+ localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
+ goto L_RAISE;
+ }
+ regs[a] = stack[m1+r+m2];
+ NEXT;
+ }
+
+#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
+#define OP_MATH_BODY(op,v1,v2) do {\
+ v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
+} while(0)
+
+ CASE(OP_ADD) {
+ /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/
+ int a = GETARG_A(i);
+
+ /* need to check if op is overridden */
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
+ {
+ mrb_int x, y, z;
+ mrb_value *regs_a = regs + a;
+
+ x = mrb_fixnum(regs_a[0]);
+ y = mrb_fixnum(regs_a[1]);
+ if (mrb_int_add_overflow(x, y, &z)) {
+ SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
+ break;
+ }
+ SET_INT_VALUE(regs[a], z);
+ }
+ break;
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
+ {
+ mrb_int x = mrb_fixnum(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
+ }
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_int y = mrb_fixnum(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x + y);
+ }
+#else
+ OP_MATH_BODY(+,mrb_float,mrb_fixnum);
+#endif
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x + y);
+ }
+#else
+ OP_MATH_BODY(+,mrb_float,mrb_float);
+#endif
+ break;
+ case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
+ regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
+ break;
+ default:
+ goto L_SEND;
+ }
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_SUB) {
+ /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/
+ int a = GETARG_A(i);
+
+ /* need to check if op is overridden */
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
+ {
+ mrb_int x, y, z;
+
+ x = mrb_fixnum(regs[a]);
+ y = mrb_fixnum(regs[a+1]);
+ if (mrb_int_sub_overflow(x, y, &z)) {
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
+ break;
+ }
+ SET_INT_VALUE(regs[a], z);
+ }
+ break;
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
+ {
+ mrb_int x = mrb_fixnum(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
+ }
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_int y = mrb_fixnum(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x - y);
+ }
+#else
+ OP_MATH_BODY(-,mrb_float,mrb_fixnum);
+#endif
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x - y);
+ }
+#else
+ OP_MATH_BODY(-,mrb_float,mrb_float);
+#endif
+ break;
+ default:
+ goto L_SEND;
+ }
+ NEXT;
+ }
+
+ CASE(OP_MUL) {
+ /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/
+ int a = GETARG_A(i);
+
+ /* need to check if op is overridden */
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
+ {
+ mrb_int x, y, z;
+
+ x = mrb_fixnum(regs[a]);
+ y = mrb_fixnum(regs[a+1]);
+ if (mrb_int_mul_overflow(x, y, &z)) {
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * (mrb_float)y);
+ break;
+ }
+ SET_INT_VALUE(regs[a], z);
+ }
+ break;
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
+ {
+ mrb_int x = mrb_fixnum(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
+ }
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_int y = mrb_fixnum(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x * y);
+ }
+#else
+ OP_MATH_BODY(*,mrb_float,mrb_fixnum);
+#endif
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x * y);
+ }
+#else
+ OP_MATH_BODY(*,mrb_float,mrb_float);
+#endif
+ break;
+ default:
+ goto L_SEND;
+ }
+ NEXT;
+ }
+
+ CASE(OP_DIV) {
+ /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/
+ int a = GETARG_A(i);
+
+ /* need to check if op is overridden */
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
+ {
+ mrb_int x = mrb_fixnum(regs[a]);
+ mrb_int y = mrb_fixnum(regs[a+1]);
+ double f;
+ if (y == 0) {
+ if (x > 0) f = INFINITY;
+ else if (x < 0) f = -INFINITY;
+ else /* if (x == 0) */ f = NAN;
+ }
+ else {
+ f = (mrb_float)x / (mrb_float)y;
+ }
+ SET_FLOAT_VALUE(mrb, regs[a], f);
+ }
+ break;
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
+ {
+ mrb_int x = mrb_fixnum(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y);
+ }
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_int y = mrb_fixnum(regs[a+1]);
+ double f;
+ if (y == 0) {
+ f = INFINITY;
+ }
+ else {
+ f = x / y;
+ }
+ SET_FLOAT_VALUE(mrb, regs[a], f);
+ }
+#else
+ OP_MATH_BODY(/,mrb_float,mrb_fixnum);
+#endif
+ break;
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ mrb_float y = mrb_float(regs[a+1]);
+ SET_FLOAT_VALUE(mrb, regs[a], x / y);
+ }
+#else
+ OP_MATH_BODY(/,mrb_float,mrb_float);
+#endif
+ break;
+ default:
+ goto L_SEND;
+ }
+#ifdef MRB_NAN_BOXING
+ if (isnan(mrb_float(regs[a]))) {
+ mrb_value v = mrb_float_value(mrb, mrb_float(regs[a]));
+ regs[a] = v;
+ }
+#endif
+ NEXT;
+ }
+
+ CASE(OP_ADDI) {
+ /* A B C R(A) := R(A)+C (Syms[B]=:+)*/
+ int a = GETARG_A(i);
+
+ /* need to check if + is overridden */
+ switch (mrb_type(regs[a])) {
+ case MRB_TT_FIXNUM:
+ {
+ mrb_int x = mrb_fixnum(regs[a]);
+ mrb_int y = GETARG_C(i);
+ mrb_int z;
+
+ if (mrb_int_add_overflow(x, y, &z)) {
+ SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
+ break;
+ }
+ SET_INT_VALUE(regs[a], z);
+ }
+ break;
+ case MRB_TT_FLOAT:
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i));
+ }
+#else
+ mrb_float(regs[a]) += GETARG_C(i);
+#endif
+ break;
+ default:
+ SET_INT_VALUE(regs[a+1], GETARG_C(i));
+ i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
+ goto L_SEND;
+ }
+ NEXT;
+ }
+
+ CASE(OP_SUBI) {
+ /* A B C R(A) := R(A)-C (Syms[B]=:-)*/
+ int a = GETARG_A(i);
+ mrb_value *regs_a = regs + a;
+
+ /* need to check if + is overridden */
+ switch (mrb_type(regs_a[0])) {
+ case MRB_TT_FIXNUM:
+ {
+ mrb_int x = mrb_fixnum(regs_a[0]);
+ mrb_int y = GETARG_C(i);
+ mrb_int z;
+
+ if (mrb_int_sub_overflow(x, y, &z)) {
+ SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
+ }
+ else {
+ SET_INT_VALUE(regs_a[0], z);
+ }
+ }
+ break;
+ case MRB_TT_FLOAT:
+#ifdef MRB_WORD_BOXING
+ {
+ mrb_float x = mrb_float(regs[a]);
+ SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i));
+ }
+#else
+ mrb_float(regs_a[0]) -= GETARG_C(i);
+#endif
+ break;
+ default:
+ SET_INT_VALUE(regs_a[1], GETARG_C(i));
+ i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1);
+ goto L_SEND;
+ }
+ NEXT;
+ }
+
+#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
+
+#define OP_CMP(op) do {\
+ int result;\
+ /* need to check if - is overridden */\
+ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\
+ result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\
+ break;\
+ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\
+ result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\
+ break;\
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\
+ result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\
+ break;\
+ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\
+ result = OP_CMP_BODY(op,mrb_float,mrb_float);\
+ break;\
+ default:\
+ goto L_SEND;\
+ }\
+ if (result) {\
+ SET_TRUE_VALUE(regs[a]);\
+ }\
+ else {\
+ SET_FALSE_VALUE(regs[a]);\
+ }\
+} while(0)
+
+ CASE(OP_EQ) {
+ /* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/
+ int a = GETARG_A(i);
+ if (mrb_obj_eq(mrb, regs[a], regs[a+1])) {
+ SET_TRUE_VALUE(regs[a]);
+ }
+ else {
+ OP_CMP(==);
+ }
+ NEXT;
+ }
+
+ CASE(OP_LT) {
+ /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/
+ int a = GETARG_A(i);
+ OP_CMP(<);
+ NEXT;
+ }
+
+ CASE(OP_LE) {
+ /* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)*/
+ int a = GETARG_A(i);
+ OP_CMP(<=);
+ NEXT;
+ }
+
+ CASE(OP_GT) {
+ /* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1)*/
+ int a = GETARG_A(i);
+ OP_CMP(>);
+ NEXT;
+ }
+
+ CASE(OP_GE) {
+ /* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/
+ int a = GETARG_A(i);
+ OP_CMP(>=);
+ NEXT;
+ }
+
+ CASE(OP_ARRAY) {
+ /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ mrb_value v = mrb_ary_new_from_values(mrb, c, &regs[b]);
+ regs[a] = v;
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_ARYCAT) {
+ /* A B mrb_ary_concat(R(A),R(B)) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ mrb_value splat = mrb_ary_splat(mrb, regs[b]);
+ mrb_ary_concat(mrb, regs[a], splat);
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_ARYPUSH) {
+ /* A B R(A).push(R(B)) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ mrb_ary_push(mrb, regs[a], regs[b]);
+ NEXT;
+ }
+
+ CASE(OP_AREF) {
+ /* A B C R(A) := R(B)[C] */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ mrb_value v = regs[b];
+
+ if (!mrb_array_p(v)) {
+ if (c == 0) {
+ regs[a] = v;
+ }
+ else {
+ SET_NIL_VALUE(regs[a]);
+ }
+ }
+ else {
+ v = mrb_ary_ref(mrb, v, c);
+ regs[a] = v;
+ }
+ NEXT;
+ }
+
+ CASE(OP_ASET) {
+ /* A B C R(B)[C] := R(A) */
+ int a = GETARG_A(i);
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ mrb_ary_set(mrb, regs[b], c, regs[a]);
+ NEXT;
+ }
+
+ CASE(OP_APOST) {
+ /* A B C *R(A),R(A+1)..R(A+C) := R(A) */
+ int a = GETARG_A(i);
+ mrb_value v = regs[a];
+ int pre = GETARG_B(i);
+ int post = GETARG_C(i);
+ struct RArray *ary;
+ int len, idx;
+
+ if (!mrb_array_p(v)) {
+ v = mrb_ary_new_from_values(mrb, 1, &regs[a]);
+ }
+ ary = mrb_ary_ptr(v);
+ len = ARY_LEN(ary);
+ if (len > pre + post) {
+ v = mrb_ary_new_from_values(mrb, len - pre - post, ARY_PTR(ary)+pre);
+ regs[a++] = v;
+ while (post--) {
+ regs[a++] = ARY_PTR(ary)[len-post-1];
+ }
+ }
+ else {
+ v = mrb_ary_new_capa(mrb, 0);
+ regs[a++] = v;
+ for (idx=0; idx+pre<len; idx++) {
+ regs[a+idx] = ARY_PTR(ary)[pre+idx];
+ }
+ while (idx < post) {
+ SET_NIL_VALUE(regs[a+idx]);
+ idx++;
+ }
+ }
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_STRING) {
+ /* A Bx R(A) := str_new(Lit(Bx)) */
+ mrb_value str = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
+ regs[GETARG_A(i)] = str;
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_STRCAT) {
+ /* A B R(A).concat(R(B)) */
+ mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]);
+ NEXT;
+ }
+
+ CASE(OP_HASH) {
+ /* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
+ int b = GETARG_B(i);
+ int c = GETARG_C(i);
+ int lim = b+c*2;
+ mrb_value hash = mrb_hash_new_capa(mrb, c);
+
+ while (b < lim) {
+ mrb_hash_set(mrb, hash, regs[b], regs[b+1]);
+ b+=2;
+ }
+ regs[GETARG_A(i)] = hash;
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_LAMBDA) {
+ /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */
+ struct RProc *p;
+ int a = GETARG_A(i);
+ int b = GETARG_b(i);
+ int c = GETARG_c(i);
+ mrb_irep *nirep = irep->reps[b];
+
+ irep_uplink(mrb, irep, nirep);
+ if (c & OP_L_CAPTURE) {
+ p = mrb_closure_new(mrb, nirep);
+ }
+ else {
+ p = mrb_proc_new(mrb, nirep);
+ }
+ if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT;
+ regs[a] = mrb_obj_value(p);
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_OCLASS) {
+ /* A R(A) := ::Object */
+ regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class);
+ NEXT;
+ }
+
+ CASE(OP_CLASS) {
+ /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
+ struct RClass *c = 0, *baseclass;
+ int a = GETARG_A(i);
+ mrb_value base, super;
+ mrb_sym id = syms[GETARG_B(i)];
+
+ base = regs[a];
+ super = regs[a+1];
+ if (mrb_nil_p(base)) {
+ baseclass = mrb->c->ci->proc->target_class;
+ if (!baseclass) baseclass = mrb->c->ci->target_class;
+
+ base = mrb_obj_value(baseclass);
+ }
+ c = mrb_vm_define_class(mrb, base, super, id);
+ regs[a] = mrb_obj_value(c);
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_MODULE) {
+ /* A B R(A) := newmodule(R(A),Syms(B)) */
+ struct RClass *c = 0, *baseclass;
+ int a = GETARG_A(i);
+ mrb_value base;
+ mrb_sym id = syms[GETARG_B(i)];
+
+ base = regs[a];
+ if (mrb_nil_p(base)) {
+ baseclass = mrb->c->ci->proc->target_class;
+ if (!baseclass) baseclass = mrb->c->ci->target_class;
+
+ base = mrb_obj_value(baseclass);
+ }
+ c = mrb_vm_define_module(mrb, base, id);
+ regs[a] = mrb_obj_value(c);
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_EXEC) {
+ /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
+ int a = GETARG_A(i);
+ int bx = GETARG_Bx(i);
+ mrb_callinfo *ci;
+ mrb_value recv = regs[a];
+ struct RProc *p;
+ mrb_irep *nirep = irep->reps[bx];
+
+ irep_uplink(mrb, irep, nirep);
+ nirep->target_class = mrb_class_ptr(recv);
+ /* prepare closure */
+ p = mrb_closure_new(mrb, nirep);
+ p->c = NULL;
+
+ /* prepare stack */
+ ci = cipush(mrb);
+ ci->pc = pc + 1;
+ ci->acc = a;
+ ci->mid = 0;
+ ci->stackent = mrb->c->stack;
+ ci->argc = 0;
+ ci->target_class = mrb_class_ptr(recv);
+
+ /* prepare stack */
+ mrb->c->stack += a;
+
+ /* setup closure */
+ p->target_class = ci->target_class;
+ ci->proc = p;
+
+ irep = p->body.irep;
+ pool = irep->pool;
+ syms = irep->syms;
+ ci->nregs = irep->nregs;
+ stack_extend(mrb, ci->nregs);
+ stack_clear(regs+1, ci->nregs-1);
+ pc = irep->iseq;
+ JUMP;
+ }
+
+ CASE(OP_METHOD) {
+ /* A B R(A).newmethod(Syms(B),R(A+1)) */
+ int a = GETARG_A(i);
+ struct RClass *c = mrb_class_ptr(regs[a]);
+ struct RProc *p = mrb_proc_ptr(regs[a+1]);
+
+ mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p);
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_SCLASS) {
+ /* A B R(A) := R(B).singleton_class */
+ regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]);
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_TCLASS) {
+ /* A R(A) := target_class */
+ if (!mrb->c->ci->target_class) {
+ mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module");
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class);
+ NEXT;
+ }
+
+ CASE(OP_RANGE) {
+ /* A B C R(A) := range_new(R(B),R(B+1),C) */
+ int b = GETARG_B(i);
+ mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i));
+ regs[GETARG_A(i)] = val;
+ mrb_gc_arena_restore(mrb, ai);
+ NEXT;
+ }
+
+ CASE(OP_DEBUG) {
+ /* A B C debug print R(A),R(B),R(C) */
+#ifdef MRB_ENABLE_DEBUG_HOOK
+ mrb->debug_op_hook(mrb, irep, pc, regs);
+#else
+#ifndef MRB_DISABLE_STDIO
+ printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i));
+#else
+ abort();
+#endif
+#endif
+ NEXT;
+ }
+
+ CASE(OP_STOP) {
+ /* stop VM */
+ L_STOP:
+ {
+ int epos = mrb->c->ci->epos;
+
+ while (mrb->c->eidx > epos) {
+ ecall(mrb, --mrb->c->eidx);
+ }
+ }
+ ERR_PC_CLR(mrb);
+ mrb->jmp = prev_jmp;
+ if (mrb->exc) {
+ return mrb_obj_value(mrb->exc);
+ }
+ return regs[irep->nlocals];
+ }
+
+ CASE(OP_ERR) {
+ /* Bx raise RuntimeError with message Lit(Bx) */
+ mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]);
+ mrb_value exc;
+
+ if (GETARG_A(i) == 0) {
+ exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg);
+ }
+ else {
+ exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg);
+ }
+ ERR_PC_SET(mrb, pc);
+ mrb_exc_set(mrb, exc);
+ goto L_RAISE;
+ }
+ }
+ END_DISPATCH;
+#undef regs
+
+ }
+ MRB_CATCH(&c_jmp) {
+ exc_catched = TRUE;
+ goto RETRY_TRY_BLOCK;
+ }
+ MRB_END_EXC(&c_jmp);
+}
+
+MRB_API mrb_value
+mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
+{
+ if (mrb->c->ci->argc < 0) {
+ return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */
+ }
+ else {
+ return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */
+ }
+}
+
+MRB_API mrb_value
+mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
+{
+ mrb_callinfo *ci;
+ mrb_value v;
+
+ if (!mrb->c->cibase) {
+ return mrb_vm_run(mrb, proc, self, stack_keep);
+ }
+ if (mrb->c->ci == mrb->c->cibase) {
+ mrb->c->ci->env = NULL;
+ return mrb_vm_run(mrb, proc, self, stack_keep);
+ }
+ ci = cipush(mrb);
+ ci->mid = 0;
+ ci->nregs = 1; /* protect the receiver */
+ ci->acc = CI_ACC_SKIP;
+ ci->target_class = mrb->object_class;
+ v = mrb_vm_run(mrb, proc, self, stack_keep);
+ cipop(mrb);
+
+ return v;
+}
+
+#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
+# if !defined(MRB_ENABLE_CXX_ABI)
+} /* end of extern "C" */
+# endif
+mrb_int mrb_jmpbuf::jmpbuf_id = 0;
+# if !defined(MRB_ENABLE_CXX_ABI)
+extern "C" {
+# endif
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/benchmark.rake b/web/server/h2o/libh2o/deps/mruby/tasks/benchmark.rake
new file mode 100644
index 00000000..84e69ebe
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/benchmark.rake
@@ -0,0 +1,91 @@
+module MRuby
+ BENCHMARK_REPEAT = 4
+end
+
+$dat_files = []
+
+def bm_files
+ Dir.glob("#{MRUBY_ROOT}/benchmark/bm_*.rb")
+end
+
+def build_config_name
+ if ENV['MRUBY_CONFIG']
+ File.basename(ENV['MRUBY_CONFIG'], '.rb').gsub('build_config_', '')
+ else
+ "build"
+ end
+end
+
+def plot_file
+ File.join(MRUBY_ROOT, 'benchmark', "#{build_config_name}.png")
+end
+
+def plot
+ opts_file = "#{MRUBY_ROOT}/benchmark/plot.gpl"
+ opts = File.read(opts_file).each_line.to_a.map(&:strip).join(';')
+
+ dat_files = $dat_files.group_by {|f| File.dirname(f).split(File::SEPARATOR)[-1]}
+
+ opts += ";set output '#{plot_file}'"
+
+ opts += ';plot '
+
+ opts += dat_files.keys.map do |data_file|
+ %Q['-' u 2:3:4:xtic(1) w hist title columnheader(1)]
+ end.join(',')
+ opts += ';'
+
+ cmd = %Q{gnuplot -p -e "#{opts}"}
+
+ IO.popen(cmd, 'w') do |p|
+ dat_files.each do |target_name, bm_files|
+ p.puts target_name.gsub('_', '-')
+ bm_files.each do |bm_file|
+ p.write File.read(bm_file)
+ end
+ p.puts "e"
+ end
+ end
+end
+
+
+MRuby.each_target do |target|
+ next if target.name == 'host'
+ mruby_bin = "#{target.build_dir}/bin/mruby"
+
+ bm_files.each do |bm_file|
+ bm_name = File.basename bm_file, ".rb"
+
+ dat_dir = File.join('benchmark', build_config_name, target.name)
+ dat_file = File.join(dat_dir, "#{bm_name}.dat")
+ $dat_files << dat_file
+
+ directory dat_dir
+
+ file dat_file => [bm_file, dat_dir, mruby_bin] do |task|
+ print bm_name
+ puts "..."
+
+ data = (0...MRuby::BENCHMARK_REPEAT).map do |n|
+ str = %x{(time -f "%e %S %U" #{mruby_bin} #{bm_file}) 2>&1 >/dev/null}
+ str.split(' ').map(&:to_f)
+ end
+
+ File.open(task.name, "w") do |f|
+ data = data.map {|_,r,s| (r + s) / 2.0}
+ min = data.min
+ max = data.max
+ avg = data.inject(&:+) / data.size
+ f.puts "#{bm_name.gsub('_', '-')} #{avg} #{min} #{max}"
+ end
+ end
+ end
+end
+
+file plot_file => $dat_files do
+ plot
+end
+
+task :benchmark => plot_file do
+ plot
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/gitlab.rake b/web/server/h2o/libh2o/deps/mruby/tasks/gitlab.rake
new file mode 100644
index 00000000..47117237
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/gitlab.rake
@@ -0,0 +1,118 @@
+CI_VERSION = '0.7'.freeze
+CI_BASE = 'ubuntu:16.10'.freeze
+CI_COMPILERS = ['gcc-4.7',
+ 'gcc-4.8',
+ 'gcc-4.9',
+ 'gcc-5',
+ 'gcc-6',
+ 'clang-3.5',
+ 'clang-3.6',
+ 'clang-3.7',
+ 'clang-3.8',
+ 'clang-3.9'].freeze
+
+def ci_image_tag(compiler)
+ compiler.tr('+', 'c').delete('-').delete('.')
+end
+
+def ci_docker_tag(compiler)
+ tag = ci_image_tag(compiler)
+ "registry.gitlab.com/dabroz/mruby:#{tag}_#{CI_VERSION}"
+end
+
+def run_cmd(cmd)
+ puts cmd
+ raise 'error' unless system cmd
+end
+
+desc 'recreate docker images for GitLab builds'
+task :gitlab_dockers do
+ CI_COMPILERS.each do |compiler|
+ tag = ci_image_tag(compiler)
+ filename = "Dockerfile.#{tag}"
+ File.open(filename, 'wb') do |f|
+ f << "# #{compiler} - #{tag}\n"
+ f << "FROM #{CI_BASE}\n"
+ f << "RUN apt-get update && apt-get install -y git ruby2.3 ruby2.3-dev bison\n"
+ f << "RUN apt-get update && apt-get install -y binutils manpages\n"
+ f << "RUN apt-get update && apt-get install -y #{compiler}\n"
+ if compiler['gcc']
+ f << "RUN apt-get update && apt-get install -y libx32#{compiler}-dev\n"
+ f << "RUN apt-get update && apt-get install --no-install-recommends -y #{compiler}-multilib\n"
+ end
+ f << "RUN dpkg --add-architecture i386\n"
+ f << "RUN apt-get update && apt-get install -y linux-libc-dev:i386\n"
+ if compiler['clang']
+ f << "RUN apt-get update && apt-get install --no-install-recommends -y libc6-dev-i386\n"
+ f << "RUN apt-get update && apt-get install -y gcc gcc-multilib\n"
+ end
+ end
+ docker_tag = ci_docker_tag(compiler)
+ cmd1 = "docker build -t #{docker_tag} -f #{filename} ."
+ cmd2 = "docker push #{docker_tag}"
+ run_cmd cmd1
+ run_cmd cmd2
+ File.delete(filename)
+ end
+end
+
+desc 'create build configurations and update .gitlab-ci.yml'
+task :gitlab_config do
+ require 'yaml'
+
+ configs = []
+ [true, false].each do |mode_32|
+ ['', 'MRB_USE_FLOAT'].each do |float_conf|
+ ['', 'MRB_INT16', 'MRB_INT64'].each do |int_conf|
+ ['', 'MRB_NAN_BOXING', 'MRB_WORD_BOXING'].each do |boxing_conf|
+ ['', 'MRB_UTF8_STRING'].each do |utf8_conf|
+ next if (float_conf == 'MRB_USE_FLOAT') && (boxing_conf == 'MRB_NAN_BOXING')
+ next if (int_conf == 'MRB_INT64') && (boxing_conf == 'MRB_NAN_BOXING')
+ next if (int_conf == 'MRB_INT16') && (boxing_conf == 'MRB_WORD_BOXING')
+ next if (int_conf == 'MRB_INT64') && (boxing_conf == 'MRB_WORD_BOXING') && mode_32
+ env = [float_conf, int_conf, boxing_conf, utf8_conf].map do |conf|
+ conf == '' ? nil : "-D#{conf}=1"
+ end.compact.join(' ')
+ bit = mode_32 ? '-m32 ' : ''
+ _info = ''
+ _info += mode_32 ? '32bit ' : '64bit '
+ _info += float_conf['USE'] ? 'float ' : ''
+ _info += int_conf['16'] ? 'int16 ' : ''
+ _info += int_conf['64'] ? 'int64 ' : ''
+ _info += boxing_conf['NAN'] ? 'nan ' : ''
+ _info += boxing_conf['word'] ? 'word ' : ''
+ _info += utf8_conf['UTF8'] ? 'utf8 ' : ''
+ _info = _info.gsub(/ +/, ' ').strip.tr(' ', '_')
+ configs << { '_info' => _info, 'CFLAGS' => "#{bit}#{env}", 'LDFLAGS' => bit.strip.to_s }
+ end
+ end
+ end
+ end
+ end
+ path = './.gitlab-ci.yml'
+ data = YAML.load_file(path)
+ data.keys.select do |key|
+ key.start_with? 'Test'
+ end.each do |key|
+ data.delete(key)
+ end
+ CI_COMPILERS.each do |compiler|
+ configs.each do |config|
+ name = "Test #{compiler} #{config['_info']}"
+ hash = {
+ 'CC' => compiler,
+ 'CXX' => compiler.gsub('gcc', 'g++').gsub('clang', 'clang++'),
+ 'LD' => compiler
+ }
+ hash = hash.merge(config)
+ hash.delete('_info')
+ data[name] = {
+ 'stage' => 'test',
+ 'image' => ci_docker_tag(compiler),
+ 'variables' => hash,
+ 'script' => 'env; ./minirake --verbose all test'
+ }
+ end
+ end
+ File.open(path, 'w') { |f| YAML.dump(data, f) }
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/libmruby.rake b/web/server/h2o/libh2o/deps/mruby/tasks/libmruby.rake
new file mode 100644
index 00000000..540aa3eb
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/libmruby.rake
@@ -0,0 +1,24 @@
+MRuby.each_target do
+ file libfile("#{build_dir}/lib/libmruby") => libmruby.flatten do |t|
+ archiver.run t.name, t.prerequisites
+ end
+
+ file "#{build_dir}/lib/libmruby.flags.mak" => [__FILE__, libfile("#{build_dir}/lib/libmruby")] do |t|
+ open(t.name, 'w') do |f|
+ f.puts "MRUBY_CFLAGS = #{cc.all_flags}"
+
+ gem_flags = gems.map { |g| g.linker.flags }
+ gem_library_paths = gems.map { |g| g.linker.library_paths }
+ f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % "#{build_dir}/lib"}"
+
+ gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
+ f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ')}"
+
+ gem_libraries = gems.map { |g| g.linker.libraries }
+ f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries)}"
+
+ f.puts "MRUBY_LIBMRUBY_PATH = #{libfile("#{build_dir}/lib/libmruby")}"
+ end
+ end
+ task :all => "#{build_dir}/lib/libmruby.flags.mak"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/mrbgems.rake b/web/server/h2o/libh2o/deps/mruby/tasks/mrbgems.rake
new file mode 100644
index 00000000..65368c30
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/mrbgems.rake
@@ -0,0 +1,96 @@
+MRuby.each_target do
+ if enable_gems?
+ # set up all gems
+ gems.each(&:setup)
+ gems.check self
+
+ # loader all gems
+ self.libmruby << objfile("#{build_dir}/mrbgems/gem_init")
+ file objfile("#{build_dir}/mrbgems/gem_init") => ["#{build_dir}/mrbgems/gem_init.c", "#{build_dir}/LEGAL"]
+ file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__] do |t|
+ FileUtils.mkdir_p "#{build_dir}/mrbgems"
+ open(t.name, 'w') do |f|
+ gem_func_gems = gems.select { |g| g.generate_functions }
+ gem_func_decls = gem_func_gems.each_with_object('') do |g, s|
+ s << "void GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb_state*);\n" \
+ "void GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb_state*);\n"
+ end
+ gem_init_calls = gem_func_gems.each_with_object('') do |g, s|
+ s << " GENERATED_TMP_mrb_#{g.funcname}_gem_init(mrb);\n"
+ end
+ gem_final_calls = gem_func_gems.each_with_object('') do |g, s|
+ s << " GENERATED_TMP_mrb_#{g.funcname}_gem_final(mrb);\n"
+ end
+ f.puts %Q[/*]
+ f.puts %Q[ * This file contains a list of all]
+ f.puts %Q[ * initializing methods which are]
+ f.puts %Q[ * necessary to bootstrap all gems.]
+ f.puts %Q[ *]
+ f.puts %Q[ * IMPORTANT:]
+ f.puts %Q[ * This file was generated!]
+ f.puts %Q[ * All manual changes will get lost.]
+ f.puts %Q[ */]
+ f.puts %Q[]
+ f.puts %Q[#include <mruby.h>]
+ f.puts %Q[]
+ f.write gem_func_decls
+ f.puts %Q[]
+ f.puts %Q[static void]
+ f.puts %Q[mrb_final_mrbgems(mrb_state *mrb) {]
+ f.write gem_final_calls
+ f.puts %Q[}]
+ f.puts %Q[]
+ f.puts %Q[void]
+ f.puts %Q[mrb_init_mrbgems(mrb_state *mrb) {]
+ f.write gem_init_calls
+ f.puts %Q[ mrb_state_atexit(mrb, mrb_final_mrbgems);] unless gem_final_calls.empty?
+ f.puts %Q[}]
+ end
+ end
+ end
+
+ # legal documents
+ file "#{build_dir}/LEGAL" => [MRUBY_CONFIG, __FILE__] do |t|
+ open(t.name, 'w+') do |f|
+ f.puts <<LEGAL
+Copyright (c) #{Time.now.year} mruby developers
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+LEGAL
+
+ if enable_gems?
+ f.puts <<GEMS_LEGAL
+
+Additional Licenses
+
+Due to the reason that you choosed additional mruby packages (GEMS),
+please check the following additional licenses too:
+GEMS_LEGAL
+
+ gems.map do |g|
+ authors = [g.authors].flatten.sort.join(", ")
+ f.puts
+ f.puts "GEM: #{g.name}"
+ f.puts "Copyright (c) #{Time.now.year} #{authors}"
+ f.puts "License: #{g.licenses}"
+ end
+ end
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/android.rake b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/android.rake
new file mode 100644
index 00000000..c59da7fc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/android.rake
@@ -0,0 +1,321 @@
+class MRuby::Toolchain::Android
+
+ DEFAULT_ARCH = 'armeabi' # TODO : Revise if arch should have a default
+
+ DEFAULT_TOOLCHAIN = :clang
+
+ DEFAULT_NDK_HOMES = %w{
+ /usr/local/opt/android-sdk/ndk-bundle
+ /usr/local/opt/android-ndk
+ %LOCALAPPDATA%/Android/android-sdk/ndk-bundle
+ %LOCALAPPDATA%/Android/android-ndk
+ ~/Library/Android/sdk/ndk-bundle
+ ~/Library/Android/ndk
+ }
+
+ TOOLCHAINS = [:clang, :gcc]
+
+ ARCHITECTURES = %w{
+ armeabi armeabi-v7a arm64-v8a
+ x86 x86_64
+ mips mips64
+ }
+
+ class AndroidNDKHomeNotFound < StandardError
+ def message
+ <<-EOM
+Couldn't find Android NDK Home.
+Set ANDROID_NDK_HOME environment variable or set :ndk_home parameter
+ EOM
+ end
+ end
+
+ class PlatformDirNotFound < StandardError
+ def message
+ <<-EOM
+Couldn't find Android NDK platform directories.
+Set ANDROID_PLATFORM environment variable or set :platform parameter
+ EOM
+ end
+ end
+
+ attr_reader :params
+
+ def initialize(params)
+ @params = params
+ end
+
+ def bin_gcc(command)
+ command = command.to_s
+
+ command = case arch
+ when /armeabi/ then 'arm-linux-androideabi-'
+ when /arm64-v8a/ then 'aarch64-linux-android-'
+ when /x86_64/ then 'x86_64-linux-android-'
+ when /x86/ then 'i686-linux-android-'
+ when /mips64/ then 'mips64el-linux-android-'
+ when /mips/ then 'mipsel-linux-android-'
+ end + command
+
+ gcc_toolchain_path.join('bin', command).to_s
+ end
+
+ def bin(command)
+ command = command.to_s
+ toolchain_path.join('bin', command).to_s
+ end
+
+ def home_path
+ @home_path ||= Pathname(
+ params[:ndk_home] ||
+ ENV['ANDROID_NDK_HOME'] ||
+ DEFAULT_NDK_HOMES.find { |path|
+ path.gsub! '%LOCALAPPDATA%', ENV['LOCALAPPDATA'] || '%LOCALAPPDATA%'
+ path.gsub! '\\', '/'
+ path.gsub! '~', Dir.home || '~'
+ File.directory?(path)
+ } || raise(AndroidNDKHomeNotFound)
+ )
+ end
+
+ def toolchain
+ @toolchain ||= params.fetch(:toolchain){ DEFAULT_TOOLCHAIN }
+ end
+
+ def toolchain_path
+ @toolchain_path ||= case toolchain
+ when :gcc
+ gcc_toolchain_path
+ when :clang
+ home_path.join('toolchains', 'llvm' , 'prebuilt', host_platform)
+ end
+ end
+
+ def gcc_toolchain_path
+ if @gcc_toolchain_path === nil then
+ prefix = case arch
+ when /armeabi/ then 'arm-linux-androideabi-'
+ when /arm64-v8a/ then 'aarch64-linux-android-'
+ when /x86_64/ then 'x86_64-'
+ when /x86/ then 'x86-'
+ when /mips64/ then 'mips64el-linux-android-'
+ when /mips/ then 'mipsel-linux-android-'
+ end
+
+ test = case arch
+ when /armeabi/ then 'arm-linux-androideabi-*'
+ when /arm64-v8a/ then 'aarch64-linux-android-*'
+ when /x86_64/ then 'x86_64-*'
+ when /x86/ then 'x86-*'
+ when /mips64/ then 'mips64el-linux-android-*'
+ when /mips/ then 'mipsel-linux-android-*'
+ end
+
+ gcc_toolchain_version = Dir[home_path.join('toolchains', test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max
+ @gcc_toolchain_path = home_path.join('toolchains', prefix + gcc_toolchain_version.to_s, 'prebuilt', host_platform)
+ end
+ @gcc_toolchain_path
+ end
+
+ def host_platform
+ @host_platform ||= case RUBY_PLATFORM
+ when /cygwin|mswin|mingw|bccwin|wince|emx/i
+ path = home_path.join('toolchains', 'llvm' , 'prebuilt', 'windows*')
+ Dir.glob(path.to_s){ |item|
+ next if File.file?(item)
+ path = Pathname(item)
+ break
+ }
+ path.basename
+ when /x86_64-darwin/i
+ 'darwin-x86_64'
+ when /darwin/i
+ 'darwin-x86'
+ when /x86_64-linux/i
+ 'linux-x86_64'
+ when /linux/i
+ 'linux-x86'
+ else
+ raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})"
+ end
+ end
+
+ def arch
+ @arch ||= (params[:arch] || ENV['ANDROID_ARCH'] || DEFAULT_ARCH).to_s
+ end
+
+ def sysroot
+ @sysroot ||= home_path.join('platforms', platform,
+ case arch
+ when /armeabi/ then 'arch-arm'
+ when /arm64-v8a/ then 'arch-arm64'
+ when /x86_64/ then 'arch-x86_64'
+ when /x86/ then 'arch-x86'
+ when /mips64/ then 'arch-mips64'
+ when /mips/ then 'arch-mips'
+ end
+ ).to_s
+ end
+
+ def platform
+ if @platform === nil then
+ @platform = params[:platform] || ENV['ANDROID_PLATFORM'] || nil
+ if @platform === nil
+ Dir.glob(home_path.join('platforms/android-*').to_s){ |item|
+ next if File.file?(item)
+ if @platform === nil
+ @platform = Integer(item.rpartition('-')[2])
+ else
+ platform = Integer(item.rpartition('-')[2])
+ @platform = platform > @platform ? platform : @platform
+ end
+ }
+ if @platform === nil
+ raise(PlatformDirNotFound)
+ else
+ @platform = "android-#{@platform}"
+ end
+ end
+ end
+ if Integer(@platform.rpartition('-')[2]) < 21
+ case arch
+ when /arm64-v8a/, /x86_64/, /mips64/
+ raise NotImplementedError, "Platform (#{@platform}) has no implementation for architecture (#{arch})"
+ end
+ end
+ @platform
+ end
+
+ def armeabi_v7a_mfpu
+ @armeabi_v7a_mfpu ||= (params[:mfpu] || 'vfpv3-d16').to_s
+ end
+
+ def armeabi_v7a_mfloat_abi
+ @armeabi_v7a_mfloat_abi ||= (params[:mfloat_abi] || 'softfp').to_s
+ end
+
+ def no_warn_mismatch
+ if %W(soft softfp).include? armeabi_v7a_mfloat_abi
+ ''
+ else
+ ',--no-warn-mismatch'
+ end
+ end
+
+ def cc
+ case toolchain
+ when :gcc then bin_gcc('gcc')
+ when :clang then bin('clang')
+ end
+ end
+
+ def ar
+ case toolchain
+ when :gcc then bin_gcc('ar')
+ when :clang then bin_gcc('ar')
+ end
+ end
+
+ def ctarget
+ flags = []
+
+ case toolchain
+ when :gcc
+ case arch
+ when /armeabi-v7a/ then flags += %W(-march=armv7-a)
+ when /armeabi/ then flags += %W(-march=armv5te)
+ when /arm64-v8a/ then flags += %W(-march=armv8-a)
+ when /x86_64/ then flags += %W(-march=x86-64)
+ when /x86/ then flags += %W(-march=i686)
+ when /mips64/ then flags += %W(-march=mips64r6)
+ when /mips/ then flags += %W(-march=mips32)
+ end
+ when :clang
+ case arch
+ when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi)
+ when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi)
+ when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android)
+ when /x86_64/ then flags += %W(-target x86_64-none-linux-android)
+ when /x86/ then flags += %W(-target i686-none-linux-android)
+ when /mips64/ then flags += %W(-target mips64el-none-linux-android)
+ when /mips/ then flags += %W(-target mipsel-none-linux-android)
+ end
+ end
+
+ case arch
+ when /armeabi-v7a/ then flags += %W(-mfpu=#{armeabi_v7a_mfpu} -mfloat-abi=#{armeabi_v7a_mfloat_abi})
+ when /armeabi/ then flags += %W(-mtune=xscale -msoft-float)
+ when /arm64-v8a/ then flags += %W()
+ when /x86_64/ then flags += %W()
+ when /x86/ then flags += %W()
+ when /mips64/ then flags += %W(-fmessage-length=0)
+ when /mips/ then flags += %W(-fmessage-length=0)
+ end
+
+ flags
+ end
+
+ def cflags
+ flags = []
+
+ flags += %W(-MMD -MP -D__android__ -DANDROID --sysroot="#{sysroot}")
+ flags += ctarget
+ case toolchain
+ when :gcc
+ when :clang
+ flags += %W(-gcc-toolchain "#{gcc_toolchain_path}" -Wno-invalid-command-line-argument -Wno-unused-command-line-argument)
+ end
+ flags += %W(-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes)
+
+ flags
+ end
+
+ def ldflags
+ flags = []
+
+ flags += %W(--sysroot="#{sysroot}")
+
+ flags
+ end
+
+ def ldflags_before_libraries
+ flags = []
+
+ case toolchain
+ when :gcc
+ case arch
+ when /armeabi-v7a/ then flags += %W(-Wl#{no_warn_mismatch})
+ end
+ when :clang
+ flags += %W(-gcc-toolchain "#{gcc_toolchain_path.to_s}")
+ case arch
+ when /armeabi-v7a/ then flags += %W(-target armv7-none-linux-androideabi -Wl,--fix-cortex-a8#{no_warn_mismatch})
+ when /armeabi/ then flags += %W(-target armv5te-none-linux-androideabi)
+ when /arm64-v8a/ then flags += %W(-target aarch64-none-linux-android)
+ when /x86_64/ then flags += %W(-target x86_64-none-linux-android)
+ when /x86/ then flags += %W(-target i686-none-linux-android)
+ when /mips64/ then flags += %W(-target mips64el-none-linux-android)
+ when /mips/ then flags += %W(-target mipsel-none-linux-android)
+ end
+ end
+ flags += %W(-no-canonical-prefixes)
+
+ flags
+ end
+end
+
+MRuby::Toolchain.new(:android) do |conf, params|
+ android = MRuby::Toolchain::Android.new(params)
+
+ toolchain android.toolchain
+
+ [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc|
+ cc.command = android.cc
+ cc.flags = android.cflags
+ end
+
+ conf.archiver.command = android.ar
+ conf.linker.command = android.cc
+ conf.linker.flags = android.ldflags
+ conf.linker.flags_before_libraries = android.ldflags_before_libraries
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/clang.rake b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/clang.rake
new file mode 100644
index 00000000..c75fa030
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/clang.rake
@@ -0,0 +1,9 @@
+MRuby::Toolchain.new(:clang) do |conf, _params|
+ toolchain :gcc
+
+ [conf.cc, conf.objc, conf.asm].each do |cc|
+ cc.command = ENV['CC'] || 'clang'
+ end
+ conf.cxx.command = ENV['CXX'] || 'clang++'
+ conf.linker.command = ENV['LD'] || 'clang'
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/gcc.rake b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/gcc.rake
new file mode 100644
index 00000000..f370c0ab
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/gcc.rake
@@ -0,0 +1,58 @@
+MRuby::Toolchain.new(:gcc) do |conf, _params|
+ [conf.cc, conf.objc, conf.asm].each do |cc|
+ cc.command = ENV['CC'] || 'gcc'
+ cc.flags = [ENV['CFLAGS'] || %w(-g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings)]
+ cc.defines = %w(DISABLE_GEMS)
+ cc.option_include_path = '-I%s'
+ cc.option_define = '-D%s'
+ cc.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}'
+ cc.cxx_compile_flag = '-x c++ -std=c++03'
+ cc.cxx_exception_flag = '-fexceptions'
+ end
+
+ [conf.cxx].each do |cxx|
+ cxx.command = ENV['CXX'] || 'g++'
+ cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(-g -O3 -Wall -Werror-implicit-function-declaration)]
+ cxx.defines = %w(DISABLE_GEMS)
+ cxx.option_include_path = '-I%s'
+ cxx.option_define = '-D%s'
+ cxx.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}'
+ cxx.cxx_compile_flag = '-x c++ -std=c++03'
+ cxx.cxx_exception_flag = '-fexceptions'
+ end
+
+ conf.linker do |linker|
+ linker.command = ENV['LD'] || 'gcc'
+ linker.flags = [ENV['LDFLAGS'] || %w()]
+ linker.libraries = %w(m)
+ linker.library_paths = []
+ linker.option_library = '-l%s'
+ linker.option_library_path = '-L%s'
+ linker.link_options = '%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}'
+ end
+
+ [[conf.cc, 'c'], [conf.cxx, 'c++']].each do |cc, lang|
+ cc.instance_variable_set :@header_search_language, lang
+ def cc.header_search_paths
+ if @header_search_command != command
+ result = `echo | #{build.filename command} -x#{@header_search_language} -Wp,-v - -fsyntax-only 2>&1`
+ result = `echo | #{command} -x#{@header_search_language} -Wp,-v - -fsyntax-only 2>&1` if $?.exitstatus != 0
+ return include_paths if $?.exitstatus != 0
+
+ @frameworks = []
+ @header_search_paths = result.lines.map { |v|
+ framework = v.match(/^ (.*)(?: \(framework directory\))$/)
+ if framework
+ @frameworks << framework[1]
+ next nil
+ end
+
+ v.match(/^ (.*)$/)
+ }.compact.map { |v| v[1] }.select { |v| File.directory? v }
+ @header_search_paths += include_paths
+ @header_search_command = command
+ end
+ @header_search_paths
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/openwrt.rake b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/openwrt.rake
new file mode 100644
index 00000000..1637f6d9
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/openwrt.rake
@@ -0,0 +1,38 @@
+# usage of environmental variables to set the
+# cross compiling toolchain proper
+MRuby::Toolchain.new(:openwrt) do |conf|
+ [conf.cc, conf.objc, conf.asm].each do |cc|
+ cc.command = ENV['TARGET_CC']
+ cc.flags = ENV['TARGET_CFLAGS']
+ cc.include_paths = ["#{MRUBY_ROOT}/include"]
+ cc.defines = %w(DISABLE_GEMS)
+ cc.option_include_path = '-I%s'
+ cc.option_define = '-D%s'
+ cc.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}'
+ end
+
+ [conf.cxx].each do |cxx|
+ cxx.command = ENV['TARGET_CXX']
+ cxx.flags = ENV['TARGET_CXXFLAGS']
+ cxx.include_paths = ["#{MRUBY_ROOT}/include"]
+ cxx.defines = %w(DISABLE_GEMS)
+ cxx.option_include_path = '-I%s'
+ cxx.option_define = '-D%s'
+ cxx.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}'
+ end
+
+ conf.linker do |linker|
+ linker.command = ENV['TARGET_CC']
+ linker.flags = ENV['TARGET_LDFLAGS']
+ linker.libraries = %w(m)
+ linker.library_paths = []
+ linker.option_library = '-l%s'
+ linker.option_library_path = '-L%s'
+ linker.link_options = '%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}'
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = ENV['TARGET_AR']
+ archiver.archive_options = 'rs %{outfile} %{objs}'
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/visualcpp.rake b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/visualcpp.rake
new file mode 100644
index 00000000..5bc24a73
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/tasks/toolchains/visualcpp.rake
@@ -0,0 +1,68 @@
+MRuby::Toolchain.new(:visualcpp) do |conf, _params|
+ conf.cc do |cc|
+ cc.command = ENV['CC'] || 'cl.exe'
+ # C4013: implicit function declaration
+ cc.flags = [ENV['CFLAGS'] || %w(/c /nologo /W3 /we4013 /Zi /MD /O2 /D_CRT_SECURE_NO_WARNINGS)]
+ cc.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING)
+ cc.option_include_path = '/I%s'
+ cc.option_define = '/D%s'
+ cc.compile_options = "%{flags} /Fo%{outfile} %{infile}"
+ cc.cxx_compile_flag = '/TP'
+ cc.cxx_exception_flag = '/EHs'
+ end
+
+ conf.cxx do |cxx|
+ cxx.command = ENV['CXX'] || 'cl.exe'
+ cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(/c /nologo /W3 /Zi /MD /O2 /EHs /D_CRT_SECURE_NO_WARNINGS)]
+ cxx.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING)
+ cxx.option_include_path = '/I%s'
+ cxx.option_define = '/D%s'
+ cxx.compile_options = "%{flags} /Fo%{outfile} %{infile}"
+ cxx.cxx_compile_flag = '/TP'
+ cxx.cxx_exception_flag = '/EHs'
+ end
+
+ conf.linker do |linker|
+ linker.command = ENV['LD'] || 'link.exe'
+ linker.flags = [ENV['LDFLAGS'] || %w(/NOLOGO /DEBUG /INCREMENTAL:NO /OPT:ICF /OPT:REF)]
+ linker.libraries = %w()
+ linker.library_paths = %w()
+ linker.option_library = '%s.lib'
+ linker.option_library_path = '/LIBPATH:%s'
+ linker.link_options = "%{flags} /OUT:%{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}"
+ end
+
+ conf.archiver do |archiver|
+ archiver.command = ENV['AR'] || 'lib.exe'
+ archiver.archive_options = '/nologo /OUT:%{outfile} %{objs}'
+ end
+
+ conf.yacc do |yacc|
+ yacc.command = ENV['YACC'] || 'bison.exe'
+ yacc.compile_options = '-o %{outfile} %{infile}'
+ end
+
+ conf.gperf do |gperf|
+ gperf.command = 'gperf.exe'
+ gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}'
+ end
+
+ conf.exts do |exts|
+ exts.object = '.obj'
+ exts.executable = '.exe'
+ exts.library = '.lib'
+ end
+
+ conf.file_separator = '\\'
+
+ if require 'open3'
+ Open3.popen3 conf.cc.command do |_, _, e, _|
+ if /Version (\d{2})\.\d{2}\.\d{5}/ =~ e.gets && $1.to_i <= 17
+ m = "# VS2010/2012 support will be dropped after the next release! #"
+ h = "#" * m.length
+ puts h, m, h
+ end
+ end
+ end
+
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/assert.rb b/web/server/h2o/libh2o/deps/mruby/test/assert.rb
new file mode 100644
index 00000000..fb7ae9ab
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/assert.rb
@@ -0,0 +1,248 @@
+$ok_test = 0
+$ko_test = 0
+$kill_test = 0
+$asserts = []
+$test_start = Time.now if Object.const_defined?(:Time)
+
+# Implementation of print due to the reason that there might be no print
+def t_print(*args)
+ i = 0
+ len = args.size
+ while i < len
+ str = args[i].to_s
+ __t_printstr__ str rescue print str
+ i += 1
+ end
+end
+
+##
+# Create the assertion in a readable way
+def assertion_string(err, str, iso=nil, e=nil, bt=nil)
+ msg = "#{err}#{str}"
+ msg += " [#{iso}]" if iso && iso != ''
+ msg += " => #{e.message}" if e
+ msg += " (mrbgems: #{GEMNAME})" if Object.const_defined?(:GEMNAME)
+ if $mrbtest_assert && $mrbtest_assert.size > 0
+ $mrbtest_assert.each do |idx, assert_msg, diff|
+ msg += "\n - Assertion[#{idx}] Failed: #{assert_msg}\n#{diff}"
+ end
+ end
+ msg += "\nbacktrace:\n\t#{bt.join("\n\t")}" if bt
+ msg
+end
+
+##
+# Verify a code block.
+#
+# str : A remark which will be printed in case
+# this assertion fails
+# iso : The ISO reference code of the feature
+# which will be tested by this
+# assertion
+def assert(str = 'Assertion failed', iso = '')
+ t_print(str, (iso != '' ? " [#{iso}]" : ''), ' : ') if $mrbtest_verbose
+ begin
+ $mrbtest_assert = []
+ $mrbtest_assert_idx = 0
+ yield
+ if($mrbtest_assert.size > 0)
+ $asserts.push(assertion_string('Fail: ', str, iso, nil))
+ $ko_test += 1
+ t_print('F')
+ else
+ $ok_test += 1
+ t_print('.')
+ end
+ rescue Exception => e
+ bt = e.backtrace if $mrbtest_verbose
+ if e.class.to_s == 'MRubyTestSkip'
+ $asserts.push "Skip: #{str} #{iso} #{e.cause}"
+ t_print('?')
+ else
+ $asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt))
+ $kill_test += 1
+ t_print('X')
+ end
+ ensure
+ $mrbtest_assert = nil
+ end
+ t_print("\n") if $mrbtest_verbose
+end
+
+def assertion_diff(exp, act)
+ " Expected: #{exp.inspect}\n" +
+ " Actual: #{act.inspect}"
+end
+
+def assert_true(ret, msg = nil, diff = nil)
+ if $mrbtest_assert
+ $mrbtest_assert_idx += 1
+ unless ret
+ msg = "Expected #{ret.inspect} to be true" unless msg
+ diff = assertion_diff(true, ret) unless diff
+ $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff])
+ end
+ end
+ ret
+end
+
+def assert_false(ret, msg = nil, diff = nil)
+ if $mrbtest_assert
+ $mrbtest_assert_idx += 1
+ if ret
+ msg = "Expected #{ret.inspect} to be false" unless msg
+ diff = assertion_diff(false, ret) unless diff
+
+ $mrbtest_assert.push([$mrbtest_assert_idx, msg, diff])
+ end
+ end
+ !ret
+end
+
+def assert_equal(arg1, arg2 = nil, arg3 = nil)
+ if block_given?
+ exp, act, msg = arg1, yield, arg2
+ else
+ exp, act, msg = arg1, arg2, arg3
+ end
+
+ msg = "Expected to be equal" unless msg
+ diff = assertion_diff(exp, act)
+ assert_true(exp == act, msg, diff)
+end
+
+def assert_not_equal(arg1, arg2 = nil, arg3 = nil)
+ if block_given?
+ exp, act, msg = arg1, yield, arg2
+ else
+ exp, act, msg = arg1, arg2, arg3
+ end
+
+ msg = "Expected to be not equal" unless msg
+ diff = assertion_diff(exp, act)
+ assert_false(exp == act, msg, diff)
+end
+
+def assert_nil(obj, msg = nil)
+ msg = "Expected #{obj.inspect} to be nil" unless msg
+ diff = assertion_diff(nil, obj)
+ assert_true(obj.nil?, msg, diff)
+end
+
+def assert_include(collection, obj, msg = nil)
+ msg = "Expected #{collection.inspect} to include #{obj.inspect}" unless msg
+ diff = " Collection: #{collection.inspect}\n" +
+ " Object: #{obj.inspect}"
+ assert_true(collection.include?(obj), msg, diff)
+end
+
+def assert_not_include(collection, obj, msg = nil)
+ msg = "Expected #{collection.inspect} to not include #{obj.inspect}" unless msg
+ diff = " Collection: #{collection.inspect}\n" +
+ " Object: #{obj.inspect}"
+ assert_false(collection.include?(obj), msg, diff)
+end
+
+def assert_raise(*exc)
+ return true unless $mrbtest_assert
+ $mrbtest_assert_idx += 1
+
+ msg = (exc.last.is_a? String) ? exc.pop : nil
+
+ begin
+ yield
+ msg ||= "Expected to raise #{exc} but nothing was raised."
+ diff = nil
+ $mrbtest_assert.push [$mrbtest_assert_idx, msg, diff]
+ false
+ rescue *exc
+ true
+ rescue Exception => e
+ msg ||= "Expected to raise #{exc}, not"
+ diff = " Class: <#{e.class}>\n" +
+ " Message: #{e.message}"
+ $mrbtest_assert.push [$mrbtest_assert_idx, msg, diff]
+ false
+ end
+end
+
+def assert_nothing_raised(msg = nil)
+ return true unless $mrbtest_assert
+ $mrbtest_assert_idx += 1
+
+ begin
+ yield
+ true
+ rescue Exception => e
+ msg ||= "Expected not to raise #{exc.join(', ')} but it raised"
+ diff = " Class: <#{e.class}>\n" +
+ " Message: #{e.message}"
+ $mrbtest_assert.push [$mrbtest_assert_idx, msg, diff]
+ false
+ end
+end
+
+##
+# Fails unless +obj+ is a kind of +cls+.
+def assert_kind_of(cls, obj, msg = nil)
+ msg = "Expected #{obj.inspect} to be a kind of #{cls}, not #{obj.class}" unless msg
+ diff = assertion_diff(cls, obj.class)
+ assert_true(obj.kind_of?(cls), msg, diff)
+end
+
+##
+# Fails unless +exp+ is equal to +act+ in terms of a Float
+def assert_float(exp, act, msg = nil)
+ msg = "Float #{exp} expected to be equal to float #{act}" unless msg
+ diff = assertion_diff(exp, act)
+ assert_true check_float(exp, act), msg, diff
+end
+
+##
+# Report the test result and print all assertions
+# which were reported broken.
+def report()
+ t_print("\n")
+
+ $asserts.each do |msg|
+ t_print "#{msg}\n"
+ end
+
+ $total_test = $ok_test+$ko_test+$kill_test
+ t_print("Total: #{$total_test}\n")
+
+ t_print(" OK: #{$ok_test}\n")
+ t_print(" KO: #{$ko_test}\n")
+ t_print("Crash: #{$kill_test}\n")
+
+ if Object.const_defined?(:Time)
+ t_time = Time.now - $test_start
+ t_print(" Time: #{t_time.round(2)} seconds\n")
+ end
+end
+
+##
+# Performs fuzzy check for equality on methods returning floats
+def check_float(a, b)
+ tolerance = Mrbtest::FLOAT_TOLERANCE
+ a = a.to_f
+ b = b.to_f
+ if a.finite? and b.finite?
+ (a-b).abs < tolerance
+ else
+ true
+ end
+end
+
+##
+# Skip the test
+class MRubyTestSkip < NotImplementedError
+ attr_accessor :cause
+ def initialize(cause)
+ @cause = cause
+ end
+end
+
+def skip(cause = "")
+ raise MRubyTestSkip.new(cause)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/bintest.rb b/web/server/h2o/libh2o/deps/mruby/test/bintest.rb
new file mode 100644
index 00000000..12971a9d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/bintest.rb
@@ -0,0 +1,33 @@
+$:.unshift File.dirname(File.dirname(File.expand_path(__FILE__)))
+require 'test/assert.rb'
+
+def cmd(s)
+ case RbConfig::CONFIG['host_os']
+ when /mswin(?!ce)|mingw|bccwin/
+ "bin\\#{s}.exe"
+ else
+ "bin/#{s}"
+ end
+end
+
+def shellquote(s)
+ case RbConfig::CONFIG['host_os']
+ when /mswin(?!ce)|mingw|bccwin/
+ "\"#{s}\""
+ else
+ "'#{s}'"
+ end
+end
+
+ARGV.each do |gem|
+ case RbConfig::CONFIG['host_os']
+ when /mswin(?!ce)|mingw|bccwin/
+ gem = gem.gsub('\\', '/')
+ end
+
+ Dir["#{gem}/bintest/**/*.rb"].each do |file|
+ load file
+ end
+end
+
+load 'test/report.rb'
diff --git a/web/server/h2o/libh2o/deps/mruby/test/report.rb b/web/server/h2o/libh2o/deps/mruby/test/report.rb
new file mode 100644
index 00000000..fb77fd0a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/report.rb
@@ -0,0 +1,4 @@
+report
+if $ko_test > 0 or $kill_test > 0
+ raise "mrbtest failed (KO:#{$ko_test}, Crash:#{$kill_test})"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/argumenterror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/argumenterror.rb
new file mode 100644
index 00000000..abb53429
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/argumenterror.rb
@@ -0,0 +1,16 @@
+##
+# ArgumentError ISO Test
+
+assert('ArgumentError', '15.2.24') do
+ e2 = nil
+ a = []
+ begin
+ # this will cause an exception due to the wrong arguments
+ a[]
+ rescue => e1
+ e2 = e1
+ end
+
+ assert_equal(Class, ArgumentError.class)
+ assert_equal(ArgumentError, e2.class)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/array.rb b/web/server/h2o/libh2o/deps/mruby/test/t/array.rb
new file mode 100644
index 00000000..7c11265a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/array.rb
@@ -0,0 +1,394 @@
+##
+# Array ISO Test
+
+assert('Array', '15.2.12') do
+ assert_equal(Class, Array.class)
+end
+
+assert('Array inclueded modules', '15.2.12.3') do
+ assert_true(Array.include?(Enumerable))
+end
+
+assert('Array.[]', '15.2.12.4.1') do
+ assert_equal([1, 2, 3], Array.[](1,2,3))
+end
+
+class SubArray < Array
+end
+
+assert('SubArray.[]') do
+ a = SubArray[1, 2, 3]
+ assert_equal(SubArray, a.class)
+end
+
+assert('Array#+', '15.2.12.5.1') do
+ assert_equal([1, 1], [1].+([1]))
+end
+
+assert('Array#*', '15.2.12.5.2') do
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong argument
+ [1].*(-1)
+ end
+ assert_equal([1, 1, 1], [1].*(3))
+ assert_equal([], [1].*(0))
+end
+
+assert('Array#<<', '15.2.12.5.3') do
+ assert_equal([1, 1], [1].<<(1))
+end
+
+assert('Array#[]', '15.2.12.5.4') do
+ a = Array.new
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong arguments
+ a.[]()
+ end
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong arguments
+ a.[](1,2,3)
+ end
+
+ assert_equal(2, [1,2,3].[](1))
+ assert_equal(nil, [1,2,3].[](4))
+ assert_equal(3, [1,2,3].[](-1))
+ assert_equal(nil, [1,2,3].[](-4))
+
+ a = [ "a", "b", "c", "d", "e" ]
+ assert_equal("b", a[1.1])
+ assert_equal(["b", "c"], a[1,2])
+ assert_equal(["b", "c", "d"], a[1..-2])
+end
+
+assert('Array#[]=', '15.2.12.5.5') do
+ a = Array.new
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong arguments
+ a.[]=()
+ end
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong arguments
+ a.[]=(1,2,3,4)
+ end
+ assert_raise(IndexError) do
+ # this will cause an exception due to the wrong arguments
+ a = [1,2,3,4,5]
+ a[1, -1] = 10
+ end
+
+ assert_equal(4, [1,2,3].[]=(1,4))
+ assert_equal(3, [1,2,3].[]=(1,2,3))
+
+ a = [1,2,3,4,5]
+ a[3..-1] = 6
+ assert_equal([1,2,3,6], a)
+
+ a = [1,2,3,4,5]
+ a[3..-1] = []
+ assert_equal([1,2,3], a)
+
+ a = [1,2,3,4,5]
+ a[2...4] = 6
+ assert_equal([1,2,6,5], a)
+
+ # passing self (#3274)
+ a = [1,2,3]
+ a[1,0] = a
+ assert_equal([1,1,2,3,2,3], a)
+ a = [1,2,3]
+ a[-1,0] = a
+ assert_equal([1,2,1,2,3,3], a)
+end
+
+assert('Array#clear', '15.2.12.5.6') do
+ a = [1]
+ a.clear
+ assert_equal([], a)
+end
+
+assert('Array#collect!', '15.2.12.5.7') do
+ a = [1,2,3]
+ a.collect! { |i| i + i }
+ assert_equal([2,4,6], a)
+end
+
+assert('Array#concat', '15.2.12.5.8') do
+ assert_equal([1,2,3,4], [1, 2].concat([3, 4]))
+
+ # passing self (#3302)
+ a = [1,2,3]
+ a.concat(a)
+ assert_equal([1,2,3,1,2,3], a)
+end
+
+assert('Array#delete_at', '15.2.12.5.9') do
+ a = [1,2,3]
+ assert_equal(2, a.delete_at(1))
+ assert_equal([1,3], a)
+ assert_equal(nil, a.delete_at(3))
+ assert_equal([1,3], a)
+ assert_equal(nil, a.delete_at(-3))
+ assert_equal([1,3], a)
+ assert_equal(3, a.delete_at(-1))
+ assert_equal([1], a)
+end
+
+assert('Array#each', '15.2.12.5.10') do
+ a = [1,2,3]
+ b = 0
+ a.each {|i| b += i}
+ assert_equal(6, b)
+end
+
+assert('Array#each_index', '15.2.12.5.11') do
+ a = [1]
+ b = nil
+ a.each_index {|i| b = i}
+ assert_equal(0, b)
+end
+
+assert('Array#empty?', '15.2.12.5.12') do
+ a = []
+ b = [b]
+ assert_true([].empty?)
+ assert_false([1].empty?)
+end
+
+assert('Array#first', '15.2.12.5.13') do
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong argument
+ [1,2,3].first(-1)
+ end
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong argument
+ [1,2,3].first(1,2)
+ end
+
+ assert_nil([].first)
+
+ b = [1,2,3]
+ assert_equal(1, b.first)
+ assert_equal([], b.first(0))
+ assert_equal([1], b.first(1))
+ assert_equal([1,2,3], b.first(4))
+end
+
+assert('Array#index', '15.2.12.5.14') do
+ a = [1,2,3]
+
+ assert_equal(1, a.index(2))
+ assert_equal(nil, a.index(0))
+end
+
+assert('Array#initialize', '15.2.12.5.15') do
+ a = [].initialize(1)
+ b = [].initialize(2)
+ c = [].initialize(2, 1)
+ d = [].initialize(2) {|i| i}
+
+ assert_equal([nil], a)
+ assert_equal([nil,nil], b)
+ assert_equal([1,1], c)
+ assert_equal([0,1], d)
+end
+
+assert('Array#initialize_copy', '15.2.12.5.16') do
+ a = [1,2,3]
+ b = [].initialize_copy(a)
+
+ assert_equal([1,2,3], b)
+end
+
+assert('Array#join', '15.2.12.5.17') do
+ a = [1,2,3].join
+ b = [1,2,3].join(',')
+
+ assert_equal('123', a)
+ assert_equal('1,2,3', b)
+end
+
+assert('Array#last', '15.2.12.5.18') do
+ assert_raise(ArgumentError) do
+ # this will cause an exception due to the wrong argument
+ [1,2,3].last(-1)
+ end
+
+ a = [1,2,3]
+ assert_equal(3, a.last)
+ assert_nil([].last)
+end
+
+assert('Array#length', '15.2.12.5.19') do
+ a = [1,2,3]
+
+ assert_equal(3, a.length)
+end
+
+assert('Array#map!', '15.2.12.5.20') do
+ a = [1,2,3]
+ a.map! { |i| i + i }
+ assert_equal([2,4,6], a)
+end
+
+assert('Array#pop', '15.2.12.5.21') do
+ a = [1,2,3]
+ b = a.pop
+
+ assert_nil([].pop)
+ assert_equal([1,2], a)
+ assert_equal(3, b)
+
+ assert_raise(RuntimeError) { [].freeze.pop }
+end
+
+assert('Array#push', '15.2.12.5.22') do
+ a = [1,2,3]
+ b = a.push(4)
+
+ assert_equal([1,2,3,4], a)
+ assert_equal([1,2,3,4], b)
+end
+
+assert('Array#replace', '15.2.12.5.23') do
+ a = [1,2,3]
+ b = [].replace(a)
+
+ assert_equal([1,2,3], b)
+end
+
+assert('Array#reverse', '15.2.12.5.24') do
+ a = [1,2,3]
+ b = a.reverse
+
+ assert_equal([1,2,3], a)
+ assert_equal([3,2,1], b)
+end
+
+assert('Array#reverse!', '15.2.12.5.25') do
+ a = [1,2,3]
+ b = a.reverse!
+
+ assert_equal([3,2,1], a)
+ assert_equal([3,2,1], b)
+end
+
+assert('Array#rindex', '15.2.12.5.26') do
+ a = [1,2,3]
+
+ assert_equal(1, a.rindex(2))
+ assert_equal(nil, a.rindex(0))
+end
+
+assert('Array#shift', '15.2.12.5.27') do
+ a = [1,2,3]
+ b = a.shift
+
+ assert_nil([].shift)
+ assert_equal([2,3], a)
+ assert_equal(1, b)
+
+ assert_raise(RuntimeError) { [].freeze.shift }
+end
+
+assert('Array#size', '15.2.12.5.28') do
+ a = [1,2,3]
+
+ assert_equal(3, a.size)
+end
+
+assert('Array#slice', '15.2.12.5.29') do
+ a = "12345".slice(1, 3)
+ b = a.slice(0)
+
+ assert_equal("2:", "#{b}:")
+ assert_equal(2, [1,2,3].[](1))
+end
+
+assert('Array#unshift', '15.2.12.5.30') do
+ a = [2,3]
+ b = a.unshift(1)
+ c = [2,3]
+ d = c.unshift(0, 1)
+
+ assert_equal([1,2,3], a)
+ assert_equal([1,2,3], b)
+ assert_equal([0,1,2,3], c)
+ assert_equal([0,1,2,3], d)
+end
+
+assert('Array#to_s', '15.2.12.5.31 / 15.2.12.5.32') do
+ a = [2, 3, 4, 5]
+ r1 = a.to_s
+ r2 = a.inspect
+
+ assert_equal(r2, r1)
+ assert_equal("[2, 3, 4, 5]", r1)
+end
+
+assert('Array#==', '15.2.12.5.33') do
+ assert_false(["a", "c"] == ["a", "c", 7])
+ assert_true(["a", "c", 7] == ["a", "c", 7])
+ assert_false(["a", "c", 7] == ["a", "d", "f"])
+end
+
+assert('Array#eql?', '15.2.12.5.34') do
+ a1 = [ 1, 2, 3 ]
+ a2 = [ 1, 2, 3 ]
+ a3 = [ 1.0, 2.0, 3.0 ]
+
+ assert_true(a1.eql? a2)
+ assert_false(a1.eql? a3)
+end
+
+assert('Array#hash', '15.2.12.5.35') do
+ a = [ 1, 2, 3 ]
+
+ #assert_true(a.hash.is_a? Integer)
+ assert_true(a.hash.is_a? Integral) # mruby special
+ assert_equal([1,2].hash, [1,2].hash)
+end
+
+assert('Array#<=>', '15.2.12.5.36') do
+ r1 = [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
+ r2 = [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
+ r3 = [ "a", "b", "c" ] <=> [ "a", "b", "c" ] #=> 0
+
+ assert_equal(-1, r1)
+ assert_equal(+1, r2)
+ assert_equal(0, r3)
+end
+
+# Not ISO specified
+
+assert("Array (Shared Array Corruption)") do
+ a = [ "a", "b", "c", "d", "e", "f" ]
+ b = a.slice(1, 3)
+ a.clear
+ b.clear
+end
+
+assert("Array (Longish inline array)") do
+ ary = [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 9], [10, 10], [11, 11], [12, 12], [13, 13], [14, 14], [15, 15], [16, 16], [17, 17], [18, 18], [19, 19], [20, 20], [21, 21], [22, 22], [23, 23], [24, 24], [25, 25], [26, 26], [27, 27], [28, 28], [29, 29], [30, 30], [31, 31], [32, 32], [33, 33], [34, 34], [35, 35], [36, 36], [37, 37], [38, 38], [39, 39], [40, 40], [41, 41], [42, 42], [43, 43], [44, 44], [45, 45], [46, 46], [47, 47], [48, 48], [49, 49], [50, 50], [51, 51], [52, 52], [53, 53], [54, 54], [55, 55], [56, 56], [57, 57], [58, 58], [59, 59], [60, 60], [61, 61], [62, 62], [63, 63], [64, 64], [65, 65], [66, 66], [67, 67], [68, 68], [69, 69], [70, 70], [71, 71], [72, 72], [73, 73], [74, 74], [75, 75], [76, 76], [77, 77], [78, 78], [79, 79], [80, 80], [81, 81], [82, 82], [83, 83], [84, 84], [85, 85], [86, 86], [87, 87], [88, 88], [89, 89], [90, 90], [91, 91], [92, 92], [93, 93], [94, 94], [95, 95], [96, 96], [97, 97], [98, 98], [99, 99], [100, 100], [101, 101], [102, 102], [103, 103], [104, 104], [105, 105], [106, 106], [107, 107], [108, 108], [109, 109], [110, 110], [111, 111], [112, 112], [113, 113], [114, 114], [115, 115], [116, 116], [117, 117], [118, 118], [119, 119], [120, 120], [121, 121], [122, 122], [123, 123], [124, 124], [125, 125], [126, 126], [127, 127], [128, 128], [129, 129], [130, 130], [131, 131], [132, 132], [133, 133], [134, 134], [135, 135], [136, 136], [137, 137], [138, 138], [139, 139], [140, 140], [141, 141], [142, 142], [143, 143], [144, 144], [145, 145], [146, 146], [147, 147], [148, 148], [149, 149], [150, 150], [151, 151], [152, 152], [153, 153], [154, 154], [155, 155], [156, 156], [157, 157], [158, 158], [159, 159], [160, 160], [161, 161], [162, 162], [163, 163], [164, 164], [165, 165], [166, 166], [167, 167], [168, 168], [169, 169], [170, 170], [171, 171], [172, 172], [173, 173], [174, 174], [175, 175], [176, 176], [177, 177], [178, 178], [179, 179], [180, 180], [181, 181], [182, 182], [183, 183], [184, 184], [185, 185], [186, 186], [187, 187], [188, 188], [189, 189], [190, 190], [191, 191], [192, 192], [193, 193], [194, 194], [195, 195], [196, 196], [197, 197], [198, 198], [199, 199]]
+ h = Hash.new(0)
+ ary.each {|p| h[p.class] += 1}
+ assert_equal({Array=>200}, h)
+end
+
+assert("Array#rindex") do
+ class Sneaky
+ def ==(*)
+ $a.clear
+ $a.replace([1])
+ false
+ end
+ end
+ $a = [2, 3, 4, 5, 6, 7, 8, 9, 10, Sneaky.new]
+ assert_equal 0, $a.rindex(1)
+end
+
+assert('Array#freeze') do
+ a = [].freeze
+ assert_raise(RuntimeError) do
+ a[0] = 1
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/basicobject.rb b/web/server/h2o/libh2o/deps/mruby/test/t/basicobject.rb
new file mode 100644
index 00000000..f3317126
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/basicobject.rb
@@ -0,0 +1,11 @@
+##
+# BasicObject
+
+assert('BasicObject') do
+ assert_equal(Class, BasicObject.class)
+end
+
+assert('BasicObject superclass') do
+ assert_nil(BasicObject.superclass)
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/bs_block.rb b/web/server/h2o/libh2o/deps/mruby/test/t/bs_block.rb
new file mode 100644
index 00000000..04a4a15b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/bs_block.rb
@@ -0,0 +1,521 @@
+##
+# Bootstrap tests for blocks
+
+assert('BS Block 1') do
+ assert_equal(1) do
+ 1.times{
+ begin
+ a = 1
+ ensure
+ foo = nil
+ end
+ }
+ end
+end
+
+assert('BS Block 2') do
+ assert_equal 2, [1,2,3].find{|x| x == 2}
+end
+
+assert('BS Block 3') do
+ class E
+ include Enumerable
+ def each(&block)
+ [1, 2, 3].each(&block)
+ end
+ end
+ assert_equal 2, E.new.find {|x| x == 2 }
+end
+
+assert('BS Block 3') do
+ sum = 0
+ for x in [1, 2, 3]
+ sum += x
+ end
+ assert_equal 6, sum
+end
+
+assert('BS Block 4') do
+ sum = 0
+ for x in (1..5)
+ sum += x
+ end
+ assert_equal 15, sum
+end
+
+assert('BS Block 5') do
+ sum = 0
+ for x in []
+ sum += x
+ end
+ assert_equal 0, sum
+end
+
+assert('BS Block 6') do
+ ans = []
+ assert_equal(1) do
+ 1.times{
+ for n in 1..3
+ a = n
+ ans << a
+ end
+ }
+ end
+end
+
+assert('BS Block 7') do
+ ans = []
+ assert_equal((1..3)) do
+ for m in 1..3
+ for n in 2..4
+ a = [m, n]
+ ans << a
+ end
+ end
+ end
+end
+
+assert('BS Block 8') do
+ assert_equal [1, 2, 3], (1..3).to_a
+end
+
+assert('BS Block 9') do
+ assert_equal([4, 8, 12]) do
+ (1..3).map{|e|
+ e * 4
+ }
+ end
+end
+
+assert('BS Block 10') do
+ def m
+ yield
+ end
+ def n
+ yield
+ end
+
+ assert_equal(100) do
+ m{
+ n{
+ 100
+ }
+ }
+ end
+end
+
+assert('BS Block 11') do
+ def m
+ yield 1
+ end
+
+ assert_equal(20) do
+ m{|ib|
+ m{|jb|
+ i = 20
+ }
+ }
+ end
+end
+
+assert('BS Block 12') do
+ def m
+ yield 1
+ end
+
+ assert_equal(2) do
+ m{|ib|
+ m{|jb|
+ ib = 20
+ kb = 2
+ }
+ }
+ end
+end
+
+assert('BS Block 13') do
+ def iter1
+ iter2{
+ yield
+ }
+ end
+
+ def iter2
+ yield
+ end
+
+ assert_equal(3) do
+ iter1{
+ jb = 2
+ iter1{
+ jb = 3
+ }
+ jb
+ }
+ end
+end
+
+assert('BS Block 14') do
+ def iter1
+ iter2{
+ yield
+ }
+ end
+
+ def iter2
+ yield
+ end
+
+ assert_equal(2) do
+ iter1{
+ jb = 2
+ iter1{
+ jb
+ }
+ jb
+ }
+ end
+end
+
+assert('BS Block 15') do
+ def m
+ yield 1
+ end
+ assert_equal(2) do
+ m{|ib|
+ ib*2
+ }
+ end
+end
+
+assert('BS Block 16') do
+ def m
+ yield 12345, 67890
+ end
+ assert_equal(92580) do
+ m{|ib,jb|
+ ib*2+jb
+ }
+ end
+end
+
+assert('BS Block 17') do
+ def iter
+ yield 10
+ end
+
+ a = nil
+ assert_equal [10, nil] do
+ [iter{|a|
+ a
+ }, a]
+ end
+end
+
+assert('BS Block 18') do
+ def iter
+ yield 10
+ end
+
+ assert_equal(21) do
+ iter{|a|
+ iter{|a|
+ a + 1
+ } + a
+ }
+ end
+end
+
+assert('BS Block 19') do
+ def iter
+ yield 10, 20, 30, 40
+ end
+
+ a = b = c = d = nil
+ assert_equal([10, 20, 30, 40, nil, nil, nil, nil]) do
+ iter{|a, b, c, d|
+ [a, b, c, d]
+ } + [a, b, c, d]
+ end
+end
+
+assert('BS Block 20') do
+ def iter
+ yield 10, 20, 30, 40
+ end
+
+ a = b = nil
+ assert_equal([10, 20, 30, 40, nil, nil]) do
+ iter{|a, b, c, d|
+ [a, b, c, d]
+ } + [a, b]
+ end
+end
+
+assert('BS Block 21') do
+ def iter
+ yield 1, 2
+ end
+
+ assert_equal([1, [2]]) do
+ iter{|a, *b|
+ [a, b]
+ }
+ end
+end
+
+assert('BS Block 22') do
+ def iter
+ yield 1, 2
+ end
+
+ assert_equal([[1, 2]]) do
+ iter{|*a|
+ [a]
+ }
+ end
+end
+
+assert('BS Block 23') do
+ def iter
+ yield 1, 2
+ end
+
+ assert_equal([1, 2, []]) do
+ iter{|a, b, *c|
+ [a, b, c]
+ }
+ end
+end
+
+assert('BS Block 24') do
+ def m
+ yield
+ end
+ assert_equal(1) do
+ m{
+ 1
+ }
+ end
+end
+
+assert('BS Block 25') do
+ def m
+ yield 123
+ end
+ assert_equal(15129) do
+ m{|ib|
+ m{|jb|
+ ib*jb
+ }
+ }
+ end
+end
+
+assert('BS Block 26') do
+ def m a
+ yield a
+ end
+ assert_equal(2) do
+ m(1){|ib|
+ m(2){|jb|
+ ib*jb
+ }
+ }
+ end
+end
+
+assert('BS Block 27') do
+ sum = 0
+ 3.times{|ib|
+ 2.times{|jb|
+ sum += ib + jb
+ }}
+ assert_equal sum, 9
+end
+
+assert('BS Block 28') do
+ assert_equal(10) do
+ 3.times{|bl|
+ break 10
+ }
+ end
+end
+
+assert('BS Block 29') do
+ def iter
+ yield 1,2,3
+ end
+
+ assert_equal([1, 2]) do
+ iter{|i, j|
+ [i, j]
+ }
+ end
+end
+
+assert('BS Block 30') do
+ def iter
+ yield 1
+ end
+
+ assert_equal([1, nil]) do
+ iter{|i, j|
+ [i, j]
+ }
+ end
+end
+
+assert('BS Block [ruby-dev:31147]') do
+ def m
+ yield
+ end
+ assert_nil m{|&b| b}
+end
+
+assert('BS Block [ruby-dev:31160]') do
+ def m()
+ yield
+ end
+ assert_nil m {|(v,(*))|}
+end
+
+assert('BS Block [issue #750]') do
+ def m(a, *b)
+ yield
+ end
+ args = [1, 2, 3]
+ assert_equal m(*args){ 1 }, 1
+end
+
+assert('BS Block 31') do
+ def m()
+ yield
+ end
+ assert_nil m {|((*))|}
+end
+
+assert('BS Block [ruby-dev:31440]') do
+ def m
+ yield [0]
+ end
+ assert_equal m{|v, &b| v}, [0]
+end
+
+assert('BS Block 32') do
+ r = false; 1.times{|&b| r = b}
+ assert_equal NilClass, r.class
+end
+
+assert('BS Block [ruby-core:14395]') do
+ class Controller
+ def respond_to(&block)
+ responder = Responder.new
+ block.call(responder)
+ responder.respond
+ end
+ def test_for_bug
+ respond_to{|format|
+ format.js{
+ "in test"
+ render{|obj|
+ obj
+ }
+ }
+ }
+ end
+ def render(&block)
+ "in render"
+ end
+ end
+
+ class Responder
+ def method_missing(symbol, &block)
+ "enter method_missing"
+ @response = Proc.new{
+ 'in method missing'
+ block.call
+ }
+ "leave method_missing"
+ end
+ def respond
+ @response.call
+ end
+ end
+ t = Controller.new
+ assert_true t.test_for_bug
+end
+
+assert("BS Block 33") do
+ module TestReturnFromNestedBlock
+ def self.test
+ 1.times do
+ 1.times do
+ return :ok
+ end
+ end
+ :bad
+ end
+ end
+ assert_equal :ok, TestReturnFromNestedBlock.test
+end
+
+assert("BS Block 34") do
+ module TestReturnFromNestedBlock_BSBlock34
+ def self.test
+ 1.times do
+ while true
+ return :ok
+ end
+ end
+ :bad
+ end
+ end
+ assert_equal :ok, TestReturnFromNestedBlock_BSBlock34.test
+end
+
+assert("BS Block 35") do
+ module TestReturnFromNestedBlock_BSBlock35
+ def self.test
+ 1.times do
+ until false
+ return :ok
+ end
+ end
+ :bad
+ end
+ end
+ assert_equal :ok, TestReturnFromNestedBlock_BSBlock35.test
+end
+
+assert('BS Block 36') do
+ def iter
+ yield 1, 2, 3, 4, 5
+ end
+
+ assert_equal([1, 2, [3, 4], 5]) do
+ iter{|a, b, *c, d|
+ [a, b, c, d]
+ }
+ end
+end
+
+assert('BS Block 37') do
+ def iter
+ yield 1, 2, 3
+ end
+
+ assert_equal([1, 2, [], 3]) do
+ iter{|a, b, *c, d|
+ [a, b, c, d]
+ }
+ end
+end
+
+assert('BS Block 38') do
+ def iter
+ yield 1,2,3,4,5,6
+ end
+
+ assert_equal [1,2,3,4,5], iter{|a,b,c=:c,d,e| [a,b,c,d,e]}
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/bs_literal.rb b/web/server/h2o/libh2o/deps/mruby/test/t/bs_literal.rb
new file mode 100644
index 00000000..c6c38140
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/bs_literal.rb
@@ -0,0 +1,38 @@
+##
+# Bootstrap test for literals
+
+assert('BS Literal 1') do
+ assert_true true
+end
+
+assert('BS Literal 2') do
+ assert_equal TrueClass, true.class
+end
+
+assert('BS Literal 3') do
+ assert_false false
+end
+
+assert('BS Literal 4') do
+ assert_equal FalseClass, false.class
+end
+
+assert('BS Literal 5') do
+ assert_equal 'nil', nil.inspect
+end
+
+assert('BS Literal 6') do
+ assert_equal NilClass, nil.class
+end
+
+assert('BS Literal 7') do
+ assert_equal Symbol, :sym.class
+end
+
+assert('BS Literal 8') do
+ assert_equal 1234, 1234
+end
+
+assert('BS Literal 9') do
+ assert_equal Fixnum, 1234.class
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/class.rb b/web/server/h2o/libh2o/deps/mruby/test/t/class.rb
new file mode 100644
index 00000000..eb077fce
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/class.rb
@@ -0,0 +1,451 @@
+##
+# Class ISO Test
+
+assert('Class', '15.2.3') do
+ assert_equal(Class, Class.class)
+end
+
+assert('Class#initialize', '15.2.3.3.1') do
+ c = Class.new do
+ def test
+ :test
+ end
+ end.new
+
+ assert_equal(c.test, :test)
+end
+
+assert('Class#initialize_copy', '15.2.3.3.2') do
+ class TestClass
+ attr_accessor :n
+ def initialize(n)
+ @n = n
+ end
+ def initialize_copy(obj)
+ @n = n
+ end
+ end
+
+ c1 = TestClass.new('Foo')
+ c2 = c1.dup
+ c3 = TestClass.new('Bar')
+
+ assert_equal(c1.n, c2.n)
+ assert_not_equal(c1.n, c3.n)
+end
+
+assert('Class#new', '15.2.3.3.3') do
+ assert_raise(TypeError, 'Singleton should raise TypeError') do
+ "a".singleton_class.new
+ end
+
+ class TestClass
+ def initialize args, &block
+ @result = if not args.nil? and block.nil?
+ # only arguments
+ :only_args
+ elsif not args.nil? and not block.nil?
+ # args and block is given
+ :args_and_block
+ else
+ # this should never happen
+ :broken
+ end
+ end
+
+ def result; @result; end
+ end
+
+ assert_equal(:only_args, TestClass.new(:arg).result)
+ # with block doesn't work yet
+end
+
+assert('Class#superclass', '15.2.3.3.4') do
+ class SubClass < String; end
+ assert_equal(String, SubClass.superclass)
+end
+
+# Not ISO specified
+
+assert('Class 1') do
+ class C1; end
+ assert_equal(Class, C1.class)
+end
+
+assert('Class 2') do
+ class C2; end
+ assert_equal(C2, C2.new.class)
+end
+
+assert('Class 3') do
+ class C3; end
+ assert_equal(Class, C3.new.class.class)
+end
+
+assert('Class 4') do
+ class C4_A; end
+ class C4 < C4_A; end
+ assert_equal(Class, C4.class)
+end
+
+assert('Class 5') do
+ class C5_A; end
+ class C5 < C5_A; end
+ assert_equal(C5, C5.new.class)
+end
+
+assert('Class 6') do
+ class C6_A; end
+ class C6 < C6_A; end
+ assert_equal(Class, C6.new.class.class)
+end
+
+assert('Class 7') do
+ class C7_A; end
+ class C7_B; end
+
+ class C7 < C7_A; end
+
+ assert_raise(TypeError) do
+ # Different superclass.
+ class C7 < C7_B; end
+ end
+end
+
+assert('Class 8') do
+ class C8_A; end
+
+ class C8; end # superclass is Object
+
+ assert_raise(TypeError) do
+ # Different superclass.
+ class C8 < C8_A; end
+ end
+end
+
+assert('Class 9') do
+ Class9Const = "a"
+
+ assert_raise(TypeError) do
+ class Class9Const; end
+ end
+end
+
+assert('Class Module 1') do
+ module M; end
+ assert_equal(Module, M.class)
+end
+
+assert('Class Module 2') do
+ module M; end
+ class C; include M; end
+ assert_equal(C, C.new.class)
+end
+
+# nested class
+assert('Class Nested 1') do
+ class A; end
+ class A::B; end
+ assert_equal(A::B, A::B)
+end
+
+assert('Class Nested 2') do
+ class A; end
+ class A::B; end
+ assert_equal(A::B, A::B.new.class)
+end
+
+assert('Class Nested 3') do
+ class A; end
+ class A::B; end
+ assert_equal(Class, A::B.new.class.class)
+end
+
+assert('Class Nested 4') do
+ class A; end
+ class A::B; end
+ class A::B::C; end
+ assert_equal(A::B::C, A::B::C)
+end
+
+assert('Class Nested 5') do
+ class A; end
+ class A::B; end
+ class A::B::C; end
+ assert_equal(Class, A::B::C.class)
+end
+
+assert('Class Nested 6') do
+ class A; end
+ class A::B; end
+ class A::B::C; end
+ assert_equal(A::B::C, A::B::C.new.class)
+end
+
+assert('Class Nested 7') do
+ class A; end
+ class A::B; end
+ class A::B2 < A::B; end
+ assert_equal(A::B2, A::B2)
+end
+
+assert('Class Nested 8') do
+ class A; end
+ class A::B; end
+ class A::B2 < A::B; end
+ assert_equal(Class, A::B2.class)
+end
+
+assert('Class Colon 1') do
+ class A; end
+ A::C = 1
+ assert_equal(1, A::C)
+end
+
+assert('Class Colon 2') do
+ class A; class ::C; end end
+ assert_equal(C, C)
+end
+
+assert('Class Colon 3') do
+ class A; class ::C; end end
+ assert_equal(Class, C.class)
+end
+
+assert('Class Dup 1') do
+ class C; end
+ assert_equal(Class, C.dup.class)
+end
+
+assert('Class Dup 2') do
+ module M; end
+ assert_equal(Module, M.dup.class)
+end
+
+assert('Class.new') do
+ assert_equal(Class, Class.new.class)
+ a = []
+ klass = Class.new do |c|
+ a << c
+ end
+ assert_equal([klass], a)
+end
+
+assert('class to return the last value') do
+ m = class C; :m end
+ assert_equal(m, :m)
+end
+
+assert('raise when superclass is not a class') do
+ module FirstModule; end
+ assert_raise(TypeError, 'should raise TypeError') do
+ class FirstClass < FirstModule; end
+ end
+
+ class SecondClass; end
+ assert_raise(TypeError, 'should raise TypeError') do
+ class SecondClass < false; end
+ end
+
+ class ThirdClass; end
+ assert_raise(TypeError, 'should raise TypeError') do
+ class ThirdClass < ThirdClass; end
+ end
+end
+
+assert('Class#inherited') do
+ class Foo
+ @@subclass_name = nil
+ def self.inherited(subclass)
+ @@subclass_name = subclass
+ end
+ def self.subclass_name
+ @@subclass_name
+ end
+ end
+
+ assert_equal(nil, Foo.subclass_name)
+
+ class Bar < Foo
+ end
+
+ assert_equal(Bar, Foo.subclass_name)
+
+ class Baz < Bar
+ end
+
+ assert_equal(Baz, Foo.subclass_name)
+end
+
+assert('singleton tests') do
+ module FooMod
+ def run_foo_mod
+ 100
+ end
+ end
+
+ bar = String.new
+
+ baz = class << bar
+ extend FooMod
+ def self.run_baz
+ 200
+ end
+ end
+
+ assert_false baz.singleton_methods.include? :run_foo_mod
+ assert_false baz.singleton_methods.include? :run_baz
+
+ assert_raise(NoMethodError, 'should raise NoMethodError') do
+ baz.run_foo_mod
+ end
+ assert_raise(NoMethodError, 'should raise NoMethodError') do
+ baz.run_baz
+ end
+
+ assert_raise(NoMethodError, 'should raise NoMethodError') do
+ bar.run_foo_mod
+ end
+ assert_raise(NoMethodError, 'should raise NoMethodError') do
+ bar.run_baz
+ end
+
+ baz = class << bar
+ extend FooMod
+ def self.run_baz
+ 300
+ end
+ self
+ end
+
+ assert_true baz.singleton_methods.include? :run_baz
+ assert_true baz.singleton_methods.include? :run_foo_mod
+ assert_equal 100, baz.run_foo_mod
+ assert_equal 300, baz.run_baz
+
+ assert_raise(NoMethodError, 'should raise NoMethodError') do
+ bar.run_foo_mod
+ end
+ assert_raise(NoMethodError, 'should raise NoMethodError') do
+ bar.run_baz
+ end
+
+ fv = false
+ class << fv
+ def self.run_false
+ 5
+ end
+ end
+
+ nv = nil
+ class << nv
+ def self.run_nil
+ 6
+ end
+ end
+
+ tv = true
+ class << tv
+ def self.run_nil
+ 7
+ end
+ end
+
+ assert_raise(TypeError, 'should raise TypeError') do
+ num = 1.0
+ class << num
+ def self.run_nil
+ 7
+ end
+ end
+ end
+end
+
+assert('clone Class') do
+ class Foo
+ def func
+ true
+ end
+ end
+
+ Foo.clone.new.func
+end
+
+assert('class variable and class << self style class method') do
+ class ClassVariableTest
+ @@class_variable = "value"
+ class << self
+ def class_variable
+ @@class_variable
+ end
+ end
+ end
+
+ assert_equal("value", ClassVariableTest.class_variable)
+end
+
+assert('class variable definition in singleton_class') do
+ class ClassVariableDefinitionInSingletonTest
+ class << self
+ @@class_variable = "value"
+ end
+ def class_variable
+ @@class_variable
+ end
+ end
+
+ assert_equal("value", ClassVariableDefinitionInSingletonTest.new.class_variable)
+end
+
+assert('class variable in module and class << self style class method') do
+ module ClassVariableInModuleTest
+ @@class_variable = "value"
+ class << self
+ def class_variable
+ @@class_variable
+ end
+ end
+ end
+
+ assert_equal("value", ClassVariableInModuleTest.class_variable)
+end
+
+assert('child class/module defined in singleton class get parent constant') do
+ actual = module GetParentConstantTest
+ EXPECT = "value"
+ class << self
+ class CHILD
+ class << self
+ EXPECT
+ end
+ end
+ end
+ end
+ assert_equal("value", actual)
+end
+
+assert('overriding class variable with a module (#3235)') do
+ module ModuleWithCVar
+ @@class_variable = 1
+ end
+ class CVarOverrideTest
+ @@class_variable = 2
+ include ModuleWithCVar
+
+ assert_equal(1, @@class_variable)
+ end
+end
+
+assert('class with non-class/module outer raises TypeError') do
+ assert_raise(TypeError) { class 0::C1; end }
+ assert_raise(TypeError) { class []::C2; end }
+end
+
+assert("remove_method doesn't segfault if the passed in argument isn't a symbol") do
+ klass = Class.new
+ assert_raise(TypeError) { klass.remove_method nil }
+ assert_raise(TypeError) { klass.remove_method 123 }
+ assert_raise(TypeError) { klass.remove_method 1.23 }
+ assert_raise(NameError) { klass.remove_method "hello" }
+ assert_raise(TypeError) { klass.remove_method Class.new }
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/codegen.rb b/web/server/h2o/libh2o/deps/mruby/test/t/codegen.rb
new file mode 100644
index 00000000..4c9e2c59
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/codegen.rb
@@ -0,0 +1,197 @@
+##
+# Codegen tests
+
+assert('peephole optimization does not eliminate move whose result is reused') do
+ assert_raise LocalJumpError do
+ def method
+ yield
+ end
+ method(&a &&= 0)
+ end
+end
+
+assert('empty condition in ternary expression parses correctly') do
+ assert_equal(() ? 1 : 2, 2)
+end
+
+assert('method call with exactly 127 arguments') do
+ def args_to_ary(*args)
+ args
+ end
+
+ assert_equal [0]*127, args_to_ary(
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, \
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ )
+end
+
+assert('nested empty heredoc') do
+ _, a = nil, <<B
+#{<<A}
+A
+B
+ assert_equal "\n", a
+end
+
+assert('splat in case splat') do
+ a = *case
+ when 0
+ * = 1
+ end
+
+ assert_equal [1], a
+end
+
+assert('undef with 127 or more arguments') do
+ assert_raise NameError do
+ undef
+ a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
+ a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
+ a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
+ a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a
+ end
+end
+
+assert('next in normal loop with 127 arguments') do
+ assert_raise NameError do
+ while true
+ next A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A
+ end
+ end
+end
+
+assert('negate literal register alignment') do
+ a = *case
+ when 0
+ -0.0
+ 2
+ end
+
+ assert_equal [2], a
+end
+
+assert('register window of calls (#3783)') do
+ # NODE_FOR
+ assert_nothing_raised do
+ for i in []; end
+ end
+
+ # NODE_SYMBOLS
+ assert_nothing_raised do
+ %i(sym)
+ end
+
+ # NODE_SCALL
+ assert_nothing_raised do
+ Object.new&.__id__
+ end
+
+ # NODE_RESCUE with splat
+ assert_nothing_raised do
+ begin
+ raise
+ rescue *[Exception]
+ end
+ end
+
+ # NODE_CASE
+ assert_nothing_raised do
+ case 1
+ when nil
+ end
+ end
+
+ # NODE_CASE with splat
+ assert_nothing_raised do
+ case 1
+ when *nil
+ end
+ end
+
+ # NODE_HASH
+ assert_nothing_raised do
+ {}.merge(
+ 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9,
+ 10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 19=>19,
+ 20=>20, 21=>21, 22=>22, 23=>23, 24=>24, 25=>25, 26=>26, 27=>27, 28=>28, 29=>29,
+ 30=>30, 31=>31, 32=>32, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 38=>38, 39=>39,
+ 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49,
+ 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59,
+ 60=>60, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67, 68=>68, 69=>69,
+ 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79,
+ 80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89,
+ 90=>90, 91=>91, 92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99,
+ 100=>100, 101=>101, 102=>102, 103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109,
+ 110=>110, 111=>111, 112=>112, 113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119,
+ 120=>120, 121=>121, 122=>122, 123=>123, 124=>124, 125=>125, 126=>126)
+ end
+
+ # NODE_OP_ASGN
+ o = Object.new
+ class << o
+ attr_accessor :a
+ end
+
+ o.a = 1
+ assert_nothing_raised{ o.a += 1 }
+ o.a = 1
+ assert_nothing_raised{ o.a <<= 1 }
+ o.a = 1
+ assert_nothing_raised{ o.a &&= 1 }
+
+ o = { k: 1 }
+ assert_nothing_raised{ o[:k] += 1 }
+ o = { k: 1 }
+ assert_nothing_raised{ o[:k] <<= 1 }
+ o = { k: 1 }
+ assert_nothing_raised{ o[:k] &&= 1 }
+
+ o = { k: 1 }
+ assert_nothing_raised{ o[*[:k]] += 1 }
+ o = { k: 1 }
+ assert_nothing_raised{ o[*[:k]] <<= 1 }
+ o = { k: 1 }
+ assert_nothing_raised{ o[*[:k]] &&= 1 }
+
+ # NODE_YIELD
+ def check_node_yield
+ yield
+ end
+ assert_nothing_raised do
+ check_node_yield{}
+ end
+
+ # NODE_DXSTR
+ assert_raise(NotImplementedError){ `#{:dynamic}` }
+
+ # NODE_XSTR
+ assert_raise(NotImplementedError){ `static` }
+
+ # NODE_DREGX
+ class Regexp; end
+ assert_raise(NoMethodError){ /#{'dynamic'}tail/ }
+ assert_raise(NoMethodError){ /#{'dynamic'}tail/iu }
+
+ # NODE_REGX
+ assert_raise(NoMethodError){ /static/ }
+ assert_raise(NoMethodError){ /static/iu }
+ Object.remove_const :Regexp
+
+ # NODE_UNDEF
+ assert_nothing_raised do
+ class << Object.new
+ undef send
+ end
+ end
+
+ # NODE_ALIAS
+ assert_nothing_raised do
+ class << Object.new
+ alias send2 send
+ end
+ end
+end \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/comparable.rb b/web/server/h2o/libh2o/deps/mruby/test/t/comparable.rb
new file mode 100644
index 00000000..2ee28de7
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/comparable.rb
@@ -0,0 +1,80 @@
+
+assert('Comparable#<', '15.3.3.2.1') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ x
+ end
+ end
+ assert_false(Foo.new < 0)
+ assert_false(Foo.new < 1)
+ assert_true(Foo.new < -1)
+ assert_raise(ArgumentError){ Foo.new < nil }
+end
+
+assert('Comparable#<=', '15.3.3.2.2') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ x
+ end
+ end
+ assert_true(Foo.new <= 0)
+ assert_false(Foo.new <= 1)
+ assert_true(Foo.new <= -1)
+ assert_raise(ArgumentError){ Foo.new <= nil }
+end
+
+assert('Comparable#==', '15.3.3.2.3') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ 0
+ end
+ end
+
+ assert_true(Foo.new == Foo.new)
+end
+
+assert('Comparable#>', '15.3.3.2.4') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ x
+ end
+ end
+ assert_false(Foo.new > 0)
+ assert_true(Foo.new > 1)
+ assert_false(Foo.new > -1)
+ assert_raise(ArgumentError){ Foo.new > nil }
+end
+
+assert('Comparable#>=', '15.3.3.2.5') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ x
+ end
+ end
+ assert_true(Foo.new >= 0)
+ assert_true(Foo.new >= 1)
+ assert_false(Foo.new >= -1)
+ assert_raise(ArgumentError){ Foo.new >= nil }
+end
+
+assert('Comparable#between?', '15.3.3.2.6') do
+ class Foo
+ include Comparable
+ def <=>(x)
+ x
+ end
+ end
+
+ c = Foo.new
+
+ assert_false(c.between?(-1, 1))
+ assert_false(c.between?(-1, -1))
+ assert_false(c.between?( 1, 1))
+ assert_true(c.between?( 1, -1))
+ assert_true(c.between?(0, 0))
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/ensure.rb b/web/server/h2o/libh2o/deps/mruby/test/t/ensure.rb
new file mode 100644
index 00000000..bef39705
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/ensure.rb
@@ -0,0 +1,54 @@
+##
+# ensure Test
+
+assert('ensure - context - yield') do
+ class EnsureYieldBreak
+ attr_reader :ensure_context
+ def try
+ yield
+ ensure
+ @ensure_context = self
+ end
+ end
+
+ yielder = EnsureYieldBreak.new
+ yielder.try do
+ end
+ assert_equal yielder, yielder.ensure_context
+end
+
+assert('ensure - context - yield and break') do
+ class EnsureYieldBreak
+ attr_reader :ensure_context
+ def try
+ yield
+ ensure
+ @ensure_context = self
+ end
+ end
+
+ yielder = EnsureYieldBreak.new
+ yielder.try do
+ break
+ end
+ assert_equal yielder, yielder.ensure_context
+end
+
+assert('ensure - context - yield and return') do
+ class EnsureYieldBreak
+ attr_reader :ensure_context
+ def try
+ yield
+ ensure
+ @ensure_context = self
+ end
+ end
+
+ yielder = EnsureYieldBreak.new
+ lambda do
+ yielder.try do
+ return
+ end
+ end.call
+ assert_equal yielder, yielder.ensure_context
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/enumerable.rb b/web/server/h2o/libh2o/deps/mruby/test/t/enumerable.rb
new file mode 100644
index 00000000..359c3451
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/enumerable.rb
@@ -0,0 +1,134 @@
+##
+# Enumerable ISO Test
+
+assert('Enumerable', '15.3.2') do
+ assert_equal(Module, Enumerable.class)
+end
+
+assert('Enumerable#all?', '15.3.2.2.1') do
+ assert_true([1,2,3].all?)
+ assert_false([1,false,3].all?)
+
+ a = [2,4,6]
+ all = a.all? do |e|
+ e % 2 == 0
+ end
+ assert_true(all)
+
+ a = [2,4,7]
+ all = a.all? do |e|
+ e % 2 == 0
+ end
+ assert_false(all)
+end
+
+assert('Enumerable#any?', '15.3.2.2.2') do
+ assert_true([false,true,false].any?)
+ assert_false([false,false,false].any?)
+
+ a = [1,3,6]
+ any = a.any? do |e|
+ e % 2 == 0
+ end
+ assert_true(any)
+
+ a = [1,3,5]
+ any = a.any? do |e|
+ e % 2 == 0
+ end
+ assert_false(any)
+end
+
+assert('Enumerable#collect', '15.3.2.2.3') do
+ assert_true [1,2,3].collect { |i| i + i } == [2,4,6]
+end
+
+assert('Enumerable#detect', '15.3.2.2.4') do
+ assert_equal 1, [1,2,3].detect() { true }
+ assert_equal 'a', [1,2,3].detect("a") { false }
+end
+
+assert('Array#each_with_index', '15.3.2.2.5') do
+ a = nil
+ b = nil
+
+ [1].each_with_index {|e,i| a = e; b = i}
+
+ assert_equal(1, a)
+ assert_equal(0, b)
+end
+
+assert('Enumerable#entries', '15.3.2.2.6') do
+ assert_equal([1], [1].entries)
+end
+
+assert('Enumerable#find', '15.3.2.2.7') do
+ assert_equal 1, [1,2,3].find() { true }
+ assert_equal 'a', [1,2,3].find("a") { false }
+end
+
+assert('Enumerable#find_all', '15.3.2.2.8') do
+ assert_true [1,2,3,4,5,6,7,8,9].find_all() {|i| i%2 == 0}, [2,4,6,8]
+end
+
+assert('Enumerable#grep', '15.3.2.2.9') do
+ assert_equal [4,5,6], [1,2,3,4,5,6,7,8,9].grep(4..6)
+end
+
+assert('Enumerable#include?', '15.3.2.2.10') do
+ assert_true [1,2,3,4,5,6,7,8,9].include?(5)
+ assert_false [1,2,3,4,5,6,7,8,9].include?(0)
+end
+
+assert('Enumerable#inject', '15.3.2.2.11') do
+ assert_equal 21, [1,2,3,4,5,6].inject() {|s, n| s + n}
+ assert_equal 22, [1,2,3,4,5,6].inject(1) {|s, n| s + n}
+end
+
+assert('Enumerable#map', '15.3.2.2.12') do
+ assert_equal [2,4,6], [1,2,3].map { |i| i + i }
+end
+
+assert('Enumerable#max', '15.3.2.2.13') do
+ a = ['aaa', 'bb', 'c']
+ assert_equal 'c', a.max
+ assert_equal 'aaa', a.max {|i1,i2| i1.length <=> i2.length}
+end
+
+assert('Enumerable#min', '15.3.2.2.14') do
+ a = ['aaa', 'bb', 'c']
+ assert_equal 'aaa', a.min
+ assert_equal 'c', a.min {|i1,i2| i1.length <=> i2.length}
+end
+
+assert('Enumerable#member?', '15.3.2.2.15') do
+ assert_true [1,2,3,4,5,6,7,8,9].member?(5)
+ assert_false [1,2,3,4,5,6,7,8,9].member?(0)
+end
+
+assert('Enumerable#partition', '15.3.2.2.16') do
+ partition = [0,1,2,3,4,5,6,7,8,9].partition do |i|
+ i % 2 == 0
+ end
+ assert_equal [[0,2,4,6,8], [1,3,5,7,9]], partition
+end
+
+assert('Enumerable#reject', '15.3.2.2.17') do
+ reject = [0,1,2,3,4,5,6,7,8,9].reject do |i|
+ i % 2 == 0
+ end
+ assert_equal [1,3,5,7,9], reject
+end
+
+assert('Enumerable#select', '15.3.2.2.18') do
+ assert_equal [2,4,6,8], [1,2,3,4,5,6,7,8,9].select() {|i| i%2 == 0}
+end
+
+assert('Enumerable#sort', '15.3.2.2.19') do
+ assert_equal [1,2,3,4,6,7], [7,3,1,2,6,4].sort
+ assert_equal [7,6,4,3,2,1], [7,3,1,2,6,4].sort {|e1,e2|e2<=>e1}
+end
+
+assert('Enumerable#to_a', '15.3.2.2.20') do
+ assert_equal [1], [1].to_a
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/exception.rb b/web/server/h2o/libh2o/deps/mruby/test/t/exception.rb
new file mode 100644
index 00000000..ce7b5841
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/exception.rb
@@ -0,0 +1,422 @@
+##
+# Exception ISO Test
+
+assert('Exception', '15.2.22') do
+ assert_equal Class, Exception.class
+end
+
+assert('Exception.exception', '15.2.22.4.1') do
+ e = Exception.exception('a')
+
+ assert_equal Exception, e.class
+end
+
+assert('Exception#exception', '15.2.22.5.1') do
+ e = Exception.new
+ re = RuntimeError.new
+ assert_equal e, e.exception
+ assert_equal e, e.exception(e)
+ assert_equal re, re.exception(re)
+ changed_re = re.exception('message has changed')
+ assert_not_equal re, changed_re
+ assert_equal 'message has changed', changed_re.message
+end
+
+assert('Exception#message', '15.2.22.5.2') do
+ e = Exception.exception('a')
+
+ assert_equal 'a', e.message
+end
+
+assert('Exception#to_s', '15.2.22.5.3') do
+ e = Exception.exception('a')
+
+ assert_equal 'a', e.to_s
+end
+
+assert('Exception.exception', '15.2.22.4.1') do
+ e = Exception.exception()
+ e.initialize('a')
+
+ assert_equal 'a', e.message
+end
+
+assert('NameError', '15.2.31') do
+ assert_raise(NameError) do
+ raise NameError.new
+ end
+
+ e = NameError.new "msg", "name"
+ assert_equal "msg", e.message
+ assert_equal "name", e.name
+end
+
+assert('ScriptError', '15.2.37') do
+ assert_raise(ScriptError) do
+ raise ScriptError.new
+ end
+end
+
+assert('SyntaxError', '15.2.38') do
+ assert_raise(SyntaxError) do
+ raise SyntaxError.new
+ end
+end
+
+# Not ISO specified
+
+assert('Exception 1') do
+r=begin
+ 1+1
+ ensure
+ 2+2
+ end
+ assert_equal 2, r
+end
+
+assert('Exception 2') do
+r=begin
+ 1+1
+ begin
+ 2+2
+ ensure
+ 3+3
+ end
+ ensure
+ 4+4
+ end
+ assert_equal 4, r
+end
+
+assert('Exception 3') do
+r=begin
+ 1+1
+ begin
+ 2+2
+ ensure
+ 3+3
+ end
+ ensure
+ 4+4
+ begin
+ 5+5
+ ensure
+ 6+6
+ end
+ end
+ assert_equal 4, r
+end
+
+assert('Exception 4') do
+ a = nil
+ 1.times{|e|
+ begin
+ rescue => err
+ end
+ a = err.class
+ }
+ assert_equal NilClass, a
+end
+
+assert('Exception 5') do
+ $ans = []
+ def m
+ $!
+ end
+ def m2
+ 1.times{
+ begin
+ return
+ ensure
+ $ans << m
+ end
+ }
+ end
+ m2
+ assert_equal [nil], $ans
+end
+
+assert('Exception 6') do
+ $i = 0
+ def m
+ iter{
+ begin
+ $i += 1
+ begin
+ $i += 2
+ break
+ ensure
+
+ end
+ ensure
+ $i += 4
+ end
+ $i = 0
+ }
+ end
+
+ def iter
+ yield
+ end
+ m
+ assert_equal 7, $i
+end
+
+assert('Exception 7') do
+ $i = 0
+ def m
+ begin
+ $i += 1
+ begin
+ $i += 2
+ return
+ ensure
+ $i += 3
+ end
+ ensure
+ $i += 4
+ end
+ p :end
+ end
+ m
+ assert_equal 10, $i
+end
+
+assert('Exception 8') do
+r=begin
+ 1
+ rescue
+ 2
+ else
+ 3
+ end
+ assert_equal 3, r
+end
+
+assert('Exception 9') do
+r=begin
+ 1+1
+ rescue
+ 2+2
+ else
+ 3+3
+ ensure
+ 4+4
+ end
+ assert_equal 6, r
+end
+
+assert('Exception 10') do
+r=begin
+ 1+1
+ begin
+ 2+2
+ rescue
+ 3+3
+ else
+ 4+4
+ end
+ rescue
+ 5+5
+ else
+ 6+6
+ ensure
+ 7+7
+ end
+ assert_equal 12, r
+end
+
+assert('Exception 11') do
+ a = :ok
+ begin
+ begin
+ raise Exception
+ rescue
+ a = :ng
+ end
+ rescue Exception
+ end
+ assert_equal :ok, a
+end
+
+assert('Exception 12') do
+ a = :ok
+ begin
+ raise Exception rescue a = :ng
+ rescue Exception
+ end
+ assert_equal :ok, a
+end
+
+assert('Exception 13') do
+ a = :ng
+ begin
+ raise StandardError
+ rescue TypeError, ArgumentError
+ a = :ng
+ rescue
+ a = :ok
+ else
+ a = :ng
+ end
+ assert_equal :ok, a
+end
+
+assert('Exception 14') do
+ def exception_test14; UnknownConstant; end
+ a = :ng
+ begin
+ send(:exception_test14)
+ rescue
+ a = :ok
+ end
+
+ assert_equal :ok, a
+end
+
+assert('Exception 15') do
+ a = begin
+ :ok
+ rescue
+ :ko
+ end
+ assert_equal :ok, a
+end
+
+assert('Exception 16') do
+ begin
+ raise "foo"
+ false
+ rescue => e
+ assert_equal "foo", e.message
+ end
+end
+
+assert('Exception 17') do
+r=begin
+ raise "a" # RuntimeError
+ rescue ArgumentError
+ 1
+ rescue StandardError
+ 2
+ else
+ 3
+ ensure
+ 4
+ end
+ assert_equal 2, r
+end
+
+assert('Exception 18') do
+r=begin
+ 0
+ rescue ArgumentError
+ 1
+ rescue StandardError
+ 2
+ else
+ 3
+ ensure
+ 4
+ end
+ assert_equal 3, r
+end
+
+assert('Exception 19') do
+ class Class4Exception19
+ def a
+ r = @e = false
+ begin
+ b
+ rescue TypeError
+ r = self.z
+ end
+ [ r, @e ]
+ end
+
+ def b
+ begin
+ 1 * "b"
+ ensure
+ @e = self.zz
+ end
+ end
+
+ def zz
+ true
+ end
+ def z
+ true
+ end
+ end
+ assert_equal [true, true], Class4Exception19.new.a
+end
+
+assert('Exception#inspect without message') do
+ assert_equal "Exception", Exception.new.inspect
+end
+
+assert('Exception#backtrace') do
+ assert_nothing_raised do
+ begin
+ raise "get backtrace"
+ rescue => e
+ e.backtrace
+ end
+ end
+end
+
+assert('Raise in ensure') do
+ assert_raise(ArgumentError) do
+ begin
+ raise "" # RuntimeError
+ ensure
+ raise ArgumentError
+ end
+ end
+end
+
+def backtrace_available?
+ begin
+ raise "XXX"
+ rescue => exception
+ not exception.backtrace.empty?
+ end
+end
+
+assert('GC in rescue') do
+ skip "backtrace isn't available" unless backtrace_available?
+
+ line = nil
+ begin
+ [1].each do
+ [2].each do
+ [3].each do
+ line = __LINE__; raise "XXX"
+ end
+ end
+ end
+ rescue => exception
+ GC.start
+ assert_equal("#{__FILE__}:#{line}:in call",
+ exception.backtrace.first)
+ end
+end
+
+assert('Method call in rescue') do
+ skip "backtrace isn't available" unless backtrace_available?
+
+ line = nil
+ begin
+ [1].each do
+ [2].each do
+ line = __LINE__; raise "XXX"
+ end
+ end
+ rescue => exception
+ [3].each do
+ end
+ assert_equal("#{__FILE__}:#{line}:in call",
+ exception.backtrace.first)
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/false.rb b/web/server/h2o/libh2o/deps/mruby/test/t/false.rb
new file mode 100644
index 00000000..3582f697
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/false.rb
@@ -0,0 +1,31 @@
+##
+# FalseClass ISO Test
+
+assert('FalseClass', '15.2.6') do
+ assert_equal Class, FalseClass.class
+end
+
+assert('FalseClass false', '15.2.6.1') do
+ assert_false false
+ assert_equal FalseClass, false.class
+ assert_false FalseClass.method_defined? :new
+end
+
+assert('FalseClass#&', '15.2.6.3.1') do
+ assert_false false.&(true)
+ assert_false false.&(false)
+end
+
+assert('FalseClass#^', '15.2.6.3.2') do
+ assert_true false.^(true)
+ assert_false false.^(false)
+end
+
+assert('FalseClass#to_s', '15.2.6.3.3') do
+ assert_equal 'false', false.to_s
+end
+
+assert('FalseClass#|', '15.2.6.3.4') do
+ assert_true false.|(true)
+ assert_false false.|(false)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/float.rb b/web/server/h2o/libh2o/deps/mruby/test/t/float.rb
new file mode 100644
index 00000000..7e8c9898
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/float.rb
@@ -0,0 +1,205 @@
+##
+# Float ISO Test
+
+assert('Float', '15.2.9') do
+ assert_equal Class, Float.class
+end
+
+assert('Float#+', '15.2.9.3.1') do
+ a = 3.123456788 + 0.000000001
+ b = 3.123456789 + 1
+
+ assert_float(3.123456789, a)
+ assert_float(4.123456789, b)
+
+ assert_raise(TypeError){ 0.0+nil }
+ assert_raise(TypeError){ 1.0+nil }
+end
+
+assert('Float#-', '15.2.9.3.2') do
+ a = 3.123456790 - 0.000000001
+ b = 5.123456789 - 1
+
+ assert_float(3.123456789, a)
+ assert_float(4.123456789, b)
+end
+
+assert('Float#*', '15.2.9.3.3') do
+ a = 3.125 * 3.125
+ b = 3.125 * 1
+
+ assert_float(9.765625, a)
+ assert_float(3.125 , b)
+end
+
+assert('Float#/', '15.2.9.3.4') do
+ a = 3.123456789 / 3.123456789
+ b = 3.123456789 / 1
+
+ assert_float(1.0 , a)
+ assert_float(3.123456789, b)
+end
+
+assert('Float#%', '15.2.9.3.5') do
+ a = 3.125 % 3.125
+ b = 3.125 % 1
+
+ assert_float(0.0 , a)
+ assert_float(0.125, b)
+end
+
+assert('Float#<=>', '15.2.9.3.6') do
+ a = 3.125 <=> 3.123
+ b = 3.125 <=> 3.125
+ c = 3.125 <=> 3.126
+ a2 = 3.125 <=> 3
+ c2 = 3.125 <=> 4
+
+ assert_equal( 1, a)
+ assert_equal( 0, b)
+ assert_equal(-1, c)
+ assert_equal( 1, a2)
+ assert_equal(-1, c2)
+end
+
+assert('Float#==', '15.2.9.3.7') do
+ assert_true 3.1 == 3.1
+ assert_false 3.1 == 3.2
+end
+
+assert('Float#ceil', '15.2.9.3.8') do
+ a = 3.123456789.ceil
+ b = 3.0.ceil
+ c = -3.123456789.ceil
+ d = -3.0.ceil
+
+ assert_equal( 4, a)
+ assert_equal( 3, b)
+ assert_equal(-3, c)
+ assert_equal(-3, d)
+end
+
+assert('Float#finite?', '15.2.9.3.9') do
+ assert_true 3.123456789.finite?
+ assert_false (1.0 / 0.0).finite?
+end
+
+assert('Float#floor', '15.2.9.3.10') do
+ a = 3.123456789.floor
+ b = 3.0.floor
+ c = -3.123456789.floor
+ d = -3.0.floor
+
+ assert_equal( 3, a)
+ assert_equal( 3, b)
+ assert_equal(-4, c)
+ assert_equal(-3, d)
+end
+
+assert('Float#infinite?', '15.2.9.3.11') do
+ a = 3.123456789.infinite?
+ b = (1.0 / 0.0).infinite?
+ c = (-1.0 / 0.0).infinite?
+
+ assert_nil a
+ assert_equal( 1, b)
+ assert_equal(-1, c)
+end
+
+assert('Float#round', '15.2.9.3.12') do
+ a = 3.123456789.round
+ b = 3.5.round
+ c = 3.4999.round
+ d = (-3.123456789).round
+ e = (-3.5).round
+ f = 12345.67.round(-1)
+ g = 3.423456789.round(0)
+ h = 3.423456789.round(1)
+ i = 3.423456789.round(3)
+
+ assert_equal( 3, a)
+ assert_equal( 4, b)
+ assert_equal( 3, c)
+ assert_equal( -3, d)
+ assert_equal( -4, e)
+ assert_equal(12350, f)
+ assert_equal( 3, g)
+ assert_float( 3.4, h)
+ assert_float(3.423, i)
+
+ assert_equal(42.0, 42.0.round(307))
+ assert_equal(1.0e307, 1.0e307.round(2))
+
+ inf = 1.0/0.0
+ assert_raise(FloatDomainError){ inf.round }
+ assert_raise(FloatDomainError){ inf.round(-1) }
+ assert_equal(inf, inf.round(1))
+ nan = 0.0/0.0
+ assert_raise(FloatDomainError){ nan.round }
+ assert_raise(FloatDomainError){ nan.round(-1) }
+ assert_true(nan.round(1).nan?)
+end
+
+assert('Float#to_f', '15.2.9.3.13') do
+ a = 3.123456789
+
+ assert_float(a, a.to_f)
+end
+
+assert('Float#to_i', '15.2.9.3.14') do
+ assert_equal(3, 3.123456789.to_i)
+ assert_raise(FloatDomainError) { Float::INFINITY.to_i }
+ assert_raise(FloatDomainError) { (-Float::INFINITY).to_i }
+ assert_raise(FloatDomainError) { Float::NAN.to_i }
+end
+
+assert('Float#truncate', '15.2.9.3.15') do
+ assert_equal( 3, 3.123456789.truncate)
+ assert_equal(-3, -3.1.truncate)
+end
+
+assert('Float#divmod') do
+ def check_floats exp, act
+ assert_float exp[0], act[0]
+ assert_float exp[1], act[1]
+ end
+
+ # Note: quotients are Float because mruby does not have Bignum.
+ check_floats [ 0, 0.0], 0.0.divmod(1)
+ check_floats [ 0, 1.1], 1.1.divmod(3)
+ check_floats [ 3, 0.2], 3.2.divmod(1)
+ check_floats [ 2, 6.3], 20.3.divmod(7)
+ check_floats [-1, 1.6], -3.4.divmod(5)
+ check_floats [-2, -0.5], 25.5.divmod(-13)
+ check_floats [ 1, -6.6], -13.6.divmod(-7)
+ check_floats [ 3, 0.2], 9.8.divmod(3.2)
+end
+
+assert('Float#nan?') do
+ assert_true (0.0/0.0).nan?
+ assert_false 0.0.nan?
+ assert_false (1.0/0.0).nan?
+ assert_false (-1.0/0.0).nan?
+end
+
+assert('Float#<<') do
+ # Left Shift by one
+ assert_equal 46, 23.0 << 1
+
+ # Left Shift by a negative is Right Shift
+ assert_equal 23, 46.0 << -1
+end
+
+assert('Float#>>') do
+ # Right Shift by one
+ assert_equal 23, 46.0 >> 1
+
+ # Right Shift by a negative is Left Shift
+ assert_equal 46, 23.0 >> -1
+
+ # Don't raise on large Right Shift
+ assert_equal 0, 23.0 >> 128
+
+ # Don't raise on large Right Shift
+ assert_equal(-1, -23.0 >> 128)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/gc.rb b/web/server/h2o/libh2o/deps/mruby/test/t/gc.rb
new file mode 100644
index 00000000..4b800e94
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/gc.rb
@@ -0,0 +1,45 @@
+# Not ISO specified
+
+assert('GC.enable') do
+ assert_false GC.disable
+ assert_true GC.enable
+ assert_false GC.enable
+end
+
+assert('GC.disable') do
+ begin
+ assert_false GC.disable
+ assert_true GC.disable
+ ensure
+ GC.enable
+ end
+end
+
+assert('GC.interval_ratio=') do
+ origin = GC.interval_ratio
+ begin
+ assert_equal 150, (GC.interval_ratio = 150)
+ ensure
+ GC.interval_ratio = origin
+ end
+end
+
+assert('GC.step_ratio=') do
+ origin = GC.step_ratio
+ begin
+ assert_equal 150, (GC.step_ratio = 150)
+ ensure
+ GC.step_ratio = origin
+ end
+end
+
+assert('GC.generational_mode=') do
+ origin = GC.generational_mode
+ begin
+ assert_false (GC.generational_mode = false)
+ assert_true (GC.generational_mode = true)
+ assert_true (GC.generational_mode = true)
+ ensure
+ GC.generational_mode = origin
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/hash.rb b/web/server/h2o/libh2o/deps/mruby/test/t/hash.rb
new file mode 100644
index 00000000..c63b8c00
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/hash.rb
@@ -0,0 +1,375 @@
+##
+# Hash ISO Test
+
+assert('Hash', '15.2.13') do
+ assert_equal Class, Hash.class
+end
+
+assert('Hash#==', '15.2.13.4.1') do
+ assert_true({ 'abc' => 'abc' } == { 'abc' => 'abc' })
+ assert_false({ 'abc' => 'abc' } == { 'cba' => 'cba' })
+ assert_true({ :equal => 1 } == { :equal => 1.0 })
+ assert_false({ :a => 1 } == true)
+end
+
+assert('Hash#[]', '15.2.13.4.2') do
+ a = { 'abc' => 'abc' }
+
+ assert_equal 'abc', a['abc']
+
+ # Hash#[] should call #default (#3272)
+ hash = {}
+ def hash.default(k); self[k] = 1; end
+ hash[:foo] += 1
+
+ assert_equal 2, hash[:foo]
+end
+
+assert('Hash#[]=', '15.2.13.4.3') do
+ a = Hash.new
+ a['abc'] = 'abc'
+
+ assert_equal 'abc', a['abc']
+end
+
+assert('Hash#clear', '15.2.13.4.4') do
+ a = { 'abc' => 'abc' }
+ a.clear
+
+ assert_equal({ }, a)
+end
+
+assert('Hash#dup') do
+ a = { 'a' => 1 }
+ b = a.dup
+ a['a'] = 2
+ assert_equal({'a' => 1}, b)
+
+ c = Hash.new { |h, k| h[k] = k.upcase }
+ d = c.dup
+ assert_equal("FOO", d["foo"])
+end
+
+assert('Hash#default', '15.2.13.4.5') do
+ a = Hash.new
+ b = Hash.new('abc')
+ c = Hash.new {|s,k| s[k] = k}
+
+ assert_nil a.default
+ assert_equal 'abc', b.default
+ assert_nil c.default
+ assert_equal 'abc', c.default('abc')
+end
+
+assert('Hash#default=', '15.2.13.4.6') do
+ a = { 'abc' => 'abc' }
+ a.default = 'cba'
+
+ assert_equal 'abc', a['abc']
+ assert_equal 'cba', a['notexist']
+end
+
+assert('Hash#default_proc', '15.2.13.4.7') do
+ a = Hash.new
+ b = Hash.new {|s,k| s[k] = k + k}
+ c = b[2]
+ d = b['cat']
+
+ assert_nil a.default_proc
+ assert_equal Proc, b.default_proc.class
+ assert_equal 4, c
+ assert_equal 'catcat', d
+end
+
+assert('Hash#delete', '15.2.13.4.8') do
+ a = { 'abc' => 'abc' }
+ b = { 'abc' => 'abc' }
+ b_tmp_1 = false
+ b_tmp_2 = false
+
+ a.delete('abc')
+ b.delete('abc') do |k|
+ b_tmp_1 = true
+ end
+ b.delete('abc') do |k|
+ b_tmp_2 = true
+ end
+
+ assert_nil a.delete('cba')
+ assert_false a.has_key?('abc')
+ assert_false b_tmp_1
+ assert_true b_tmp_2
+end
+
+assert('Hash#each', '15.2.13.4.9') do
+ a = { 'abc_key' => 'abc_value' }
+ key = nil
+ value = nil
+
+ a.each do |k,v|
+ key = k
+ value = v
+ end
+
+ assert_equal 'abc_key', key
+ assert_equal 'abc_value', value
+end
+
+assert('Hash#each_key', '15.2.13.4.10') do
+ a = { 'abc_key' => 'abc_value' }
+ key = nil
+
+ a.each_key do |k|
+ key = k
+ end
+
+ assert_equal 'abc_key', key
+end
+
+assert('Hash#each_value', '15.2.13.4.11') do
+ a = { 'abc_key' => 'abc_value' }
+ value = nil
+
+ a.each_value do |v|
+ value = v
+ end
+
+ assert_equal 'abc_value', value
+end
+
+assert('Hash#empty?', '15.2.13.4.12') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_false a.empty?
+ assert_true b.empty?
+end
+
+assert('Hash#has_key?', '15.2.13.4.13') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_true a.has_key?('abc_key')
+ assert_false b.has_key?('cba')
+end
+
+assert('Hash#has_value?', '15.2.13.4.14') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_true a.has_value?('abc_value')
+ assert_false b.has_value?('cba')
+end
+
+assert('Hash#include?', '15.2.13.4.15') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_true a.include?('abc_key')
+ assert_false b.include?('cba')
+end
+
+assert('Hash#initialize', '15.2.13.4.16') do
+ # Testing initialize by new.
+ h = Hash.new
+ h2 = Hash.new(:not_found)
+
+ assert_true h.is_a? Hash
+ assert_equal({ }, h)
+ assert_nil h["hello"]
+ assert_equal :not_found, h2["hello"]
+end
+
+assert('Hash#initialize_copy', '15.2.13.4.17') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new.initialize_copy(a)
+
+ assert_equal({ 'abc_key' => 'abc_value' }, b)
+end
+
+assert('Hash#key?', '15.2.13.4.18') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_true a.key?('abc_key')
+ assert_false b.key?('cba')
+end
+
+assert('Hash#keys', '15.2.13.4.19') do
+ a = { 'abc_key' => 'abc_value' }
+
+ assert_equal ['abc_key'], a.keys
+end
+
+assert('Hash#length', '15.2.13.4.20') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_equal 1, a.length
+ assert_equal 0, b.length
+end
+
+assert('Hash#member?', '15.2.13.4.21') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_true a.member?('abc_key')
+ assert_false b.member?('cba')
+end
+
+assert('Hash#merge', '15.2.13.4.22') do
+ a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
+ b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }
+
+ result_1 = a.merge b
+ result_2 = a.merge(b) do |key, original, new|
+ original
+ end
+
+ assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'XXX',
+ 'xyz_key' => 'xyz_value' }, result_1)
+ assert_equal({'abc_key' => 'abc_value', 'cba_key' => 'cba_value',
+ 'xyz_key' => 'xyz_value' }, result_2)
+
+ assert_raise(TypeError) do
+ { 'abc_key' => 'abc_value' }.merge "a"
+ end
+end
+
+assert('Hash#replace', '15.2.13.4.23') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new.replace(a)
+
+ assert_equal({ 'abc_key' => 'abc_value' }, b)
+
+ a = Hash.new(42)
+ b = {}
+ b.replace(a)
+ assert_equal(42, b[1])
+
+ a = Hash.new{|h,x| x}
+ b.replace(a)
+ assert_equal(127, b[127])
+
+ assert_raise(TypeError) do
+ { 'abc_key' => 'abc_value' }.replace "a"
+ end
+end
+
+assert('Hash#shift', '15.2.13.4.24') do
+ a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
+ b = a.shift
+
+ assert_equal Array, b.class
+ assert_equal 2, b.size
+ assert_equal 1, a.size
+
+ b = a.shift
+
+ assert_equal Array, b.class
+ assert_equal 2, b.size
+ assert_equal 0, a.size
+end
+
+assert('Hash#size', '15.2.13.4.25') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_equal 1, a.size
+ assert_equal 0, b.size
+end
+
+assert('Hash#store', '15.2.13.4.26') do
+ a = Hash.new
+ a.store('abc', 'abc')
+
+ assert_equal 'abc', a['abc']
+end
+
+assert('Hash#value?', '15.2.13.4.27') do
+ a = { 'abc_key' => 'abc_value' }
+ b = Hash.new
+
+ assert_true a.value?('abc_value')
+ assert_false b.value?('cba')
+end
+
+assert('Hash#values', '15.2.13.4.28') do
+ a = { 'abc_key' => 'abc_value' }
+
+ assert_equal ['abc_value'], a.values
+end
+
+# Not ISO specified
+
+assert('Hash#eql?') do
+ a = { 'a' => 1, 'b' => 2, 'c' => 3 }
+ b = { 'a' => 1, 'b' => 2, 'c' => 3 }
+ c = { 'a' => 1.0, 'b' => 2, 'c' => 3 }
+ assert_true(a.eql?(b))
+ assert_false(a.eql?(c))
+ assert_false(a.eql?(true))
+end
+
+assert('Hash#reject') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.reject do |k,v|
+ v % 2 == 0
+ end
+ assert_equal({:one => 1, :three => 3}, ret)
+ assert_equal({:one => 1, :two => 2, :three => 3, :four => 4}, h)
+end
+
+assert('Hash#reject!') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.reject! do |k,v|
+ v % 2 == 0
+ end
+ assert_equal({:one => 1, :three => 3}, ret)
+ assert_equal({:one => 1, :three => 3}, h)
+end
+
+assert('Hash#select') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.select do |k,v|
+ v % 2 == 0
+ end
+ assert_equal({:two => 2, :four => 4}, ret)
+ assert_equal({:one => 1, :two => 2, :three => 3, :four => 4}, h)
+end
+
+assert('Hash#select!') do
+ h = {:one => 1, :two => 2, :three => 3, :four => 4}
+ ret = h.select! do |k,v|
+ v % 2 == 0
+ end
+ assert_equal({:two => 2, :four => 4}, ret)
+ assert_equal({:two => 2, :four => 4}, h)
+end
+
+# Not ISO specified
+
+assert('Hash#inspect') do
+ h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
+ ret = h.to_s
+
+ assert_include ret, '"c"=>300'
+ assert_include ret, '"a"=>100'
+ assert_include ret, '"d"=>400'
+end
+
+assert('Hash#rehash') do
+ h = {[:a] => "b"}
+ # hash key modified
+ h.keys[0][0] = :b
+ # h[[:b]] => nil
+ h.rehash
+ assert_equal("b", h[[:b]])
+end
+
+assert('Hash#freeze') do
+ h = {}.freeze
+ assert_raise(RuntimeError) do
+ h[:a] = 'b'
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/indexerror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/indexerror.rb
new file mode 100644
index 00000000..a8dce23a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/indexerror.rb
@@ -0,0 +1,6 @@
+##
+# IndexError ISO Test
+
+assert('IndexError', '15.2.33') do
+ assert_equal Class, IndexError.class
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/integer.rb b/web/server/h2o/libh2o/deps/mruby/test/t/integer.rb
new file mode 100644
index 00000000..d4ef8b51
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/integer.rb
@@ -0,0 +1,268 @@
+##
+# Integer ISO Test
+
+assert('Integer', '15.2.8') do
+ assert_equal Class, Integer.class
+end
+
+assert('Integer#+', '15.2.8.3.1') do
+ a = 1+1
+ b = 1+1.0
+
+ assert_equal 2, a
+ assert_equal 2.0, b
+
+ assert_raise(TypeError){ 0+nil }
+ assert_raise(TypeError){ 1+nil }
+
+ c = Mrbtest::FIXNUM_MAX + 1
+ d = Mrbtest::FIXNUM_MAX.__send__(:+, 1)
+ e = Mrbtest::FIXNUM_MAX + 1.0
+ assert_equal Float, c.class
+ assert_equal Float, d.class
+ assert_float e, c
+ assert_float e, d
+end
+
+assert('Integer#-', '15.2.8.3.2') do
+ a = 2-1
+ b = 2-1.0
+
+ assert_equal 1, a
+ assert_equal 1.0, b
+
+ c = Mrbtest::FIXNUM_MIN - 1
+ d = Mrbtest::FIXNUM_MIN.__send__(:-, 1)
+ e = Mrbtest::FIXNUM_MIN - 1.0
+ assert_equal Float, c.class
+ assert_equal Float, d.class
+ assert_float e, c
+ assert_float e, d
+end
+
+assert('Integer#*', '15.2.8.3.3') do
+ a = 1*1
+ b = 1*1.0
+
+ assert_equal 1, a
+ assert_equal 1.0, b
+
+ assert_raise(TypeError){ 0*nil }
+ assert_raise(TypeError){ 1*nil }
+
+ c = Mrbtest::FIXNUM_MAX * 2
+ d = Mrbtest::FIXNUM_MAX.__send__(:*, 2)
+ e = Mrbtest::FIXNUM_MAX * 2.0
+ assert_equal Float, c.class
+ assert_equal Float, d.class
+ assert_float e, c
+ assert_float e, d
+end
+
+assert('Integer#/', '15.2.8.3.4') do
+ a = 2/1
+ b = 2/1.0
+
+ assert_equal 2, a
+ assert_equal 2.0, b
+end
+
+assert('Integer#%', '15.2.8.3.5') do
+ a = 1%1
+ b = 1%1.0
+ c = 2%4
+ d = 2%5
+ e = 2%-5
+ f = -2%5
+ g = -2%-5
+ h = 2%-2
+ i = -2%2
+ j = -2%-2
+
+ assert_equal 0, a
+ assert_equal 0.0, b
+ assert_equal 2, c
+ assert_equal 2, d
+ assert_equal(-3, e)
+ assert_equal 3, f
+ assert_equal(-2, g)
+ assert_equal 0, h
+ assert_equal 0, i
+ assert_equal 0, j
+end
+
+assert('Integer#<=>', '15.2.9.3.6') do
+ a = 1<=>0
+ b = 1<=>1
+ c = 1<=>2
+
+ assert_equal 1, a
+ assert_equal 0, b
+ assert_equal(-1, c)
+end
+
+assert('Integer#==', '15.2.8.3.7') do
+ a = 1==0
+ b = 1==1
+
+ assert_false a
+ assert_true b
+end
+
+assert('Integer#~', '15.2.8.3.8') do
+ # Complement
+ assert_equal(-1, ~0)
+ assert_equal(-3, ~2)
+end
+
+assert('Integer#&', '15.2.8.3.9') do
+ # Bitwise AND
+ # 0101 (5)
+ # & 0011 (3)
+ # = 0001 (1)
+ assert_equal 1, 5 & 3
+end
+
+assert('Integer#|', '15.2.8.3.10') do
+ # Bitwise OR
+ # 0101 (5)
+ # | 0011 (3)
+ # = 0111 (7)
+ assert_equal 7, 5 | 3
+end
+
+assert('Integer#^', '15.2.8.3.11') do
+ # Bitwise XOR
+ # 0101 (5)
+ # ^ 0011 (3)
+ # = 0110 (6)
+ assert_equal 6, 5 ^ 3
+end
+
+assert('Integer#<<', '15.2.8.3.12') do
+ # Left Shift by one
+ # 00010111 (23)
+ # = 00101110 (46)
+ assert_equal 46, 23 << 1
+
+ # Left Shift by a negative is Right Shift
+ assert_equal 23, 46 << -1
+
+ # Left Shift by 31 is bitShift overflow to SignedInt
+ assert_equal 2147483648, 1 << 31
+
+ # -3 Left Shift by 30 is bitShift overflow to SignedInt
+ assert_equal(-3221225472, -3 << 30)
+end
+
+assert('Integer#>>', '15.2.8.3.13') do
+ # Right Shift by one
+ # 00101110 (46)
+ # = 00010111 (23)
+ assert_equal 23, 46 >> 1
+
+ # Right Shift by a negative is Left Shift
+ assert_equal 46, 23 >> -1
+
+ # Don't raise on large Right Shift
+ assert_equal 0, 23 >> 128
+end
+
+assert('Integer#ceil', '15.2.8.3.14') do
+ assert_equal 10, 10.ceil
+end
+
+assert('Integer#downto', '15.2.8.3.15') do
+ a = 0
+ 3.downto(1) do |i|
+ a += i
+ end
+ assert_equal 6, a
+end
+
+assert('Integer#eql?', '15.2.8.3.16') do
+ a = 1.eql?(1)
+ b = 1.eql?(2)
+ c = 1.eql?(nil)
+
+ assert_true a
+ assert_false b
+ assert_false c
+end
+
+assert('Integer#floor', '15.2.8.3.17') do
+ a = 1.floor
+
+ assert_equal 1, a
+end
+
+assert('Integer#next', '15.2.8.3.19') do
+ assert_equal 2, 1.next
+end
+
+assert('Integer#round', '15.2.8.3.20') do
+ assert_equal 1, 1.round
+end
+
+assert('Integer#succ', '15.2.8.3.21') do
+ assert_equal 2, 1.succ
+end
+
+assert('Integer#times', '15.2.8.3.22') do
+ a = 0
+ 3.times do
+ a += 1
+ end
+ assert_equal 3, a
+end
+
+assert('Integer#to_f', '15.2.8.3.23') do
+ assert_equal 1.0, 1.to_f
+end
+
+assert('Integer#to_i', '15.2.8.3.24') do
+ assert_equal 1, 1.to_i
+end
+
+assert('Integer#to_s', '15.2.8.3.25') do
+ assert_equal '1', 1.to_s
+ assert_equal("-1", -1.to_s)
+end
+
+assert('Integer#truncate', '15.2.8.3.26') do
+ assert_equal 1, 1.truncate
+end
+
+assert('Integer#upto', '15.2.8.3.27') do
+ a = 0
+ 1.upto(3) do |i|
+ a += i
+ end
+ assert_equal 6, a
+end
+
+assert('Integer#divmod', '15.2.8.3.30') do
+ assert_equal [ 0, 0], 0.divmod(1)
+ assert_equal [ 0, 1], 1.divmod(3)
+ assert_equal [ 3, 0], 3.divmod(1)
+ assert_equal [ 2, 6], 20.divmod(7)
+ assert_equal [-1, 2], -3.divmod(5)
+ assert_equal [-2, -1], 25.divmod(-13)
+ assert_equal [ 1, -6], -13.divmod(-7)
+end
+
+# Not ISO specified
+
+assert('Integer#step') do
+ a = []
+ b = []
+ 1.step(3) do |i|
+ a << i
+ end
+ 1.step(6, 2) do |i|
+ b << i
+ end
+
+ assert_equal [1, 2, 3], a
+ assert_equal [1, 3, 5], b
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/iterations.rb b/web/server/h2o/libh2o/deps/mruby/test/t/iterations.rb
new file mode 100644
index 00000000..f227a603
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/iterations.rb
@@ -0,0 +1,61 @@
+assert('while expression', '11.5.2.3.2') do
+ idx = 10
+ all = []
+ res = while idx > 0
+ all << idx
+ idx -= 1
+ end
+
+ assert_equal nil, res
+ assert_equal [10,9,8,7,6,5,4,3,2,1], all
+end
+
+assert('until expression', '11.5.2.3.3') do
+ idx = 10
+ all = []
+ res = until idx == 0
+ all << idx
+ idx -= 1
+ end
+
+ assert_equal nil, res
+ assert_equal [10,9,8,7,6,5,4,3,2,1], all
+end
+
+assert('break expression', '11.5.2.4.3') do
+ assert_equal :result do
+ while true
+ break :result
+ end
+ end
+
+ assert_equal :result do
+ until false
+ break :result
+ end
+ end
+end
+
+assert('next expression', '11.5.2.4.4') do
+ assert_equal [8,6,4,2,0] do
+ all = []
+ idx = 10
+ while idx > 0
+ idx -= 1
+ next if (idx % 2) == 1
+ all << idx
+ end
+ all
+ end
+
+ assert_equal [8,6,4,2,0] do
+ all = []
+ idx = 10
+ until idx == 0
+ idx -= 1
+ next if (idx % 2) == 1
+ all << idx
+ end
+ all
+ end
+end \ No newline at end of file
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/kernel.rb b/web/server/h2o/libh2o/deps/mruby/test/t/kernel.rb
new file mode 100644
index 00000000..e9bd24dc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/kernel.rb
@@ -0,0 +1,643 @@
+##
+# Kernel ISO Test
+
+assert('Kernel', '15.3.1') do
+ assert_equal Module, Kernel.class
+end
+
+assert('Kernel.block_given?', '15.3.1.2.2') do
+ def bg_try(&b)
+ if Kernel.block_given?
+ yield
+ else
+ "no block"
+ end
+ end
+
+ assert_false Kernel.block_given?
+ # test without block
+ assert_equal "no block", bg_try
+ # test with block
+ assert_equal "block" do
+ bg_try { "block" }
+ end
+ # test with block
+ assert_equal "block" do
+ bg_try do
+ "block"
+ end
+ end
+end
+
+# Kernel.eval is provided by the mruby-gem mrbgem. '15.3.1.2.3'
+
+assert('Kernel.global_variables', '15.3.1.2.4') do
+ assert_equal Array, Kernel.global_variables.class
+end
+
+assert('Kernel.iterator?', '15.3.1.2.5') do
+ assert_false Kernel.iterator?
+end
+
+assert('Kernel.lambda', '15.3.1.2.6') do
+ l = Kernel.lambda do
+ true
+ end
+
+ m = Kernel.lambda(&l)
+
+ assert_true l.call
+ assert_equal Proc, l.class
+ assert_true m.call
+ assert_equal Proc, m.class
+end
+
+# Not implemented at the moment
+#assert('Kernel.local_variables', '15.3.1.2.7') do
+# Kernel.local_variables.class == Array
+#end
+
+assert('Kernel.loop', '15.3.1.2.8') do
+ i = 0
+
+ Kernel.loop do
+ i += 1
+ break if i == 100
+ end
+
+ assert_equal 100, i
+end
+
+assert('Kernel.p', '15.3.1.2.9') do
+ # TODO search for a way to test p to stdio
+ assert_true true
+end
+
+assert('Kernel.print', '15.3.1.2.10') do
+ # TODO search for a way to test print to stdio
+ assert_true true
+end
+
+assert('Kernel.puts', '15.3.1.2.11') do
+ # TODO search for a way to test puts to stdio
+ assert_true true
+end
+
+assert('Kernel.raise', '15.3.1.2.12') do
+ assert_raise RuntimeError do
+ Kernel.raise
+ end
+
+ assert_raise RuntimeError do
+ Kernel.raise RuntimeError.new
+ end
+end
+
+assert('Kernel#__id__', '15.3.1.3.3') do
+ assert_equal Fixnum, __id__.class
+end
+
+assert('Kernel#__send__', '15.3.1.3.4') do
+ # test with block
+ l = __send__(:lambda) do
+ true
+ end
+
+ assert_true l.call
+ assert_equal Proc, l.class
+ # test with argument
+ assert_true __send__(:respond_to?, :nil?)
+ # test without argument and without block
+ assert_equal Array, __send__(:public_methods).class
+end
+
+assert('Kernel#block_given?', '15.3.1.3.6') do
+ def bg_try(&b)
+ if block_given?
+ yield
+ else
+ "no block"
+ end
+ end
+
+ assert_false block_given?
+ assert_equal "no block", bg_try
+ assert_equal "block" do
+ bg_try { "block" }
+ end
+ assert_equal "block" do
+ bg_try do
+ "block"
+ end
+ end
+end
+
+assert('Kernel#class', '15.3.1.3.7') do
+ assert_equal Module, Kernel.class
+end
+
+assert('Kernel#clone', '15.3.1.3.8') do
+ class KernelCloneTest
+ def initialize
+ @v = 0
+ end
+
+ def get
+ @v
+ end
+
+ def set(v)
+ @v = v
+ end
+ end
+
+ a = KernelCloneTest.new
+ a.set(1)
+ b = a.clone
+
+ def a.test
+ end
+ a.set(2)
+ c = a.clone
+
+ immutables = [ 1, :foo, true, false, nil ]
+ error_count = 0
+ immutables.each do |i|
+ begin
+ i.clone
+ rescue TypeError
+ error_count += 1
+ end
+ end
+
+ assert_equal 2, a.get
+ assert_equal 1, b.get
+ assert_equal 2, c.get
+ assert_true a.respond_to?(:test)
+ assert_false b.respond_to?(:test)
+ assert_true c.respond_to?(:test)
+end
+
+assert('Kernel#dup', '15.3.1.3.9') do
+ class KernelDupTest
+ def initialize
+ @v = 0
+ end
+
+ def get
+ @v
+ end
+
+ def set(v)
+ @v = v
+ end
+ end
+
+ a = KernelDupTest.new
+ a.set(1)
+ b = a.dup
+
+ def a.test
+ end
+ a.set(2)
+ c = a.dup
+
+ immutables = [ 1, :foo, true, false, nil ]
+ error_count = 0
+ immutables.each do |i|
+ begin
+ i.dup
+ rescue TypeError
+ error_count += 1
+ end
+ end
+
+ assert_equal immutables.size, error_count
+ assert_equal 2, a.get
+ assert_equal 1, b.get
+ assert_equal 2, c.get
+ assert_true a.respond_to?(:test)
+ assert_false b.respond_to?(:test)
+ assert_false c.respond_to?(:test)
+end
+
+assert('Kernel#dup class') do
+ assert_nothing_raised do
+ Array.dup.new(200)
+ Range.dup.new(2, 3)
+ String.dup.new("a"*50)
+ end
+end
+
+# Kernel#eval is provided by mruby-eval mrbgem '15.3.1.3.12'
+
+assert('Kernel#extend', '15.3.1.3.13') do
+ class Test4ExtendClass
+ end
+
+ module Test4ExtendModule
+ def test_method; end
+ end
+
+ a = Test4ExtendClass.new
+ a.extend(Test4ExtendModule)
+ b = Test4ExtendClass.new
+
+ assert_true a.respond_to?(:test_method)
+ assert_false b.respond_to?(:test_method)
+end
+
+assert('Kernel#extend works on toplevel', '15.3.1.3.13') do
+ module Test4ExtendModule
+ def test_method; end
+ end
+ # This would crash...
+ extend(Test4ExtendModule)
+
+ assert_true respond_to?(:test_method)
+end
+
+assert('Kernel#freeze') do
+ obj = Object.new
+ assert_equal obj, obj.freeze
+ assert_equal 0, 0.freeze
+ assert_equal :a, :a.freeze
+end
+
+assert('Kernel#global_variables', '15.3.1.3.14') do
+ assert_equal Array, global_variables.class
+end
+
+assert('Kernel#hash', '15.3.1.3.15') do
+ assert_equal hash, hash
+end
+
+assert('Kernel#inspect', '15.3.1.3.17') do
+ s = inspect
+
+ assert_equal String, s.class
+ assert_equal "main", s
+end
+
+assert('Kernel#instance_variable_defined?', '15.3.1.3.20') do
+ o = Object.new
+ o.instance_variable_set(:@a, 1)
+
+ assert_true o.instance_variable_defined?("@a")
+ assert_false o.instance_variable_defined?("@b")
+ assert_true o.instance_variable_defined?("@a"[0,2])
+ assert_true o.instance_variable_defined?("@abc"[0,2])
+end
+
+assert('Kernel#instance_variables', '15.3.1.3.23') do
+ o = Object.new
+ o.instance_eval do
+ @a = 11
+ @b = 12
+ end
+ ivars = o.instance_variables
+
+ assert_equal Array, ivars.class,
+ assert_equal(2, ivars.size)
+ assert_true ivars.include?(:@a)
+ assert_true ivars.include?(:@b)
+end
+
+assert('Kernel#is_a?', '15.3.1.3.24') do
+ assert_true is_a?(Kernel)
+ assert_false is_a?(Array)
+
+ assert_raise TypeError do
+ 42.is_a?(42)
+ end
+end
+
+assert('Kernel#iterator?', '15.3.1.3.25') do
+ assert_false iterator?
+end
+
+assert('Kernel#kind_of?', '15.3.1.3.26') do
+ assert_true kind_of?(Kernel)
+ assert_false kind_of?(Array)
+end
+
+assert('Kernel#lambda', '15.3.1.3.27') do
+ l = lambda do
+ true
+ end
+
+ m = lambda(&l)
+
+ assert_true l.call
+ assert_equal Proc, l.class
+ assert_true m.call
+ assert_equal Proc, m.class
+end
+
+# Not implemented yet
+#assert('Kernel#local_variables', '15.3.1.3.28') do
+# local_variables.class == Array
+#end
+
+assert('Kernel#loop', '15.3.1.3.29') do
+ i = 0
+
+ loop do
+ i += 1
+ break if i == 100
+ end
+
+ assert_equal i, 100
+end
+
+assert('Kernel#method_missing', '15.3.1.3.30') do
+ class MMTestClass
+ def method_missing(sym)
+ "A call to #{sym}"
+ end
+ end
+ mm_test = MMTestClass.new
+ assert_equal 'A call to no_method_named_this', mm_test.no_method_named_this
+
+ class SuperMMTestClass < MMTestClass
+ def no_super_method_named_this
+ super
+ end
+ end
+ super_mm_test = SuperMMTestClass.new
+ assert_equal 'A call to no_super_method_named_this', super_mm_test.no_super_method_named_this
+
+ class NoSuperMethodTestClass
+ def no_super_method_named_this
+ super
+ end
+ end
+ no_super_test = NoSuperMethodTestClass.new
+ begin
+ no_super_test.no_super_method_named_this
+ rescue NoMethodError => e
+ assert_equal "undefined method 'no_super_method_named_this' for #{no_super_test}", e.message
+ end
+
+ a = String.new
+ begin
+ a.no_method_named_this
+ rescue NoMethodError => e
+ assert_equal "undefined method 'no_method_named_this' for \"\"", e.message
+ end
+
+ class ShortInspectClass
+ def inspect
+ 'An inspect string'
+ end
+ end
+ b = ShortInspectClass.new
+ begin
+ b.no_method_named_this
+ rescue NoMethodError => e
+ assert_equal "undefined method 'no_method_named_this' for An inspect string", e.message
+ end
+
+ class LongInspectClass
+ def inspect
+ "A" * 70
+ end
+ end
+ c = LongInspectClass.new
+ begin
+ c.no_method_named_this
+ rescue NoMethodError => e
+ assert_equal "undefined method 'no_method_named_this' for #{c}", e.message
+ end
+
+ class NoInspectClass
+ undef inspect
+ end
+ d = NoInspectClass.new
+ begin
+ d.no_method_named_this
+ rescue NoMethodError => e
+ assert_equal "undefined method 'no_method_named_this' for #{d}", e.message
+ end
+end
+
+assert('Kernel#methods', '15.3.1.3.31') do
+ assert_equal Array, methods.class
+end
+
+assert('Kernel#nil?', '15.3.1.3.32') do
+ assert_false nil?
+end
+
+assert('Kernel#object_id', '15.3.1.3.33') do
+ a = ""
+ b = ""
+ assert_not_equal a.object_id, b.object_id
+
+ assert_kind_of Numeric, object_id
+ assert_kind_of Numeric, "".object_id
+ assert_kind_of Numeric, true.object_id
+ assert_kind_of Numeric, false.object_id
+ assert_kind_of Numeric, nil.object_id
+ assert_kind_of Numeric, :no.object_id
+ assert_kind_of Numeric, 1.object_id
+ assert_kind_of Numeric, 1.0.object_id
+end
+
+# Kernel#p is defined in mruby-print mrbgem. '15.3.1.3.34'
+
+# Kernel#print is defined in mruby-print mrbgem. '15.3.1.3.35'
+
+assert('Kernel#private_methods', '15.3.1.3.36') do
+ assert_equal Array, private_methods.class
+end
+
+assert('Kernel#protected_methods', '15.3.1.3.37') do
+ assert_equal Array, protected_methods.class
+end
+
+assert('Kernel#public_methods', '15.3.1.3.38') do
+ assert_equal Array, public_methods.class
+ class Foo
+ def foo
+ end
+ end
+ assert_equal [:foo], Foo.new.public_methods(false)
+end
+
+# Kernel#puts is defined in mruby-print mrbgem. '15.3.1.3.39'
+
+assert('Kernel#raise', '15.3.1.3.40') do
+ assert_raise RuntimeError do
+ raise
+ end
+
+ assert_raise RuntimeError do
+ raise RuntimeError.new
+ end
+end
+
+assert('Kernel#remove_instance_variable', '15.3.1.3.41') do
+ class Test4RemoveInstanceVar
+ attr_reader :var
+ def initialize
+ @var = 99
+ end
+ def remove
+ remove_instance_variable(:@var)
+ end
+ end
+
+ tri = Test4RemoveInstanceVar.new
+ assert_equal 99, tri.var
+ tri.remove
+ assert_equal nil, tri.var
+ assert_raise NameError do
+ tri.remove
+ end
+end
+
+# Kernel#require is defined in mruby-require. '15.3.1.3.42'
+
+assert('Kernel#respond_to?', '15.3.1.3.43') do
+ class Test4RespondTo
+ def valid_method; end
+
+ def test_method; end
+ undef test_method
+ end
+
+ assert_raise TypeError do
+ Test4RespondTo.new.respond_to?(1)
+ end
+
+ assert_raise ArgumentError do
+ Test4RespondTo.new.respond_to?
+ end
+
+ assert_raise ArgumentError do
+ Test4RespondTo.new.respond_to? :a, true, :aa
+ end
+
+ assert_true respond_to?(:nil?)
+ assert_true Test4RespondTo.new.respond_to?(:valid_method)
+ assert_true Test4RespondTo.new.respond_to?('valid_method')
+ assert_false Test4RespondTo.new.respond_to?(:test_method)
+end
+
+assert('Kernel#send', '15.3.1.3.44') do
+ # test with block
+ l = send(:lambda) do
+ true
+ end
+
+ assert_true l.call
+ assert_equal l.class, Proc
+ # test with argument
+ assert_true send(:respond_to?, :nil?)
+ # test without argument and without block
+ assert_equal send(:public_methods).class, Array
+end
+
+assert('Kernel#singleton_methods', '15.3.1.3.45') do
+ assert_equal singleton_methods.class, Array
+end
+
+assert('Kernel#to_s', '15.3.1.3.46') do
+ assert_equal to_s.class, String
+end
+
+assert('Kernel#to_s on primitives') do
+ begin
+ Fixnum.alias_method :to_s_, :to_s
+ Fixnum.remove_method :to_s
+
+ assert_nothing_raised do
+ # segfaults if mrb_cptr is used
+ 1.to_s
+ end
+ ensure
+ Fixnum.alias_method :to_s, :to_s_
+ Fixnum.remove_method :to_s_
+ end
+end
+
+assert('Kernel.local_variables', '15.3.1.2.7') do
+ a, b = 0, 1
+ a += b
+
+ vars = Kernel.local_variables.sort
+ assert_equal [:a, :b, :vars], vars
+
+ assert_equal [:a, :b, :c, :vars], Proc.new { |a, b|
+ c = 2
+ Kernel.local_variables.sort
+ }.call(-1, -2)
+end
+
+assert('Kernel#!=') do
+ str1 = "hello"
+ str2 = str1
+ str3 = "world"
+
+ assert_false (str1[1] != 'e')
+ assert_true (str1 != str3)
+ assert_false (str2 != str1)
+end
+
+# operator "!~" is defined in ISO Ruby 11.4.4.
+assert('Kernel#!~') do
+ x = "x"
+ def x.=~(other)
+ other == "x"
+ end
+ assert_false x !~ "x"
+ assert_true x !~ "z"
+
+ y = "y"
+ def y.=~(other)
+ other == "y"
+ end
+ def y.!~(other)
+ other == "not y"
+ end
+ assert_false y !~ "y"
+ assert_false y !~ "z"
+ assert_true y !~ "not y"
+end
+
+assert('Kernel#respond_to_missing?') do
+ class Test4RespondToMissing
+ def respond_to_missing?(method_name, include_private = false)
+ method_name == :a_method
+ end
+ end
+
+ assert_true Test4RespondToMissing.new.respond_to?(:a_method)
+ assert_false Test4RespondToMissing.new.respond_to?(:no_method)
+end
+
+assert('Kernel#global_variables') do
+ variables = global_variables
+ 1.upto(9) do |i|
+ assert_equal variables.include?(:"$#{i}"), true
+ end
+end
+
+assert('Kernel#define_singleton_method') do
+ o = Object.new
+ ret = o.define_singleton_method(:test_method) do
+ :singleton_method_ok
+ end
+ assert_equal :test_method, ret
+ assert_equal :singleton_method_ok, o.test_method
+end
+
+assert('stack extend') do
+ def recurse(count, stop)
+ return count if count > stop
+ recurse(count+1, stop)
+ end
+
+ assert_equal 6, recurse(0, 5)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/lang.rb b/web/server/h2o/libh2o/deps/mruby/test/t/lang.rb
new file mode 100755
index 00000000..57c37564
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/lang.rb
@@ -0,0 +1,74 @@
+# The aim of these tests is to detect pitfall for optimized VM.
+
+# Test for or/and
+#
+# You may think instruction fusion(OP_EQ and OP_JMPIF) for avoiding
+# generate intermediate boolean value.
+# But and/or is pitfall for this fusioning.
+#
+# For example, the following mruby code:
+#
+# if i > 0 and i < 10 then
+#
+# compiles to the following byte code:
+#
+# 1 000 OP_LOADI R1 0 ; R1:i
+# 2 001 OP_MOVE R2 R1 ; R1:i
+# 2 002 OP_LOADI R3 0
+# 2 003 OP_GT R2 :> 1
+# 2 004 OP_JMPNOT R2 008
+# 2 005 OP_MOVE R2 R1 ; R1:i
+# 2 006 OP_LOADI R3 10
+# 2 007 OP_LT R2 :< 1
+# 2 008 OP_JMPNOT R2 (The address of end of then part)
+#
+# When the instruction fusion the OP_GT and OP_JMPNOT you fell into the pitfalls.
+# The deleted intermediate boolean value is used in OP_JMPNOT (address 008).
+
+assert('and', '11.2.3') do
+ a = 1
+ if a > 0 and a < 10 then
+ b = 1
+ else
+ b = 0
+ end
+ assert_equal 1, b
+
+ if a < 0 and a < 10 then
+ b = 1
+ else
+ b = 0
+ end
+ assert_equal 0, b
+
+ if a < 0 and a > 10 then
+ b = 1
+ else
+ b = 0
+ end
+ assert_equal 0, b
+end
+
+assert('or','11.2.4') do
+ a = 1
+ if a > 0 or a < 10 then
+ b = 1
+ else
+ b = 0
+ end
+ assert_equal 1, b
+
+ if a < 0 or a < 10 then
+ b = 1
+ else
+ b = 0
+ end
+ assert_equal 1, b
+
+ if a < 0 or a > 10 then
+ b = 1
+ else
+ b = 0
+ end
+ assert_equal 0, b
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/literals.rb b/web/server/h2o/libh2o/deps/mruby/test/t/literals.rb
new file mode 100644
index 00000000..51a37c32
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/literals.rb
@@ -0,0 +1,337 @@
+##
+# Literals ISO Test
+
+assert('Literals Numerical', '8.7.6.2') do
+ # signed and unsigned integer
+ assert_equal 1, 1
+ assert_equal(-1, -1)
+ assert_equal(+1, +1)
+ # signed and unsigned float
+ assert_equal 1.0, 1.0
+ assert_equal(-1.0, -1.0)
+ # binary
+ assert_equal 128, 0b10000000
+ assert_equal 128, 0B10000000
+ # octal
+ assert_equal 8, 0o10
+ assert_equal 8, 0O10
+ assert_equal 8, 0_10
+ # hex
+ assert_equal 255, 0xff
+ assert_equal 255, 0Xff
+ # decimal
+ assert_equal 999, 0d999
+ assert_equal 999, 0D999
+ # decimal seperator
+ assert_equal 10000000, 10_000_000
+ assert_equal 10, 1_0
+ # integer with exponent
+ assert_equal 10.0, 1e1
+ assert_equal(0.1, 1e-1)
+ assert_equal 10.0, 1e+1
+ # float with exponent
+ assert_equal 10.0, 1.0e1
+ assert_equal(0.1, 1.0e-1)
+ assert_equal 10.0, 1.0e+1
+end
+
+assert('Literals Strings Single Quoted', '8.7.6.3.2') do
+ assert_equal 'abc', 'abc'
+ assert_equal '\'', '\''
+ assert_equal '\\', '\\'
+end
+
+assert('Literals Strings Double Quoted', '8.7.6.3.3') do
+ a = "abc"
+
+ assert_equal "abc", "abc"
+ assert_equal "\"", "\""
+ assert_equal "\\", "\\"
+ assert_equal "abc", "#{a}"
+end
+
+assert('Literals Strings Quoted Non-Expanded', '8.7.6.3.4') do
+ a = %q{abc}
+ b = %q(abc)
+ c = %q[abc]
+ d = %q<abc>
+ e = %q/abc/
+ f = %q/ab\/c/
+ g = %q{#{a}}
+
+ assert_equal 'abc', a
+ assert_equal 'abc', b
+ assert_equal 'abc', c
+ assert_equal 'abc', d
+ assert_equal 'abc', e
+ assert_equal 'ab/c', f
+ assert_equal '#{a}', g
+end
+
+assert('Literals Strings Quoted Expanded', '8.7.6.3.5') do
+ a = %Q{abc}
+ b = %Q(abc)
+ c = %Q[abc]
+ d = %Q<abc>
+ e = %Q/abc/
+ f = %Q/ab\/c/
+ g = %Q{#{a}}
+
+ assert_equal 'abc', a
+ assert_equal 'abc', b
+ assert_equal 'abc', c
+ assert_equal 'abc', d
+ assert_equal 'abc', e
+ assert_equal 'ab/c', f
+ assert_equal 'abc', g
+end
+
+assert('Literals Strings Here documents', '8.7.6.3.6') do
+ a = <<AAA
+aaa
+AAA
+ b = <<b_b
+bbb
+b_b
+ c = [<<CCC1, <<"CCC2", <<'CCC3']
+c1
+CCC1
+c 2
+CCC2
+c 3
+CCC3
+
+ d = <<DDD
+d#{1+2}DDD
+d\t
+DDD\n
+DDD
+ e = <<'EEE'
+e#{1+2}EEE
+e\t
+EEE\n
+EEE
+ f = <<"FFF"
+F
+FF#{"f"}FFF
+F
+FFF
+
+ g = <<-GGG
+ ggg
+ GGG
+ h = <<-"HHH"
+ hhh
+ HHH
+ i = <<-'III'
+ iii
+ III
+ j = [<<-JJJ1 , <<-"JJJ2" , <<-'JJJ3' ]
+ j#{1}j
+ JJJ1
+ j#{2}j
+ JJJ2
+ j#{3}j
+ JJJ3
+
+ k = <<'KKK'.to_i
+123
+KKK
+
+ m = [<<MM1, <<MM2]
+x#{m2 = {x:<<MM3}}y
+mm3
+MM3
+mm1
+MM1
+mm2
+MM2
+
+ n = [1, "#{<<NN1}", 3,
+nn1
+NN1
+ 4]
+
+ qqq = Proc.new {|*x| x.join(' $ ')}
+ q1 = qqq.call("a", <<QQ1, "c",
+q
+QQ1
+ "d")
+ q2 = qqq.call("l", "m#{<<QQ2}n",
+qq
+QQ2
+ "o")
+
+ w = %W( 1 #{<<WWW} 3
+www
+WWW
+ 4 5 )
+
+ x = [1, <<XXX1,
+foo #{<<XXX2} bar
+222 #{<<XXX3} 444
+333
+XXX3
+5
+XXX2
+6
+XXX1
+ 9]
+
+ z = <<'ZZZ'
+ZZZ
+
+ assert_equal "aaa\n", a
+ assert_equal "bbb\n", b
+ assert_equal ["c1\n", "c 2\n", "c 3\n"], c
+ assert_equal "d3DDD\nd\t\nDDD\n\n", d
+ assert_equal "e\#{1+2}EEE\ne\\t\nEEE\\n\n", e
+ assert_equal "F\nFFfFFF\nF\n", f
+ assert_equal " ggg\n", g
+ assert_equal " hhh\n", h
+ assert_equal " iii\n", i
+ assert_equal [" j1j\n", " j2j\n", " j\#{3}j\n"], j
+ assert_equal 123, k
+ assert_equal ["x{:x=>\"mm3\\n\"}y\nmm1\n", "mm2\n"], m
+ assert_equal ({:x=>"mm3\n"}), m2
+ assert_equal [1, "nn1\n", 3, 4], n
+ assert_equal "a $ q\n $ c $ d", q1
+ assert_equal "l $ mqq\nn $ o", q2
+ assert_equal ["1", "www\n", "3", "4", "5"], w
+ assert_equal [1, "foo 222 333\n 444\n5\n bar\n6\n", 9], x
+ assert_equal "", z
+
+end
+
+
+assert('Literals Array', '8.7.6.4') do
+ a = %W{abc#{1+2}def \}g}
+ b = %W(abc #{2+3} def \(g)
+ c = %W[#{3+4}]
+ d = %W< #{4+5} >
+ e = %W//
+ f = %W[[ab cd][ef]]
+ g = %W{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+ h = %W(a\nb
+ test\ abc
+ c\
+d
+ x\y x\\y x\\\y)
+
+ assert_equal ['abc3def', '}g'], a
+ assert_equal ['abc', '5', 'def', '(g'], b
+ assert_equal ['7'],c
+ assert_equal ['9'], d
+ assert_equal [], e
+ assert_equal ['[ab', 'cd][ef]'], f
+ assert_equal ['ab', '-11', '22'], g
+ assert_equal ["a\nb", 'test abc', "c\nd", "xy", "x\\y", "x\\y"], h
+
+ a = %w{abc#{1+2}def \}g}
+ b = %w(abc #{2+3} def \(g)
+ c = %w[#{3+4}]
+ d = %w< #{4+5} >
+ e = %w//
+ f = %w[[ab cd][ef]]
+ g = %w{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+ h = %w(a\nb
+ test\ abc
+ c\
+d
+ x\y x\\y x\\\y)
+
+ assert_equal ['abc#{1+2}def', '}g'], a
+ assert_equal ['abc', '#{2+3}', 'def', '(g'], b
+ assert_equal ['#{3+4}'], c
+ assert_equal ['#{4+5}'], d
+ assert_equal [], e
+ assert_equal ['[ab', 'cd][ef]'], f
+ assert_equal ['ab', '#{-1}1', '2#{2}'], g
+ assert_equal ["a\\nb", "test abc", "c\nd", "x\\y", "x\\y", "x\\\\y"], h
+end
+
+
+assert('Literals Array of symbols') do
+ a = %I{abc#{1+2}def \}g}
+ b = %I(abc #{2+3} def \(g)
+ c = %I[#{3+4}]
+ d = %I< #{4+5} >
+ e = %I//
+ f = %I[[ab cd][ef]]
+ g = %I{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+
+ assert_equal [:'abc3def', :'}g'], a
+ assert_equal [:'abc', :'5', :'def', :'(g'], b
+ assert_equal [:'7'],c
+ assert_equal [:'9'], d
+ assert_equal [], e
+ assert_equal [:'[ab', :'cd][ef]'], f
+ assert_equal [:'ab', :'-11', :'22'], g
+
+ a = %i{abc#{1+2}def \}g}
+ b = %i(abc #{2+3} def \(g)
+ c = %i[#{3+4}]
+ d = %i< #{4+5} >
+ e = %i//
+ f = %i[[ab cd][ef]]
+ g = %i{
+ ab
+ #{-1}1
+ 2#{2}
+ }
+
+ assert_equal [:'abc#{1+2}def', :'}g'], a
+ assert_equal [:'abc', :'#{2+3}', :'def', :'(g'], b
+ assert_equal [:'#{3+4}'], c
+ assert_equal [:'#{4+5}'], d
+ assert_equal [] ,e
+ assert_equal [:'[ab', :'cd][ef]'], f
+ assert_equal [:'ab', :'#{-1}1', :'2#{2}'], g
+end
+
+assert('Literals Symbol', '8.7.6.6') do
+ # do not compile error
+ :$asd
+ :@asd
+ :@@asd
+ :asd=
+ :asd!
+ :asd?
+ :+
+ :+@
+ :if
+ :BEGIN
+
+ a = :"asd qwe"
+ b = :'foo bar'
+ c = :"a#{1+2}b"
+ d = %s(asd)
+ e = %s( foo \))
+ f = %s[asd \[
+qwe]
+ g = %s/foo#{1+2}bar/
+ h = %s{{foo bar}}
+
+ assert_equal :'asd qwe', a
+ assert_equal :"foo bar", b
+ assert_equal :a3b, c
+ assert_equal :asd, d
+ assert_equal :' foo )', e
+ assert_equal :"asd [\nqwe", f
+ assert_equal :'foo#{1+2}bar', g
+ assert_equal :'{foo bar}', h
+end
+
+# Not Implemented ATM assert('Literals Regular expression', '8.7.6.5') do
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/localjumperror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/localjumperror.rb
new file mode 100644
index 00000000..1780cb51
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/localjumperror.rb
@@ -0,0 +1,13 @@
+##
+# LocalJumpError ISO Test
+
+assert('LocalJumpError', '15.2.25') do
+ assert_equal Class, LocalJumpError.class
+# assert_raise LocalJumpError do
+# # this will cause an exception due to the wrong location
+# retry
+# end
+end
+
+# TODO 15.2.25.2.1 LocalJumpError#exit_value
+# TODO 15.2.25.2.2 LocalJumpError#reason
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/methods.rb b/web/server/h2o/libh2o/deps/mruby/test/t/methods.rb
new file mode 100644
index 00000000..f9c25dc3
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/methods.rb
@@ -0,0 +1,109 @@
+##
+# Chapter 13.3 "Methods" ISO Test
+
+assert('The alias statement', '13.3.6 a) 4)') do
+ # check aliasing in all possible ways
+
+ def alias_test_method_original; true; end
+
+ alias alias_test_method_a alias_test_method_original
+ alias :alias_test_method_b :alias_test_method_original
+
+ assert_true(alias_test_method_original)
+ assert_true(alias_test_method_a)
+ assert_true(alias_test_method_b)
+end
+
+assert('The alias statement (overwrite original)', '13.3.6 a) 4)') do
+ # check that an aliased method can be overwritten
+ # without side effect
+
+ def alias_test_method_original; true; end
+
+ alias alias_test_method_a alias_test_method_original
+ alias :alias_test_method_b :alias_test_method_original
+
+ assert_true(alias_test_method_original)
+
+ def alias_test_method_original; false; end
+
+ assert_false(alias_test_method_original)
+ assert_true(alias_test_method_a)
+ assert_true(alias_test_method_b)
+end
+
+assert('The alias statement', '13.3.6 a) 5)') do
+ # check that alias is raising NameError if
+ # non-existing method should be undefined
+
+ assert_raise(NameError) do
+ alias new_name_a non_existing_method
+ end
+
+ assert_raise(NameError) do
+ alias :new_name_b :non_existing_method
+ end
+end
+
+assert('The undef statement', '13.3.7 a) 4)') do
+ # check that undef is undefining method
+ # based on the method name
+
+ def existing_method_a; true; end
+ def existing_method_b; true; end
+ def existing_method_c; true; end
+ def existing_method_d; true; end
+ def existing_method_e; true; end
+ def existing_method_f; true; end
+
+ # check that methods are defined
+
+ assert_true(existing_method_a, 'Method should be defined')
+ assert_true(existing_method_b, 'Method should be defined')
+ assert_true(existing_method_c, 'Method should be defined')
+ assert_true(existing_method_d, 'Method should be defined')
+ assert_true(existing_method_e, 'Method should be defined')
+ assert_true(existing_method_f, 'Method should be defined')
+
+ # undefine in all possible ways and check that method
+ # is undefined
+
+ undef existing_method_a
+ assert_raise(NoMethodError) do
+ existing_method_a
+ end
+
+ undef :existing_method_b
+ assert_raise(NoMethodError) do
+ existing_method_b
+ end
+
+ undef existing_method_c, existing_method_d
+ assert_raise(NoMethodError) do
+ existing_method_c
+ end
+ assert_raise(NoMethodError) do
+ existing_method_d
+ end
+
+ undef :existing_method_e, :existing_method_f
+ assert_raise(NoMethodError) do
+ existing_method_e
+ end
+ assert_raise(NoMethodError) do
+ existing_method_f
+ end
+end
+
+assert('The undef statement (method undefined)', '13.3.7 a) 5)') do
+ # check that undef is raising NameError if
+ # non-existing method should be undefined
+
+ assert_raise(NameError) do
+ undef non_existing_method
+ end
+
+ assert_raise(NameError) do
+ undef :non_existing_method
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/module.rb b/web/server/h2o/libh2o/deps/mruby/test/t/module.rb
new file mode 100644
index 00000000..5a46c24f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/module.rb
@@ -0,0 +1,914 @@
+##
+# Module ISO Test
+
+def labeled_module(name, &block)
+ Module.new do
+ singleton_class.class_eval do
+ define_method(:to_s) { name }
+ alias_method :inspect, :to_s
+ end
+ class_eval(&block) if block
+ end
+end
+
+def labeled_class(name, supklass = Object, &block)
+ Class.new(supklass) do
+ singleton_class.class_eval do
+ define_method(:to_s) { name }
+ alias_method :inspect, :to_s
+ end
+ class_eval(&block) if block
+ end
+end
+
+assert('Module', '15.2.2') do
+ assert_equal Class, Module.class
+end
+
+# TODO not implemented ATM assert('Module.constants', '15.2.2.3.1') do
+
+# TODO not implemented ATM assert('Module.nesting', '15.2.2.3.2') do
+
+assert('Module.nesting', '15.2.2.2.2') do
+ module Test4ModuleNesting
+ module Test4ModuleNesting2
+ assert_equal [Test4ModuleNesting2, Test4ModuleNesting],
+ Module.nesting
+ end
+ end
+ module Test4ModuleNesting::Test4ModuleNesting2
+ assert_equal [Test4ModuleNesting::Test4ModuleNesting2], Module.nesting
+ end
+end
+
+assert('Module#ancestors', '15.2.2.4.9') do
+ class Test4ModuleAncestors
+ end
+ sc = Test4ModuleAncestors.singleton_class
+ r = String.ancestors
+
+ assert_equal Array, r.class
+ assert_true r.include?(String)
+ assert_true r.include?(Object)
+end
+
+assert('Module#append_features', '15.2.2.4.10') do
+ module Test4AppendFeatures
+ def self.append_features(mod)
+ Test4AppendFeatures2.const_set(:Const4AppendFeatures2, mod)
+ end
+ end
+ module Test4AppendFeatures2
+ include Test4AppendFeatures
+ end
+
+ assert_equal Test4AppendFeatures2, Test4AppendFeatures2.const_get(:Const4AppendFeatures2)
+end
+
+assert('Module#attr NameError') do
+ %w[
+ foo?
+ @foo
+ @@foo
+ $foo
+ ].each do |name|
+ module NameTest; end
+
+ assert_raise(NameError) do
+ NameTest.module_eval { attr_reader name.to_sym }
+ end
+
+ assert_raise(NameError) do
+ NameTest.module_eval { attr_writer name.to_sym }
+ end
+
+ assert_raise(NameError) do
+ NameTest.module_eval { attr name.to_sym }
+ end
+
+ assert_raise(NameError) do
+ NameTest.module_eval { attr_accessor name.to_sym }
+ end
+ end
+
+end
+
+assert('Module#attr', '15.2.2.4.11') do
+ class AttrTest
+ class << self
+ attr :cattr
+ def cattr_val=(val)
+ @cattr = val
+ end
+ end
+ attr :iattr
+ def iattr_val=(val)
+ @iattr = val
+ end
+ end
+
+ test = AttrTest.new
+ assert_true AttrTest.respond_to?(:cattr)
+ assert_true test.respond_to?(:iattr)
+
+ assert_false AttrTest.respond_to?(:cattr=)
+ assert_false test.respond_to?(:iattr=)
+
+ test.iattr_val = 'test'
+ assert_equal 'test', test.iattr
+
+ AttrTest.cattr_val = 'test'
+ assert_equal 'test', AttrTest.cattr
+end
+
+assert('Module#attr_accessor', '15.2.2.4.12') do
+ class AttrTestAccessor
+ class << self
+ attr_accessor :cattr
+ end
+ attr_accessor :iattr, 'iattr2'
+ end
+
+ attr_instance = AttrTestAccessor.new
+ assert_true AttrTestAccessor.respond_to?(:cattr=)
+ assert_true attr_instance.respond_to?(:iattr=)
+ assert_true attr_instance.respond_to?(:iattr2=)
+ assert_true AttrTestAccessor.respond_to?(:cattr)
+ assert_true attr_instance.respond_to?(:iattr)
+ assert_true attr_instance.respond_to?(:iattr2)
+
+ attr_instance.iattr = 'test'
+ assert_equal 'test', attr_instance.iattr
+
+ AttrTestAccessor.cattr = 'test'
+ assert_equal 'test', AttrTestAccessor.cattr
+end
+
+assert('Module#attr_reader', '15.2.2.4.13') do
+ class AttrTestReader
+ class << self
+ attr_reader :cattr
+ def cattr_val=(val)
+ @cattr = val
+ end
+ end
+ attr_reader :iattr, 'iattr2'
+ def iattr_val=(val)
+ @iattr = val
+ end
+ end
+
+ attr_instance = AttrTestReader.new
+ assert_true AttrTestReader.respond_to?(:cattr)
+ assert_true attr_instance.respond_to?(:iattr)
+ assert_true attr_instance.respond_to?(:iattr2)
+
+ assert_false AttrTestReader.respond_to?(:cattr=)
+ assert_false attr_instance.respond_to?(:iattr=)
+ assert_false attr_instance.respond_to?(:iattr2=)
+
+ attr_instance.iattr_val = 'test'
+ assert_equal 'test', attr_instance.iattr
+
+ AttrTestReader.cattr_val = 'test'
+ assert_equal 'test', AttrTestReader.cattr
+end
+
+assert('Module#attr_writer', '15.2.2.4.14') do
+ class AttrTestWriter
+ class << self
+ attr_writer :cattr
+ def cattr_val
+ @cattr
+ end
+ end
+ attr_writer :iattr, 'iattr2'
+ def iattr_val
+ @iattr
+ end
+ end
+
+ attr_instance = AttrTestWriter.new
+ assert_true AttrTestWriter.respond_to?(:cattr=)
+ assert_true attr_instance.respond_to?(:iattr=)
+ assert_true attr_instance.respond_to?(:iattr2=)
+
+ assert_false AttrTestWriter.respond_to?(:cattr)
+ assert_false attr_instance.respond_to?(:iattr)
+ assert_false attr_instance.respond_to?(:iattr2)
+
+ attr_instance.iattr = 'test'
+ assert_equal 'test', attr_instance.iattr_val
+
+ AttrTestWriter.cattr = 'test'
+ assert_equal 'test', AttrTestWriter.cattr_val
+end
+
+assert('Module#class_eval', '15.2.2.4.15') do
+ class Test4ClassEval
+ @a = 11
+ @b = 12
+ end
+ Test4ClassEval.class_eval do
+ def method1
+ end
+ end
+ r = Test4ClassEval.instance_methods
+
+ assert_equal 11, Test4ClassEval.class_eval{ @a }
+ assert_equal 12, Test4ClassEval.class_eval{ @b }
+ assert_equal Array, r.class
+ assert_true r.include?(:method1)
+end
+
+assert('Module#class_variable_defined?', '15.2.2.4.16') do
+ class Test4ClassVariableDefined
+ @@cv = 99
+ end
+
+ assert_true Test4ClassVariableDefined.class_variable_defined?(:@@cv)
+ assert_false Test4ClassVariableDefined.class_variable_defined?(:@@noexisting)
+end
+
+assert('Module#class_variable_get', '15.2.2.4.17') do
+ class Test4ClassVariableGet
+ @@cv = 99
+ end
+
+ assert_equal 99, Test4ClassVariableGet.class_variable_get(:@@cv)
+end
+
+assert('Module#class_variable_set', '15.2.2.4.18') do
+ class Test4ClassVariableSet
+ @@foo = 100
+ def foo
+ @@foo
+ end
+ end
+
+ assert_true Test4ClassVariableSet.class_variable_set(:@@cv, 99)
+ assert_true Test4ClassVariableSet.class_variable_set(:@@foo, 101)
+ assert_true Test4ClassVariableSet.class_variables.include? :@@cv
+ assert_equal 99, Test4ClassVariableSet.class_variable_get(:@@cv)
+ assert_equal 101, Test4ClassVariableSet.new.foo
+end
+
+assert('Module#class_variables', '15.2.2.4.19') do
+ class Test4ClassVariables1
+ @@var1 = 1
+ end
+ class Test4ClassVariables2 < Test4ClassVariables1
+ @@var2 = 2
+ end
+
+ assert_equal [:@@var1], Test4ClassVariables1.class_variables
+ assert_equal [:@@var2, :@@var1], Test4ClassVariables2.class_variables
+end
+
+assert('Module#const_defined?', '15.2.2.4.20') do
+ module Test4ConstDefined
+ Const4Test4ConstDefined = true
+ end
+
+ assert_true Test4ConstDefined.const_defined?(:Const4Test4ConstDefined)
+ assert_false Test4ConstDefined.const_defined?(:NotExisting)
+end
+
+assert('Module#const_get', '15.2.2.4.21') do
+ module Test4ConstGet
+ Const4Test4ConstGet = 42
+ end
+
+ assert_equal 42, Test4ConstGet.const_get(:Const4Test4ConstGet)
+ assert_equal 42, Test4ConstGet.const_get("Const4Test4ConstGet")
+ assert_equal 42, Object.const_get("Test4ConstGet::Const4Test4ConstGet")
+
+ assert_raise(TypeError){ Test4ConstGet.const_get(123) }
+ assert_raise(NameError){ Test4ConstGet.const_get(:I_DO_NOT_EXIST) }
+ assert_raise(NameError){ Test4ConstGet.const_get("I_DO_NOT_EXIST::ME_NEITHER") }
+end
+
+assert('Module#const_missing', '15.2.2.4.22') do
+ module Test4ConstMissing
+ def self.const_missing(sym)
+ 42 # the answer to everything
+ end
+ end
+
+ assert_equal 42, Test4ConstMissing.const_get(:ConstDoesntExist)
+end
+
+assert('Module#const_set', '15.2.2.4.23') do
+ module Test4ConstSet
+ Const4Test4ConstSet = 42
+ end
+
+ assert_true Test4ConstSet.const_set(:Const4Test4ConstSet, 23)
+ assert_equal 23, Test4ConstSet.const_get(:Const4Test4ConstSet)
+end
+
+assert('Module#constants', '15.2.2.4.24') do
+ $n = []
+ module TestA
+ C = 1
+ end
+ class TestB
+ include TestA
+ C2 = 1
+ $n = constants.sort
+ end
+
+ assert_equal [ :C ], TestA.constants
+ assert_equal [ :C, :C2 ], $n
+end
+
+assert('Module#include', '15.2.2.4.27') do
+ module Test4Include
+ Const4Include = 42
+ end
+ module Test4Include2
+ @include_result = include Test4Include
+ class << self
+ attr_reader :include_result
+ end
+ end
+
+ assert_equal 42, Test4Include2.const_get(:Const4Include)
+ assert_equal Test4Include2, Test4Include2.include_result
+end
+
+assert('Module#include?', '15.2.2.4.28') do
+ module Test4IncludeP
+ end
+ class Test4IncludeP2
+ include Test4IncludeP
+ end
+ class Test4IncludeP3 < Test4IncludeP2
+ end
+
+ assert_true Test4IncludeP2.include?(Test4IncludeP)
+ assert_true Test4IncludeP3.include?(Test4IncludeP)
+ assert_false Test4IncludeP.include?(Test4IncludeP)
+end
+
+assert('Module#included', '15.2.2.4.29') do
+ module Test4Included
+ Const4Included = 42
+ def self.included mod
+ Test4Included.const_set(:Const4Included2, mod)
+ end
+ end
+ module Test4Included2
+ include Test4Included
+ end
+
+ assert_equal 42, Test4Included2.const_get(:Const4Included)
+ assert_equal Test4Included2, Test4Included2.const_get(:Const4Included2)
+end
+
+assert('Module#included_modules', '15.2.2.4.30') do
+ module Test4includedModules
+ end
+ module Test4includedModules2
+ include Test4includedModules
+ end
+ r = Test4includedModules2.included_modules
+
+ assert_equal Array, r.class
+ assert_true r.include?(Test4includedModules)
+end
+
+assert('Module#initialize', '15.2.2.4.31') do
+ assert_kind_of Module, Module.new
+ mod = Module.new { def hello; "hello"; end }
+ assert_equal [:hello], mod.instance_methods
+ a = nil
+ mod = Module.new { |m| a = m }
+ assert_equal mod, a
+end
+
+assert('Module#instance_methods', '15.2.2.4.33') do
+ module Test4InstanceMethodsA
+ def method1() end
+ end
+ class Test4InstanceMethodsB
+ def method2() end
+ end
+ class Test4InstanceMethodsC < Test4InstanceMethodsB
+ def method3() end
+ end
+
+ r = Test4InstanceMethodsC.instance_methods(true)
+
+ assert_equal [:method1], Test4InstanceMethodsA.instance_methods
+ assert_equal [:method2], Test4InstanceMethodsB.instance_methods(false)
+ assert_equal [:method3], Test4InstanceMethodsC.instance_methods(false)
+ assert_equal Array, r.class
+ assert_true r.include?(:method3)
+ assert_true r.include?(:method2)
+end
+
+assert('Module#method_defined?', '15.2.2.4.34') do
+ module Test4MethodDefined
+ module A
+ def method1() end
+ end
+
+ class B
+ def method2() end
+ end
+
+ class C < B
+ include A
+ def method3() end
+ end
+ end
+
+ assert_true Test4MethodDefined::A.method_defined? :method1
+ assert_true Test4MethodDefined::C.method_defined? :method1
+ assert_true Test4MethodDefined::C.method_defined? "method2"
+ assert_true Test4MethodDefined::C.method_defined? "method3"
+ assert_false Test4MethodDefined::C.method_defined? "method4"
+end
+
+
+assert('Module#module_eval', '15.2.2.4.35') do
+ module Test4ModuleEval
+ @a = 11
+ @b = 12
+ end
+
+ assert_equal 11, Test4ModuleEval.module_eval{ @a }
+ assert_equal 12, Test4ModuleEval.module_eval{ @b }
+end
+
+assert('Module#remove_class_variable', '15.2.2.4.39') do
+ class Test4RemoveClassVariable
+ @@cv = 99
+ end
+
+ assert_equal 99, Test4RemoveClassVariable.remove_class_variable(:@@cv)
+ assert_false Test4RemoveClassVariable.class_variables.include? :@@cv
+end
+
+assert('Module#remove_const', '15.2.2.4.40') do
+ module Test4RemoveConst
+ ExistingConst = 23
+ end
+
+ result = Test4RemoveConst.module_eval { remove_const :ExistingConst }
+
+ name_error = false
+ begin
+ Test4RemoveConst.module_eval { remove_const :NonExistingConst }
+ rescue NameError
+ name_error = true
+ end
+
+ # Constant removed from Module
+ assert_false Test4RemoveConst.const_defined? :ExistingConst
+ # Return value of binding
+ assert_equal 23, result
+ # Name Error raised when Constant doesn't exist
+ assert_true name_error
+end
+
+assert('Module#remove_method', '15.2.2.4.41') do
+ module Test4RemoveMethod
+ class Parent
+ def hello
+ end
+ end
+
+ class Child < Parent
+ def hello
+ end
+ end
+ end
+
+ assert_true Test4RemoveMethod::Child.class_eval{ remove_method :hello }
+ assert_true Test4RemoveMethod::Child.instance_methods.include? :hello
+ assert_false Test4RemoveMethod::Child.instance_methods(false).include? :hello
+end
+
+assert('Module#undef_method', '15.2.2.4.42') do
+ module Test4UndefMethod
+ class Parent
+ def hello
+ end
+ end
+
+ class Child < Parent
+ def hello
+ end
+ end
+
+ class GrandChild < Child
+ end
+ end
+ Test4UndefMethod::Child.class_eval{ undef_method :hello }
+
+ assert_true Test4UndefMethod::Parent.new.respond_to?(:hello)
+ assert_false Test4UndefMethod::Child.new.respond_to?(:hello)
+ assert_false Test4UndefMethod::GrandChild.new.respond_to?(:hello)
+ assert_false Test4UndefMethod::Child.instance_methods(false).include? :hello
+end
+
+# Not ISO specified
+
+assert('Module#define_method') do
+ c = Class.new {
+ define_method(:m1) { :ok }
+ define_method(:m2, Proc.new { :ok })
+ }
+ assert_equal c.new.m1, :ok
+ assert_equal c.new.m2, :ok
+ assert_raise(TypeError) do
+ Class.new { define_method(:n1, nil) }
+ end
+end
+
+# @!group prepend
+ assert('Module#prepend') do
+ module M0
+ def m1; [:M0] end
+ end
+ module M1
+ def m1; [:M1, super, :M1] end
+ end
+ module M2
+ def m1; [:M2, super, :M2] end
+ end
+ M3 = Module.new do
+ def m1; [:M3, super, :M3] end
+ end
+ module M4
+ def m1; [:M4, super, :M4] end
+ end
+
+ class P0
+ include M0
+ prepend M1
+ def m1; [:C0, super, :C0] end
+ end
+ class P1 < P0
+ prepend M2, M3
+ include M4
+ def m1; [:C1, super, :C1] end
+ end
+
+ obj = P1.new
+ expected = [:M2,[:M3,[:C1,[:M4,[:M1,[:C0,[:M0],:C0],:M1],:M4],:C1],:M3],:M2]
+ assert_equal(expected, obj.m1)
+ end
+
+ assert('Module#prepend result') do
+ module TestPrepended; end
+ module TestPrependResult
+ @prepend_result = prepend TestPrepended
+ class << self
+ attr_reader :prepend_result
+ end
+ end
+
+ assert_equal TestPrependResult, TestPrependResult.prepend_result
+ end
+
+ # mruby shouldn't be affected by this since there is
+ # no visibility control (yet)
+ assert('Module#prepend public') do
+ assert_nothing_raised('ruby/ruby #8846') do
+ Class.new.prepend(Module.new)
+ end
+ end
+
+ assert('Module#prepend inheritance') do
+ bug6654 = '[ruby-core:45914]'
+ a = labeled_module('a')
+ b = labeled_module('b') { include a }
+ c = labeled_module('c') { prepend b }
+
+ #assert bug6654 do
+ # the Module#< operator should be used here instead, but we don't have it
+ assert_include(c.ancestors, a)
+ assert_include(c.ancestors, b)
+ #end
+
+ bug8357 = '[ruby-core:54736] [Bug #8357]'
+ b = labeled_module('b') { prepend a }
+ c = labeled_class('c') { include b }
+
+ #assert bug8357 do
+ # the Module#< operator should be used here instead, but we don't have it
+ assert_include(c.ancestors, a)
+ assert_include(c.ancestors, b)
+ #end
+
+ bug8357 = '[ruby-core:54742] [Bug #8357]'
+ assert_kind_of(b, c.new, bug8357)
+ end
+
+ assert('Moduler#prepend + #instance_methods') do
+ bug6655 = '[ruby-core:45915]'
+ assert_equal(Object.instance_methods, Class.new {prepend Module.new}.instance_methods, bug6655)
+ end
+
+ assert 'Module#prepend + #singleton_methods' do
+ o = Object.new
+ o.singleton_class.class_eval {prepend Module.new}
+ assert_equal([], o.singleton_methods)
+ end
+
+ assert 'Module#prepend + #remove_method' do
+ c = Class.new do
+ prepend Module.new { def foo; end }
+ end
+ assert_raise(NameError) do
+ c.class_eval do
+ remove_method(:foo)
+ end
+ end
+ c.class_eval do
+ def foo; end
+ end
+ removed = nil
+ c.singleton_class.class_eval do
+ define_method(:method_removed) {|id| removed = id}
+ end
+ assert_nothing_raised('[Bug #7843]') do
+ c.class_eval do
+ remove_method(:foo)
+ end
+ end
+ assert_equal(:foo, removed)
+ end
+
+ assert 'Module#prepend + Class#ancestors' do
+ bug6658 = '[ruby-core:45919]'
+ m = labeled_module("m")
+ c = labeled_class("c") {prepend m}
+ assert_equal([m, c], c.ancestors[0, 2], bug6658)
+
+ bug6662 = '[ruby-dev:45868]'
+ c2 = labeled_class("c2", c)
+ anc = c2.ancestors
+ assert_equal([c2, m, c, Object], anc[0..anc.index(Object)], bug6662)
+ end
+
+ assert 'Module#prepend + Module#ancestors' do
+ bug6659 = '[ruby-dev:45861]'
+ m0 = labeled_module("m0") { def x; [:m0, *super] end }
+ m1 = labeled_module("m1") { def x; [:m1, *super] end; prepend m0 }
+ m2 = labeled_module("m2") { def x; [:m2, *super] end; prepend m1 }
+ c0 = labeled_class("c0") { def x; [:c0] end }
+ c1 = labeled_class("c1") { def x; [:c1] end; prepend m2 }
+ c2 = labeled_class("c2", c0) { def x; [:c2, *super] end; include m2 }
+ #
+ assert_equal([m0, m1], m1.ancestors, bug6659)
+ #
+ bug6662 = '[ruby-dev:45868]'
+ assert_equal([m0, m1, m2], m2.ancestors, bug6662)
+ assert_equal([m0, m1, m2, c1], c1.ancestors[0, 4], bug6662)
+ assert_equal([:m0, :m1, :m2, :c1], c1.new.x)
+ assert_equal([c2, m0, m1, m2, c0], c2.ancestors[0, 5], bug6662)
+ assert_equal([:c2, :m0, :m1, :m2, :c0], c2.new.x)
+ #
+ m3 = labeled_module("m3") { include m1; prepend m1 }
+ assert_equal([m3, m0, m1], m3.ancestors)
+ m3 = labeled_module("m3") { prepend m1; include m1 }
+ assert_equal([m0, m1, m3], m3.ancestors)
+ m3 = labeled_module("m3") { prepend m1; prepend m1 }
+ assert_equal([m0, m1, m3], m3.ancestors)
+ m3 = labeled_module("m3") { include m1; include m1 }
+ assert_equal([m3, m0, m1], m3.ancestors)
+ end
+
+ assert 'Module#prepend #instance_methods(false)' do
+ bug6660 = '[ruby-dev:45863]'
+ assert_equal([:m1], Class.new{ prepend Module.new; def m1; end }.instance_methods(false), bug6660)
+ assert_equal([:m1], Class.new(Class.new{def m2;end}){ prepend Module.new; def m1; end }.instance_methods(false), bug6660)
+ end
+
+ assert 'cyclic Module#prepend' do
+ bug7841 = '[ruby-core:52205] [Bug #7841]'
+ m1 = Module.new
+ m2 = Module.new
+ m1.instance_eval { prepend(m2) }
+ assert_raise(ArgumentError, bug7841) do
+ m2.instance_eval { prepend(m1) }
+ end
+ end
+
+ # these assertions will not run without a #assert_seperately method
+ #assert 'test_prepend_optmethod' do
+ # bug7983 = '[ruby-dev:47124] [Bug #7983]'
+ # assert_separately [], %{
+ # module M
+ # def /(other)
+ # to_f / other
+ # end
+ # end
+ # Fixnum.send(:prepend, M)
+ # assert_equal(0.5, 1 / 2, "#{bug7983}")
+ # }
+ # assert_equal(0, 1 / 2)
+ #end
+
+ # mruby has no visibility control
+ assert 'Module#prepend visibility' do
+ bug8005 = '[ruby-core:53106] [Bug #8005]'
+ c = Class.new do
+ prepend Module.new {}
+ def foo() end
+ protected :foo
+ end
+ a = c.new
+ assert_true a.respond_to?(:foo), bug8005
+ assert_nothing_raised(bug8005) {a.send :foo}
+ end
+
+ # mruby has no visibility control
+ assert 'Module#prepend inherited visibility' do
+ bug8238 = '[ruby-core:54105] [Bug #8238]'
+ module Test4PrependVisibilityInherited
+ class A
+ def foo() A; end
+ private :foo
+ end
+ class B < A
+ public :foo
+ prepend Module.new
+ end
+ end
+ assert_equal(Test4PrependVisibilityInherited::A, Test4PrependVisibilityInherited::B.new.foo, "#{bug8238}")
+ end
+
+ assert 'Module#prepend + #included_modules' do
+ bug8025 = '[ruby-core:53158] [Bug #8025]'
+ mixin = labeled_module("mixin")
+ c = labeled_module("c") {prepend mixin}
+ im = c.included_modules
+ assert_not_include(im, c, bug8025)
+ assert_include(im, mixin, bug8025)
+ c1 = labeled_class("c1") {prepend mixin}
+ c2 = labeled_class("c2", c1)
+ im = c2.included_modules
+ assert_not_include(im, c1, bug8025)
+ assert_not_include(im, c2, bug8025)
+ assert_include(im, mixin, bug8025)
+ end
+
+ assert 'Module#prepend super in alias' do
+ skip "super does not currently work in aliased methods"
+ bug7842 = '[Bug #7842]'
+
+ p = labeled_module("P") do
+ def m; "P"+super; end
+ end
+
+ a = labeled_class("A") do
+ def m; "A"; end
+ end
+
+ b = labeled_class("B", a) do
+ def m; "B"+super; end
+ alias m2 m
+ prepend p
+ alias m3 m
+ end
+
+ assert_nothing_raised do
+ assert_equal("BA", b.new.m2, bug7842)
+ end
+
+ assert_nothing_raised do
+ assert_equal("PBA", b.new.m3, bug7842)
+ end
+ end
+
+ assert 'Module#prepend each class' do
+ m = labeled_module("M")
+ c1 = labeled_class("C1") {prepend m}
+ c2 = labeled_class("C2", c1) {prepend m}
+ assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should be able to prepend each class")
+ end
+
+ assert 'Module#prepend no duplication' do
+ m = labeled_module("M")
+ c = labeled_class("C") {prepend m; prepend m}
+ assert_equal([m, c], c.ancestors[0, 2], "should never duplicate")
+ end
+
+ assert 'Module#prepend in superclass' do
+ m = labeled_module("M")
+ c1 = labeled_class("C1")
+ c2 = labeled_class("C2", c1) {prepend m}
+ c1.class_eval {prepend m}
+ assert_equal([m, c2, m, c1], c2.ancestors[0, 4], "should accesisble prepended module in superclass")
+ end
+
+ # requires #assert_seperately
+ #assert 'Module#prepend call super' do
+ # assert_separately([], <<-'end;') #do
+ # bug10847 = '[ruby-core:68093] [Bug #10847]'
+ # module M; end
+ # Float.prepend M
+ # assert_nothing_raised(SystemStackError, bug10847) do
+ # 0.3.numerator
+ # end
+ # end;
+ #end
+# @!endgroup prepend
+
+assert('Module#to_s') do
+ module Outer
+ class Inner; end
+ const_set :SetInner, Class.new
+ end
+
+ assert_equal 'Outer', Outer.to_s
+ assert_equal 'Outer::Inner', Outer::Inner.to_s
+ assert_equal 'Outer::SetInner', Outer::SetInner.to_s
+
+ outer = Module.new do
+ const_set :SetInner, Class.new
+ end
+ Object.const_set :SetOuter, outer
+
+ assert_equal 'SetOuter', SetOuter.to_s
+ assert_equal 'SetOuter::SetInner', SetOuter::SetInner.to_s
+
+ mod = Module.new
+ cls = Class.new
+
+ assert_equal "#<Module:0x", mod.to_s[0,11]
+ assert_equal "#<Class:0x", cls.to_s[0,10]
+end
+
+assert('Module#inspect') do
+ module Test4to_sModules
+ end
+
+ assert_equal 'Test4to_sModules', Test4to_sModules.inspect
+end
+
+assert('Issue 1467') do
+ module M1
+ def initialize()
+ super()
+ end
+ end
+
+ class C1
+ include M1
+ def initialize()
+ super()
+ end
+ end
+
+ class C2
+ include M1
+ end
+
+ C1.new
+ C2.new
+end
+
+assert('clone Module') do
+ module M1
+ def foo
+ true
+ end
+ end
+
+ class B
+ include M1.clone
+ end
+
+ B.new.foo
+end
+
+assert('Module#module_function') do
+ module M
+ def modfunc; end
+ module_function :modfunc
+ end
+
+ assert_true M.respond_to?(:modfunc)
+end
+
+assert('module with non-class/module outer raises TypeError') do
+ assert_raise(TypeError) { module 0::M1 end }
+ assert_raise(TypeError) { module []::M2 end }
+end
+
+assert('get constant of parent module in singleton class; issue #3568') do
+ actual = module GetConstantInSingletonTest
+ EXPECTED = "value"
+ class << self
+ EXPECTED
+ end
+ end
+
+ assert_equal("value", actual)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/nameerror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/nameerror.rb
new file mode 100644
index 00000000..28682bed
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/nameerror.rb
@@ -0,0 +1,28 @@
+##
+# NameError ISO Test
+
+assert('NameError', '15.2.31') do
+ assert_equal Class, NameError.class
+end
+
+assert('NameError#name', '15.2.31.2.1') do
+
+ # This check is not duplicate with 15.2.31.2.2 check.
+ # Because the NameError in this test is generated in
+ # C API.
+ class TestDummy
+ alias foo bar
+ rescue NameError => e
+ $test_dummy_result = e.name
+ end
+
+ assert_equal :bar, $test_dummy_result
+end
+
+assert('NameError#initialize', '15.2.31.2.2') do
+ e = NameError.new('a', :foo)
+
+ assert_equal NameError, e.class
+ assert_equal 'a', e.message
+ assert_equal :foo, e.name
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/nil.rb b/web/server/h2o/libh2o/deps/mruby/test/t/nil.rb
new file mode 100644
index 00000000..b49878fc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/nil.rb
@@ -0,0 +1,39 @@
+##
+# NilClass ISO Test
+
+assert('NilClass', '15.2.4') do
+ assert_equal Class, NilClass.class
+end
+
+assert('NilClass', '15.2.4.1') do
+ assert_equal NilClass, nil.class
+ assert_false NilClass.method_defined? :new
+end
+
+assert('NilClass#&', '15.2.4.3.1') do
+ assert_false nil.&(true)
+ assert_false nil.&(nil)
+end
+
+assert('NilClass#^', '15.2.4.3.2') do
+ assert_true nil.^(true)
+ assert_false nil.^(false)
+end
+
+assert('NilClass#|', '15.2.4.3.3') do
+ assert_true nil.|(true)
+ assert_false nil.|(false)
+end
+
+assert('NilClass#nil?', '15.2.4.3.4') do
+ assert_true nil.nil?
+end
+
+assert('NilClass#to_s', '15.2.4.3.5') do
+ assert_equal '', nil.to_s
+end
+
+assert('safe navigation') do
+ assert_nil nil&.size
+ assert_equal 0, []&.size
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/nomethoderror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/nomethoderror.rb
new file mode 100644
index 00000000..5fed7968
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/nomethoderror.rb
@@ -0,0 +1,22 @@
+##
+# NoMethodError ISO Test
+
+assert('NoMethodError', '15.2.32') do
+ NoMethodError.class == Class
+ assert_raise NoMethodError do
+ doesNotExistAsAMethodNameForVerySure("")
+ end
+end
+
+assert('NoMethodError#args', '15.2.32.2.1') do
+ a = NoMethodError.new 'test', :test, [1, 2]
+ assert_equal [1, 2], a.args
+
+ assert_nothing_raised do
+ begin
+ doesNotExistAsAMethodNameForVerySure 3, 1, 4
+ rescue NoMethodError => e
+ assert_equal [3, 1, 4], e.args
+ end
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/numeric.rb b/web/server/h2o/libh2o/deps/mruby/test/t/numeric.rb
new file mode 100644
index 00000000..120cc960
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/numeric.rb
@@ -0,0 +1,43 @@
+##
+# Numeric ISO Test
+
+assert('Numeric', '15.2.7') do
+ assert_equal Class, Numeric.class
+end
+
+assert('Numeric#+@', '15.2.7.4.1') do
+ assert_equal(+1, +1)
+end
+
+assert('Numeric#-@', '15.2.7.4.2') do
+ assert_equal(-1, -1)
+end
+
+assert('Numeric#abs', '15.2.7.4.3') do
+ assert_equal(1, 1.abs)
+ assert_equal(1.0, -1.abs)
+end
+
+assert('Numeric#pow') do
+ assert_equal(8, 2 ** 3)
+ assert_equal(-8, -2 ** 3)
+ assert_equal(1, 2 ** 0)
+ assert_equal(1, 2.2 ** 0)
+ assert_equal(0.5, 2 ** -1)
+end
+
+assert('Numeric#/', '15.2.8.3.4') do
+ n = Class.new(Numeric){ def /(x); 15.1;end }.new
+
+ assert_equal(2, 10/5)
+ assert_equal(0.0625, 1/16)
+ assert_equal(15.1, n/10)
+ assert_raise(TypeError){ 1/n }
+ assert_raise(TypeError){ 1/nil }
+end
+
+# Not ISO specified
+
+assert('Numeric#**') do
+ assert_equal 8.0, 2.0**3
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/object.rb b/web/server/h2o/libh2o/deps/mruby/test/t/object.rb
new file mode 100644
index 00000000..6a755d3b
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/object.rb
@@ -0,0 +1,11 @@
+##
+# Object ISO Test
+
+assert('Object', '15.2.1') do
+ assert_equal Class, Object.class
+end
+
+assert('Object superclass', '15.2.1.2') do
+ assert_equal BasicObject, Object.superclass
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/proc.rb b/web/server/h2o/libh2o/deps/mruby/test/t/proc.rb
new file mode 100644
index 00000000..42ac3b94
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/proc.rb
@@ -0,0 +1,180 @@
+##
+# Proc ISO Test
+
+assert('Proc', '15.2.17') do
+ assert_equal Class, Proc.class
+end
+
+assert('Proc.new', '15.2.17.3.1') do
+ assert_raise ArgumentError do
+ Proc.new
+ end
+
+ assert_equal (Proc.new {}).class, Proc
+
+ assert_raise LocalJumpError do
+ Proc.new{ break }.call
+ end
+end
+
+assert('Proc#[]', '15.2.17.4.1') do
+ a = 0
+ b = Proc.new { a += 1 }
+ b.[]
+
+ a2 = 0
+ b2 = Proc.new { |i| a2 += i }
+ b2.[](5)
+
+ assert_equal 1, a
+ assert_equal 5, a2
+end
+
+assert('Proc#arity', '15.2.17.4.2') do
+ a = Proc.new {|x, y|}.arity
+ b = Proc.new {|x, *y, z|}.arity
+ c = Proc.new {|x=0, y|}.arity
+ d = Proc.new {|(x, y), z=0|}.arity
+
+ assert_equal 2, a
+ assert_equal(-3, b)
+ assert_equal 1, c
+ assert_equal 1, d
+
+ e = ->(x=0, y){}.arity
+ f = ->((x, y), z=0){}.arity
+ g = ->(x=0){}.arity
+
+ assert_equal(-2, e)
+ assert_equal(-2, f)
+ assert_equal(-1, g)
+end
+
+assert('Proc#call', '15.2.17.4.3') do
+ a = 0
+ b = Proc.new { a += 1 }
+ b.call
+
+ a2 = 0
+ b2 = Proc.new { |i| a2 += i }
+ b2.call(5)
+
+ assert_equal 1, a
+ assert_equal 5, a2
+end
+
+assert('Proc#call proc args pos block') do
+ pr = Proc.new {|a,b,&c|
+ [a, b, c.class, c&&c.call(:x)]
+ }
+ assert_equal [nil, nil, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+
+ assert_equal [nil, nil, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+end
+
+assert('Proc#call proc args pos rest post') do
+ pr = Proc.new {|a,b,*c,d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal [nil, nil, [], nil, nil], pr.call()
+ assert_equal [1, nil, [], nil, nil], pr.call(1)
+ assert_equal [1, 2, [], nil, nil], pr.call(1,2)
+ assert_equal [1, 2, [], 3, nil], pr.call(1,2,3)
+ assert_equal [1, 2, [], 3, 4], pr.call(1,2,3,4)
+ assert_equal [1, 2, [3], 4, 5], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, [3, 4], 5, 6], pr.call(1,2,3,4,5,6)
+ assert_equal [1, 2, [3, 4, 5], 6,7], pr.call(1,2,3,4,5,6,7)
+
+ assert_equal [nil, nil, [], nil, nil], pr.call([])
+ assert_equal [1, nil, [], nil, nil], pr.call([1])
+ assert_equal [1, 2, [], nil, nil], pr.call([1,2])
+ assert_equal [1, 2, [], 3, nil], pr.call([1,2,3])
+ assert_equal [1, 2, [], 3, 4], pr.call([1,2,3,4])
+ assert_equal [1, 2, [3], 4, 5], pr.call([1,2,3,4,5])
+ assert_equal [1, 2, [3, 4], 5, 6], pr.call([1,2,3,4,5,6])
+ assert_equal [1, 2, [3, 4, 5], 6,7], pr.call([1,2,3,4,5,6,7])
+end
+
+assert('Proc#return_does_not_break_self') do
+ class TestClass
+ attr_accessor :block
+ def initialize
+ end
+ def return_array
+ @block = Proc.new { self }
+ return []
+ end
+ def return_instance_variable
+ @block = Proc.new { self }
+ return @block
+ end
+ def return_const_fixnum
+ @block = Proc.new { self }
+ return 123
+ end
+ def return_nil
+ @block = Proc.new { self }
+ return nil
+ end
+ end
+
+ c = TestClass.new
+ assert_equal [], c.return_array
+ assert_equal c, c.block.call
+
+ c.return_instance_variable
+ assert_equal c, c.block.call
+
+ assert_equal 123, c.return_const_fixnum
+ assert_equal c, c.block.call
+
+ assert_equal nil, c.return_nil
+ assert_equal c, c.block.call
+end
+
+assert('call Proc#initialize if defined') do
+ a = []
+ c = Class.new(Proc) do
+ define_method(:initialize) do
+ a << :ok
+ end
+ end
+
+ assert_kind_of c, c.new{}
+ assert_equal [:ok], a
+end
+
+assert('&obj call to_proc if defined') do
+ pr = Proc.new{}
+ def mock(&b)
+ b
+ end
+ assert_equal pr.object_id, mock(&pr).object_id
+ assert_equal pr, mock(&pr)
+
+ obj = Object.new
+ def obj.to_proc
+ Proc.new{ :from_to_proc }
+ end
+ assert_equal :from_to_proc, mock(&obj).call
+
+ assert_raise(TypeError){ mock(&(Object.new)) }
+end
+
+assert('Creation of a proc through the block of a method') do
+ def m(&b) b end
+
+ assert_equal m{}.class, Proc
+
+ assert_raise LocalJumpError do
+ m{ break }.call
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/range.rb b/web/server/h2o/libh2o/deps/mruby/test/t/range.rb
new file mode 100644
index 00000000..5391369d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/range.rb
@@ -0,0 +1,95 @@
+##
+# Range ISO Test
+
+assert('Range', '15.2.14') do
+ assert_equal Class, Range.class
+end
+
+assert('Range#==', '15.2.14.4.1') do
+ assert_true (1..10) == (1..10)
+ assert_false (1..10) == (1..100)
+ assert_true (1..10) == Range.new(1.0, 10.0)
+end
+
+assert('Range#===', '15.2.14.4.2') do
+ a = (1..10)
+
+ assert_true a === 5
+ assert_false a === 20
+end
+
+assert('Range#begin', '15.2.14.4.3') do
+ assert_equal 1, (1..10).begin
+end
+
+assert('Range#each', '15.2.14.4.4') do
+ a = (1..3)
+ b = 0
+ a.each {|i| b += i}
+ assert_equal 6, b
+end
+
+assert('Range#end', '15.2.14.4.5') do
+ assert_equal 10, (1..10).end
+end
+
+assert('Range#exclude_end?', '15.2.14.4.6') do
+ assert_true (1...10).exclude_end?
+ assert_false (1..10).exclude_end?
+end
+
+assert('Range#first', '15.2.14.4.7') do
+ assert_equal 1, (1..10).first
+end
+
+assert('Range#include?', '15.2.14.4.8') do
+ assert_true (1..10).include?(10)
+ assert_false (1..10).include?(11)
+
+ assert_true (1...10).include?(9)
+ assert_false (1...10).include?(10)
+end
+
+assert('Range#initialize', '15.2.14.4.9') do
+ a = Range.new(1, 10, true)
+ b = Range.new(1, 10, false)
+
+ assert_equal (1...10), a
+ assert_true a.exclude_end?
+ assert_equal (1..10), b
+ assert_false b.exclude_end?
+
+ assert_raise(NameError) { (0..1).send(:initialize, 1, 3) }
+end
+
+assert('Range#last', '15.2.14.4.10') do
+ assert_equal 10, (1..10).last
+end
+
+assert('Range#member?', '15.2.14.4.11') do
+ a = (1..10)
+
+ assert_true a.member?(5)
+ assert_false a.member?(20)
+end
+
+assert('Range#to_s', '15.2.14.4.12') do
+ assert_equal "0..1", (0..1).to_s
+ assert_equal "0...1", (0...1).to_s
+ assert_equal "a..b", ("a".."b").to_s
+ assert_equal "a...b", ("a"..."b").to_s
+end
+
+assert('Range#inspect', '15.2.14.4.13') do
+ assert_equal "0..1", (0..1).inspect
+ assert_equal "0...1", (0...1).inspect
+ assert_equal "\"a\"..\"b\"", ("a".."b").inspect
+ assert_equal "\"a\"...\"b\"", ("a"..."b").inspect
+end
+
+assert('Range#eql?', '15.2.14.4.14') do
+ assert_true (1..10).eql? (1..10)
+ assert_false (1..10).eql? (1..100)
+ assert_false (1..10).eql? (Range.new(1.0, 10.0))
+ assert_false (1..10).eql? "1..10"
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/rangeerror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/rangeerror.rb
new file mode 100644
index 00000000..97878096
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/rangeerror.rb
@@ -0,0 +1,6 @@
+##
+# RangeError ISO Test
+
+assert('RangeError', '15.2.26') do
+ assert_equal Class, RangeError.class
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/regexperror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/regexperror.rb
new file mode 100644
index 00000000..b8f8c2c1
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/regexperror.rb
@@ -0,0 +1,4 @@
+##
+# RegexpError ISO Test
+
+# TODO broken ATM assert('RegexpError', '15.2.27') do
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/runtimeerror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/runtimeerror.rb
new file mode 100644
index 00000000..d02cba96
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/runtimeerror.rb
@@ -0,0 +1,6 @@
+##
+# RuntimeError ISO Test
+
+assert('RuntimeError', '15.2.28') do
+ assert_equal Class, RuntimeError.class
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/standarderror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/standarderror.rb
new file mode 100644
index 00000000..c349b08c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/standarderror.rb
@@ -0,0 +1,6 @@
+##
+# StandardError ISO Test
+
+assert('StandardError', '15.2.23') do
+ assert_equal Class, StandardError.class
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/string.rb b/web/server/h2o/libh2o/deps/mruby/test/t/string.rb
new file mode 100644
index 00000000..a4139622
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/string.rb
@@ -0,0 +1,727 @@
+# coding: utf-8
+##
+# String ISO Test
+
+UTF8STRING = ("\343\201\202".size == 1)
+
+assert('String', '15.2.10') do
+ assert_equal Class, String.class
+end
+
+assert('String#<=>', '15.2.10.5.1') do
+ a = '' <=> ''
+ b = '' <=> 'not empty'
+ c = 'not empty' <=> ''
+ d = 'abc' <=> 'cba'
+ e = 'cba' <=> 'abc'
+
+ assert_equal 0, a
+ assert_equal(-1, b)
+ assert_equal 1, c
+ assert_equal(-1, d)
+ assert_equal 1, e
+end
+
+assert('String#==', '15.2.10.5.2') do
+ assert_equal 'abc', 'abc'
+ assert_not_equal 'abc', 'cba'
+end
+
+# 'String#=~', '15.2.10.5.3' will be tested in mrbgems.
+
+assert('String#+', '15.2.10.5.4') do
+ assert_equal 'ab', 'a' + 'b'
+end
+
+assert('String#*', '15.2.10.5.5') do
+ assert_equal 'aaaaa', 'a' * 5
+ assert_equal '', 'a' * 0
+ assert_raise(ArgumentError) do
+ 'a' * -1
+ end
+end
+
+assert('String#[]', '15.2.10.5.6') do
+ # length of args is 1
+ a = 'abc'[0]
+ b = 'abc'[-1]
+ c = 'abc'[10]
+ d = 'abc'[-10]
+ e = 'abc'[1.1]
+
+ # length of args is 2
+ a1 = 'abc'[0, -1]
+ b1 = 'abc'[10, 0]
+ c1 = 'abc'[-10, 0]
+ d1 = 'abc'[0, 0]
+ e1 = 'abc'[1, 2]
+
+ # args is RegExp
+ # It will be tested in mrbgems.
+
+ # args is String
+ a3 = 'abc'['bc']
+ b3 = 'abc'['XX']
+
+ assert_equal 'a', 'a'
+ # assert_equal 'c', b
+ # assert_nil c
+ # assert_nil d
+ # assert_equal 'b', e
+ # assert_nil a1
+ # assert_nil b1
+ # assert_nil c1
+ # assert_equal '', d1
+ # assert_equal 'bc', e1
+ # assert_equal 'bc', a3
+ # assert_nil b3
+
+ # assert_raise(TypeError) do
+ # a[nil]
+ # end
+end
+
+assert('String#[](UTF-8)', '15.2.10.5.6') do
+ assert_equal "ち", "こんにちは世界"[3]
+ assert_equal nil, "こんにちは世界"[20]
+ assert_equal "世", "こんにちは世界"[-2]
+ assert_equal "世界", "こんにちは世界"[-2..-1]
+ assert_equal "んに", "こんにちは世界"[1,2]
+ assert_equal "世", "こんにちは世界"["世"]
+end if UTF8STRING
+
+assert('String#[] with Range') do
+ a1 = 'abc'[1..0]
+ b1 = 'abc'[1..1]
+ c1 = 'abc'[1..2]
+ d1 = 'abc'[1..3]
+ e1 = 'abc'[1..4]
+ f1 = 'abc'[0..-2]
+ g1 = 'abc'[-2..3]
+ h1 = 'abc'[3..4]
+ i1 = 'abc'[4..5]
+ j1 = 'abcdefghijklmnopqrstuvwxyz'[1..3]
+ a2 = 'abc'[1...0]
+ b2 = 'abc'[1...1]
+ c2 = 'abc'[1...2]
+ d2 = 'abc'[1...3]
+ e2 = 'abc'[1...4]
+ f2 = 'abc'[0...-2]
+ g2 = 'abc'[-2...3]
+ h2 = 'abc'[3...4]
+ i2 = 'abc'[4...5]
+ j2 = 'abcdefghijklmnopqrstuvwxyz'[1...3]
+
+ assert_equal '', a1
+ assert_equal 'b', b1
+ assert_equal 'bc', c1
+ assert_equal 'bc', d1
+ assert_equal 'bc', e1
+ assert_equal 'ab', f1
+ assert_equal 'bc', g1
+ assert_equal '', h1
+ assert_nil i2
+ assert_equal 'bcd', j1
+ assert_equal '', a2
+ assert_equal '', b2
+ assert_equal 'b', c2
+ assert_equal 'bc', d2
+ assert_equal 'bc', e2
+ assert_equal 'a', f2
+ assert_equal 'bc', g2
+ assert_equal '', h2
+ assert_nil i2
+ assert_equal 'bc', j2
+end
+
+assert('String#[]=') do
+ # length of args is 1
+ a = 'abc'
+ a[0] = 'X'
+ assert_equal 'Xbc', a
+
+ b = 'abc'
+ b[-1] = 'X'
+ assert_equal 'abX', b
+
+ c = 'abc'
+ assert_raise(IndexError) do
+ c[10] = 'X'
+ end
+
+ d = 'abc'
+ assert_raise(IndexError) do
+ d[-10] = 'X'
+ end
+
+ e = 'abc'
+ e[1.1] = 'X'
+ assert_equal 'aXc', e
+
+
+ # length of args is 2
+ a1 = 'abc'
+ assert_raise(IndexError) do
+ a1[0, -1] = 'X'
+ end
+
+ b1 = 'abc'
+ assert_raise(IndexError) do
+ b1[10, 0] = 'X'
+ end
+
+ c1 = 'abc'
+ assert_raise(IndexError) do
+ c1[-10, 0] = 'X'
+ end
+
+ d1 = 'abc'
+ d1[0, 0] = 'X'
+ assert_equal 'Xabc', d1
+
+ e1 = 'abc'
+ e1[1, 3] = 'X'
+ assert_equal 'aX', e1
+
+ # args is RegExp
+ # It will be tested in mrbgems.
+
+ # args is String
+ a3 = 'abc'
+ a3['bc'] = 'X'
+ assert_equal a3, 'aX'
+
+ b3 = 'abc'
+ assert_raise(IndexError) do
+ b3['XX'] = 'Y'
+ end
+end
+
+assert('String#capitalize', '15.2.10.5.7') do
+ a = 'abc'
+ a.capitalize
+
+ assert_equal 'abc', a
+ assert_equal 'Abc', 'abc'.capitalize
+end
+
+assert('String#capitalize!', '15.2.10.5.8') do
+ a = 'abc'
+ a.capitalize!
+
+ assert_equal 'Abc', a
+ assert_equal nil, 'Abc'.capitalize!
+end
+
+assert('String#chomp', '15.2.10.5.9') do
+ a = 'abc'.chomp
+ b = ''.chomp
+ c = "abc\n".chomp
+ d = "abc\n\n".chomp
+ e = "abc\t".chomp("\t")
+ f = "abc\n"
+
+ f.chomp
+
+ assert_equal 'abc', a
+ assert_equal '', b
+ assert_equal 'abc', c
+ assert_equal "abc\n", d
+ assert_equal 'abc', e
+ assert_equal "abc\n", f
+end
+
+assert('String#chomp!', '15.2.10.5.10') do
+ a = 'abc'
+ b = ''
+ c = "abc\n"
+ d = "abc\n\n"
+ e = "abc\t"
+
+ a.chomp!
+ b.chomp!
+ c.chomp!
+ d.chomp!
+ e.chomp!("\t")
+
+ assert_equal 'abc', a
+ assert_equal '', b
+ assert_equal 'abc', c
+ assert_equal "abc\n", d
+ assert_equal 'abc', e
+end
+
+assert('String#chomp! uses the correct length') do
+ class A
+ def to_str
+ $s.replace("AA")
+ "A"
+ end
+ end
+
+ $s = "AAA"
+ $s.chomp!(A.new)
+ assert_equal $s, "A"
+end
+
+assert('String#chop', '15.2.10.5.11') do
+ a = ''.chop
+ b = 'abc'.chop
+ c = 'abc'
+
+ c.chop
+
+ assert_equal '', a
+ assert_equal 'ab', b
+ assert_equal 'abc', c
+end
+
+assert('String#chop(UTF-8)', '15.2.10.5.11') do
+ a = ''.chop
+ b = 'あいう'.chop
+ c = "あ\nい".chop.chop
+
+ assert_equal '', a
+ assert_equal 'あい', b
+ assert_equal 'あ', c
+end if UTF8STRING
+
+assert('String#chop!', '15.2.10.5.12') do
+ a = ''
+ b = 'abc'
+
+ a.chop!
+ b.chop!
+
+ assert_equal a, ''
+ assert_equal b, 'ab'
+end
+
+assert('String#chop!(UTF-8)', '15.2.10.5.12') do
+ a = ''
+ b = "あいうえ\n"
+ c = "あいうえ\n"
+
+ a.chop!
+ b.chop!
+ c.chop!
+ c.chop!
+
+ assert_equal a, ''
+ assert_equal b, 'あいうえ'
+ assert_equal c, 'あいう'
+end if UTF8STRING
+
+assert('String#downcase', '15.2.10.5.13') do
+ a = 'ABC'.downcase
+ b = 'ABC'
+
+ b.downcase
+
+ assert_equal 'abc', a
+ assert_equal 'ABC', b
+end
+
+assert('String#downcase!', '15.2.10.5.14') do
+ a = 'ABC'
+
+ a.downcase!
+
+ assert_equal 'abc', a
+ assert_equal nil, 'abc'.downcase!
+end
+
+assert('String#each_line', '15.2.10.5.15') do
+ a = "first line\nsecond line\nthird line"
+ list = ["first line\n", "second line\n", "third line"]
+ n_list = []
+
+ a.each_line do |line|
+ n_list << line
+ end
+
+ assert_equal list, n_list
+
+ n_list.clear
+ a.each_line("li") do |line|
+ n_list << line
+ end
+ assert_equal ["first li", "ne\nsecond li", "ne\nthird li", "ne"], n_list
+end
+
+assert('String#empty?', '15.2.10.5.16') do
+ a = ''
+ b = 'not empty'
+
+ assert_true a.empty?
+ assert_false b.empty?
+end
+
+assert('String#eql?', '15.2.10.5.17') do
+ assert_true 'abc'.eql?('abc')
+ assert_false 'abc'.eql?('cba')
+end
+
+assert('String#gsub', '15.2.10.5.18') do
+ assert_equal('aBcaBc', 'abcabc'.gsub('b', 'B'), 'gsub without block')
+ assert_equal('aBcaBc', 'abcabc'.gsub('b'){|w| w.capitalize }, 'gsub with block')
+ assert_equal('$a$a$', '#a#a#'.gsub('#', '$'), 'mruby/mruby#847')
+ assert_equal('$a$a$', '#a#a#'.gsub('#'){|w| '$' }, 'mruby/mruby#847 with block')
+ assert_equal('$$a$$', '##a##'.gsub('##', '$$'), 'mruby/mruby#847 another case')
+ assert_equal('$$a$$', '##a##'.gsub('##'){|w| '$$' }, 'mruby/mruby#847 another case with block')
+ assert_equal('A', 'a'.gsub('a', 'A'))
+ assert_equal('A', 'a'.gsub('a'){|w| w.capitalize })
+ assert_equal("<a><><>", 'a'.gsub('a', '<\0><\1><\2>'))
+ assert_equal(".h.e.l.l.o.", "hello".gsub("", "."))
+ a = []
+ assert_equal(".h.e.l.l.o.", "hello".gsub("") { |i| a << i; "." })
+ assert_equal(["", "", "", "", "", ""], a)
+ assert_raise(ArgumentError) { "".gsub }
+ assert_raise(ArgumentError) { "".gsub("", "", "") }
+end
+
+assert('String#gsub with backslash') do
+ s = 'abXcdXef'
+ assert_equal 'ab<\\>cd<\\>ef', s.gsub('X', '<\\\\>')
+ assert_equal 'ab<X>cd<X>ef', s.gsub('X', '<\\&>')
+ assert_equal 'ab<X>cd<X>ef', s.gsub('X', '<\\0>')
+ assert_equal 'ab<ab>cd<abXcd>ef', s.gsub('X', '<\\`>')
+ assert_equal 'ab<cdXef>cd<ef>ef', s.gsub('X', '<\\\'>')
+end
+
+assert('String#gsub!', '15.2.10.5.19') do
+ a = 'abcabc'
+ a.gsub!('b', 'B')
+
+ b = 'abcabc'
+ b.gsub!('b') { |w| w.capitalize }
+
+ assert_equal 'aBcaBc', a
+ assert_equal 'aBcaBc', b
+end
+
+assert('String#hash', '15.2.10.5.20') do
+ a = 'abc'
+
+ assert_equal 'abc'.hash, a.hash
+end
+
+assert('String#include?', '15.2.10.5.21') do
+ assert_true 'abc'.include?('a')
+ assert_false 'abc'.include?('d')
+end
+
+assert('String#index', '15.2.10.5.22') do
+ assert_equal 0, 'abc'.index('a')
+ assert_nil 'abc'.index('d')
+ assert_equal 3, 'abcabc'.index('a', 1)
+ assert_equal 5, "hello".index("", 5)
+ assert_equal nil, "hello".index("", 6)
+end
+
+assert('String#initialize', '15.2.10.5.23') do
+ a = ''
+ a.initialize('abc')
+ assert_equal 'abc', a
+
+ a.initialize('abcdefghijklmnopqrstuvwxyz')
+ assert_equal 'abcdefghijklmnopqrstuvwxyz', a
+end
+
+assert('String#initialize_copy', '15.2.10.5.24') do
+ a = ''
+ a.initialize_copy('abc')
+
+ assert_equal 'abc', a
+end
+
+assert('String#intern', '15.2.10.5.25') do
+ assert_equal :abc, 'abc'.intern
+end
+
+assert('String#length', '15.2.10.5.26') do
+ assert_equal 3, 'abc'.length
+end
+
+# 'String#match', '15.2.10.5.27' will be tested in mrbgems.
+
+assert('String#replace', '15.2.10.5.28') do
+ a = ''
+ a.replace('abc')
+
+ assert_equal 'abc', a
+ assert_equal 'abc', 'cba'.replace(a)
+
+ b = 'abc' * 10
+ c = ('cba' * 10).dup
+ b.replace(c);
+ c.replace(b);
+ assert_equal c, b
+
+ # shared string
+ s = "foo" * 100
+ a = s[10, 90] # create shared string
+ assert_equal("", s.replace("")) # clear
+ assert_equal("", s) # s is cleared
+ assert_not_equal("", a) # a should not be affected
+end
+
+assert('String#reverse', '15.2.10.5.29') do
+ a = 'abc'
+ a.reverse
+
+ assert_equal 'abc', a
+ assert_equal 'cba', 'abc'.reverse
+end
+
+assert('String#reverse(UTF-8)', '15.2.10.5.29') do
+ assert_equal "ち", "こんにちは世界"[3]
+ assert_equal nil, "こんにちは世界"[20]
+ assert_equal "世", "こんにちは世界"[-2]
+ assert_equal "世界", "こんにちは世界"[-2..-1]
+ assert_equal "んに", "こんにちは世界"[1,2]
+ assert_equal "世", "こんにちは世界"["世"]
+end if UTF8STRING
+
+assert('String#reverse!', '15.2.10.5.30') do
+ a = 'abc'
+ a.reverse!
+
+ assert_equal 'cba', a
+ assert_equal 'cba', 'abc'.reverse!
+end
+
+assert('String#reverse!(UTF-8)', '15.2.10.5.30') do
+ a = 'こんにちは世界!'
+ a.reverse!
+
+ assert_equal '!界世はちにんこ', a
+ assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse!
+end if UTF8STRING
+
+assert('String#rindex', '15.2.10.5.31') do
+ assert_equal 0, 'abc'.rindex('a')
+ assert_nil 'abc'.rindex('d')
+ assert_equal 0, 'abcabc'.rindex('a', 1)
+ assert_equal 3, 'abcabc'.rindex('a', 4)
+end
+
+assert('String#rindex(UTF-8)', '15.2.10.5.31') do
+ str = "こんにちは世界!\nこんにちは世界!"
+ assert_nil str.index('さ')
+ assert_equal 3, str.index('ち')
+ assert_equal 12, str.index('ち', 10)
+ assert_equal nil, str.index("さ")
+end if UTF8STRING
+
+# 'String#scan', '15.2.10.5.32' will be tested in mrbgems.
+
+assert('String#size', '15.2.10.5.33') do
+ assert_equal 3, 'abc'.size
+end
+
+assert('String#size(UTF-8)', '15.2.10.5.33') do
+ str = 'こんにちは世界!'
+ assert_equal 8, str.size
+ assert_not_equal str.bytesize, str.size
+ assert_equal 2, str[1, 2].size
+end if UTF8STRING
+
+assert('String#slice', '15.2.10.5.34') do
+ # length of args is 1
+ a = 'abc'.slice(0)
+ b = 'abc'.slice(-1)
+ c = 'abc'.slice(10)
+ d = 'abc'.slice(-10)
+
+ # length of args is 2
+ a1 = 'abc'.slice(0, -1)
+ b1 = 'abc'.slice(10, 0)
+ c1 = 'abc'.slice(-10, 0)
+ d1 = 'abc'.slice(0, 0)
+ e1 = 'abc'.slice(1, 2)
+
+ # slice of shared string
+ e11 = e1.slice(0)
+
+ # args is RegExp
+ # It will be tested in mrbgems.
+
+ # args is String
+ a3 = 'abc'.slice('bc')
+ b3 = 'abc'.slice('XX')
+
+ assert_equal 'a', a
+ assert_equal 'c', b
+ assert_nil c
+ assert_nil d
+ assert_nil a1
+ assert_nil b1
+ assert_nil c1
+ assert_equal '', d1
+ assert_equal 'bc', e1
+ assert_equal 'b', e11
+ assert_equal 'bc', a3
+ assert_nil b3
+end
+
+# TODO Broken ATM
+assert('String#split', '15.2.10.5.35') do
+ # without RegExp behavior is actually unspecified
+ assert_equal ['abc', 'abc', 'abc'], 'abc abc abc'.split
+ assert_equal ["a", "b", "c", "", "d"], 'a,b,c,,d'.split(',')
+ assert_equal ['abc', 'abc', 'abc'], 'abc abc abc'.split(nil)
+ assert_equal ['a', 'b', 'c'], 'abc'.split("")
+end
+
+assert('String#split(UTF-8)', '15.2.10.5.35') do
+ got = "こんにちは世界!".split('')
+ assert_equal ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'], got
+ got = "こんにちは世界!".split('に')
+ assert_equal ['こん', 'ちは世界!'], got
+end if UTF8STRING
+
+assert('String#sub', '15.2.10.5.36') do
+ assert_equal 'aBcabc', 'abcabc'.sub('b', 'B')
+ assert_equal 'aBcabc', 'abcabc'.sub('b') { |w| w.capitalize }
+ assert_equal 'aa$', 'aa#'.sub('#', '$')
+ assert_equal '.abc', "abc".sub("", ".")
+
+ str = "abc"
+ miss = str.sub("X", "Z")
+ assert_equal str, miss
+ assert_not_equal str.object_id, miss.object_id
+
+ a = []
+ assert_equal '.abc', "abc".sub("") { |i| a << i; "." }
+ assert_equal [""], a
+end
+
+assert('String#sub with backslash') do
+ s = 'abXcdXef'
+ assert_equal 'ab<\\>cdXef', s.sub('X', '<\\\\>')
+ assert_equal 'ab<X>cdXef', s.sub('X', '<\\&>')
+ assert_equal 'ab<X>cdXef', s.sub('X', '<\\0>')
+ assert_equal 'ab<ab>cdXef', s.sub('X', '<\\`>')
+ assert_equal 'ab<cdXef>cdXef', s.sub('X', '<\\\'>')
+end
+
+assert('String#sub!', '15.2.10.5.37') do
+ a = 'abcabc'
+ a.sub!('b', 'B')
+
+ b = 'abcabc'
+ b.sub!('b') { |w| w.capitalize }
+
+ assert_equal 'aBcabc', a
+ assert_equal 'aBcabc', b
+end
+
+assert('String#to_f', '15.2.10.5.38') do
+ a = ''.to_f
+ b = '123456789'.to_f
+ c = '12345.6789'.to_f
+ d = '1e-2147483648'.to_f
+ e = '1e2147483648'.to_f
+
+ assert_float(0.0, a)
+ assert_float(123456789.0, b)
+ assert_float(12345.6789, c)
+ assert_float(0, d)
+ assert_float(Float::INFINITY, e)
+end
+
+assert('String#to_i', '15.2.10.5.39') do
+ a = ''.to_i
+ b = '32143'.to_i
+ c = 'a'.to_i(16)
+ d = '100'.to_i(2)
+ e = '1_000'.to_i
+
+ assert_equal 0, a
+ assert_equal 32143, b
+ assert_equal 10, c
+ assert_equal 4, d
+ assert_equal 1_000, e
+end
+
+assert('String#to_s', '15.2.10.5.40') do
+ assert_equal 'abc', 'abc'.to_s
+end
+
+assert('String#to_sym', '15.2.10.5.41') do
+ assert_equal :abc, 'abc'.to_sym
+end
+
+assert('String#upcase', '15.2.10.5.42') do
+ a = 'abc'.upcase
+ b = 'abc'
+
+ b.upcase
+
+ assert_equal 'ABC', a
+ assert_equal 'abc', b
+end
+
+assert('String#upcase!', '15.2.10.5.43') do
+ a = 'abc'
+
+ a.upcase!
+
+ assert_equal 'ABC', a
+ assert_equal nil, 'ABC'.upcase!
+
+ a = 'abcdefghijklmnopqrstuvwxyz'
+ b = a.dup
+ a.upcase!
+ b.upcase!
+ assert_equal 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', b
+end
+
+assert('String#inspect', '15.2.10.5.46') do
+ # should not raise an exception - regress #1210
+ assert_nothing_raised do
+ ("\1" * 100).inspect
+ end
+
+ assert_equal "\"\\000\"", "\0".inspect
+end
+
+# Not ISO specified
+
+assert('String interpolation (mrb_str_concat for shared strings)') do
+ a = "A" * 32
+ assert_equal "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:", "#{a}:"
+end
+
+assert('Check the usage of a NUL character') do
+ "qqq\0ppp"
+end
+
+assert('String#bytes') do
+ str1 = "hello"
+ bytes1 = [104, 101, 108, 108, 111]
+
+ str2 = "\xFF"
+ bytes2 = [0xFF]
+
+ assert_equal bytes1, str1.bytes
+ assert_equal bytes2, str2.bytes
+end
+
+assert('String#each_byte') do
+ str1 = "hello"
+ bytes1 = [104, 101, 108, 108, 111]
+ bytes2 = []
+
+ str1.each_byte {|b| bytes2 << b }
+
+ assert_equal bytes1, bytes2
+end
+
+assert('String#freeze') do
+ str = "hello"
+ str.freeze
+
+ assert_raise(RuntimeError) { str.upcase! }
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/superclass.rb b/web/server/h2o/libh2o/deps/mruby/test/t/superclass.rb
new file mode 100644
index 00000000..10b6438d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/superclass.rb
@@ -0,0 +1,47 @@
+[
+ # [:Object, :implementation_defined_value, '15.2.2.1'],
+ [:Module, :Object, '15.2.2.2'],
+ [:Class, :Module, '15.2.3.2'],
+ [:NilClass, :Object, '15.2.4.2'],
+ [:TrueClass, :Object, '15.2.5.2'],
+ [:FalseClass, :Object, '15.2.6.2'],
+ [:Numeric, :Object, '15.2.7.2'],
+ [:Integer, :Numeric, '15.2.8.2'],
+ [:Float, :Numeric, '15.2.9.2'],
+ [:String, :Object, '15.2.10.2'],
+ [:Symbol, :Object, '15.2.11.2'],
+ [:Array, :Object, '15.2.12.2'],
+ [:Hash, :Object, '15.2.13.2'],
+ [:Range, :Object, '15.2.14.2'],
+# [:Regexp, :Object, '15.2.15.2'], #No Regexp in mruby core
+# [:MatchData, :Object, '15.2.16.2'],
+ [:Proc, :Object, '15.2.17.2'],
+# [:Struct, :Object, '15.2.18.2'],
+# [:Time, :Object, '15.2.19.2'],
+# [:IO, :Object, '15.2.20.2'],
+# [:File, :IO, '15.2.21.2'],
+ [:Exception, :Object, '15.2.22.2'],
+ [:StandardError, :Exception, '15.2.23.2'],
+ [:ArgumentError, :StandardError, '15.2.24.2'],
+ # [:LocalJumpError, :StandardError, '15.2.25.2'],
+ [:LocalJumpError, :ScriptError, '15.2.25.2'], # mruby specific
+ [:RangeError, :StandardError, '12.2.26.2'],
+ [:RegexpError, :StandardError, '12.2.27.2'],
+ [:RuntimeError, :StandardError, '12.2.28.2'],
+ [:TypeError, :StandardError, '12.2.29.2'],
+# [:ZeroDivisionError, :StandardError, '12.2.30.2'], # No ZeroDivisionError in mruby
+ [:NameError, :StandardError, '15.2.31.2'],
+ [:NoMethodError, :NameError, '15.2.32.2'],
+ [:IndexError, :StandardError, '15.2.33.2'],
+# [:IOError, :StandardError, '12.2.34.2'],
+# [:EOFError, :IOError, '12.2.35.2'],
+# [:SystemCallError, :StandardError, '15.2.36.2'],
+ [:ScriptError, :Exception, '12.2.37.2'],
+ [:SyntaxError, :ScriptError, '12.2.38.2'],
+# [:LoadError, :ScriptError, '12.2.39,2'],
+].each do |cls, super_cls, iso|
+ assert "Direct superclass of #{cls}", iso do
+ skip "#{cls} isn't defined" unless Object.const_defined? cls
+ assert_equal Object.const_get(super_cls), Object.const_get(cls).superclass
+ end
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/symbol.rb b/web/server/h2o/libh2o/deps/mruby/test/t/symbol.rb
new file mode 100644
index 00000000..9059f45c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/symbol.rb
@@ -0,0 +1,30 @@
+##
+# Symbol ISO Test
+
+assert('Symbol') do
+ assert_equal :"a", :a
+ assert_equal :"a#{1}", :a1
+ assert_equal :'a', :a
+ assert_equal :'a#{1}', :"a\#{1}"
+end
+
+assert('Symbol', '15.2.11') do
+ assert_equal Class, Symbol.class
+end
+
+assert('Symbol#===', '15.2.11.3.1') do
+ assert_true :abc == :abc
+ assert_false :abc == :cba
+end
+
+assert('Symbol#id2name', '15.2.11.3.2') do
+ assert_equal 'abc', :abc.id2name
+end
+
+assert('Symbol#to_s', '15.2.11.3.3') do
+ assert_equal 'abc', :abc.to_s
+end
+
+assert('Symbol#to_sym', '15.2.11.3.4') do
+ assert_equal :abc, :abc.to_sym
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/syntax.rb b/web/server/h2o/libh2o/deps/mruby/test/t/syntax.rb
new file mode 100644
index 00000000..29939455
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/syntax.rb
@@ -0,0 +1,468 @@
+assert('__FILE__') do
+ file = __FILE__[-9, 9]
+ assert_equal 'syntax.rb', file
+end
+
+assert('__LINE__') do
+ assert_equal 7, __LINE__
+end
+
+assert('super', '11.3.4') do
+ assert_raise NoMethodError do
+ super
+ end
+
+ class SuperFoo
+ def foo
+ true
+ end
+ def bar(*a)
+ a
+ end
+ end
+ class SuperBar < SuperFoo
+ def foo
+ super
+ end
+ def bar(*a)
+ super(*a)
+ end
+ end
+ bar = SuperBar.new
+
+ assert_true bar.foo
+ assert_equal [1,2,3], bar.bar(1,2,3)
+end
+
+assert('yield', '11.3.5') do
+ assert_raise LocalJumpError do
+ yield
+ end
+ assert_raise LocalJumpError do
+ o = Object.new
+ def o.foo
+ yield
+ end
+ o.foo
+ end
+end
+
+assert('redo in a for loop (#3275)') do
+ sum = 0
+ for i in 1..10
+ sum += i
+ i -= 1
+ if i > 0
+ redo
+ end
+ end
+
+ assert_equal 220, sum
+end
+
+assert('Abbreviated variable assignment', '11.4.2.3.2') do
+ a ||= 1
+ b &&= 1
+ c = 1
+ c += 2
+
+ assert_equal 1, a
+ assert_nil b
+ assert_equal 3, c
+end
+
+assert('case expression', '11.5.2.2.4') do
+ # case-expression-with-expression, one when-clause
+ x = 0
+ case "a"
+ when "a"
+ x = 1
+ end
+ assert_equal 1, x
+
+ # case-expression-with-expression, multiple when-clauses
+ x = 0
+ case "b"
+ when "a"
+ x = 1
+ when "b"
+ x = 2
+ end
+ assert_equal 2, x
+
+ # no matching when-clause
+ x = 0
+ case "c"
+ when "a"
+ x = 1
+ when "b"
+ x = 2
+ end
+ assert_equal 0, x
+
+ # case-expression-with-expression, one when-clause and one else-clause
+ a = 0
+ case "c"
+ when "a"
+ x = 1
+ else
+ x = 3
+ end
+ assert_equal 3, x
+
+ # case-expression-without-expression, one when-clause
+ x = 0
+ case
+ when true
+ x = 1
+ end
+ assert_equal 1, x
+
+ # case-expression-without-expression, multiple when-clauses
+ x = 0
+ case
+ when 0 == 1
+ x = 1
+ when 1 == 1
+ x = 2
+ end
+ assert_equal 2, x
+
+ # case-expression-without-expression, one when-clause and one else-clause
+ x = 0
+ case
+ when 0 == 1
+ x = 1
+ else
+ x = 3
+ end
+ assert_equal 3, x
+
+ # multiple when-arguments
+ x = 0
+ case 4
+ when 1, 3, 5
+ x = 1
+ when 2, 4, 6
+ x = 2
+ end
+ assert_equal 2, x
+
+ # when-argument with splatting argument
+ x = :integer
+ odds = [ 1, 3, 5, 7, 9 ]
+ evens = [ 2, 4, 6, 8 ]
+ case 5
+ when *odds
+ x = :odd
+ when *evens
+ x = :even
+ end
+ assert_equal :odd, x
+
+ true
+end
+
+assert('Nested const reference') do
+ module Syntax4Const
+ CONST1 = "hello world"
+ class Const2
+ def const1
+ CONST1
+ end
+ end
+ end
+ assert_equal "hello world", Syntax4Const::CONST1
+ assert_equal "hello world", Syntax4Const::Const2.new.const1
+end
+
+assert('Abbreviated variable assignment as returns') do
+ module Syntax4AbbrVarAsgnAsReturns
+ class A
+ def b
+ @c ||= 1
+ end
+ end
+ end
+ assert_equal 1, Syntax4AbbrVarAsgnAsReturns::A.new.b
+end
+
+assert('Splat and multiple assignment') do
+ *a = *[1,2,3]
+ b, *c = *[7,8,9]
+
+ assert_equal [1,2,3], a
+ assert_equal 7, b
+ assert_equal [8,9], c
+
+ (a, b), c = [1,2],3
+ assert_equal [1,2,3], [a,b,c]
+ (a, b), c = 1,2,3
+ assert_equal [1,nil,2], [a,b,c]
+end
+
+assert('Splat and multiple assignment from variable') do
+ a = [1, 2, 3]
+ b, *c = a
+
+ assert_equal 1, b
+ assert_equal [2, 3], c
+end
+
+assert('Splat and multiple assignment from variables') do
+ a = [1, 2, 3]
+ b = [4, 5, 6, 7]
+ c, d, *e, f, g = *a, *b
+
+ assert_equal 1, c
+ assert_equal 2, d
+ assert_equal [3, 4, 5], e
+ assert_equal 6, f
+ assert_equal 7, g
+end
+
+assert('Splat and multiple assignment in for') do
+ a = [1, 2, 3, 4, 5, 6, 7]
+ for b, c, *d, e, f in [a] do
+ end
+
+ assert_equal 1, b
+ assert_equal 2, c
+ assert_equal [3, 4, 5], d
+ assert_equal 6, e
+ assert_equal 7, f
+end
+
+assert('Splat without assignment') do
+ * = [0]
+ a, * = [1, 2]
+ assert_equal 1, a
+end
+
+assert('multiple assignment (rest)') do
+ *a = 0
+ assert_equal [0], a
+end
+
+assert('multiple assignment (rest+post)') do
+ *a, b = 0, 1, 2
+ *c, d = 3
+
+ assert_equal [0, 1], a
+ assert_equal 2, b
+ assert_equal [], c
+ assert_equal 3, d
+end
+
+assert('multiple assignment (nosplat array rhs)') do
+ a, *b = []
+ *c, d = [0]
+ e, *f, g = [1, 2]
+
+ assert_nil a
+ assert_equal [], b
+ assert_equal [], c
+ assert_equal 0, d
+ assert_equal 1, e
+ assert_equal [], f
+ assert_equal 2, g
+end
+
+assert('multiple assignment (empty array rhs #3236, #3239)') do
+ a,b,*c = []; assert_equal [nil, nil, []], [a, b, c]
+ a,b,*c = [1]; assert_equal [1, nil, []], [a, b, c]
+ a,b,*c = [nil]; assert_equal [nil,nil, []], [a, b, c]
+ a,b,*c = [[]]; assert_equal [[], nil, []], [a, b, c]
+end
+
+assert('Return values of case statements') do
+ a = [] << case 1
+ when 3 then 2
+ when 2 then 2
+ when 1 then 2
+ end
+
+ b = [] << case 1
+ when 2 then 2
+ else
+ end
+
+ def fb
+ n = 0
+ Proc.new do
+ n += 1
+ case
+ when n % 15 == 0
+ else n
+ end
+ end
+ end
+
+ assert_equal [2], a
+ assert_equal [nil], b
+ assert_equal 1, fb.call
+end
+
+assert('Return values of if and case statements') do
+ true_clause_value =
+ if true
+ 1
+ else
+ case 2
+ when 3
+ end
+ 4
+ end
+
+ assert_equal 1, true_clause_value
+end
+
+assert('Return values of no expression case statement') do
+ when_value =
+ case
+ when true
+ 1
+ end
+
+ assert_equal 1, when_value
+end
+
+assert('splat object in assignment') do
+ o = Object.new
+ def o.to_a
+ nil
+ end
+ assert_equal [o], (a = *o)
+
+ def o.to_a
+ 1
+ end
+ assert_raise(TypeError) { a = *o }
+
+ def o.to_a
+ [2]
+ end
+ assert_equal [2], (a = *o)
+end
+
+assert('splat object in case statement') do
+ o = Object.new
+ def o.to_a
+ nil
+ end
+ a = case o
+ when *o
+ 1
+ end
+ assert_equal 1, a
+end
+
+assert('splat in case statement') do
+ values = [3,5,1,7,8]
+ testa = [1,2,7]
+ testb = [5,6]
+ resulta = []
+ resultb = []
+ resultc = []
+ values.each do |value|
+ case value
+ when *testa
+ resulta << value
+ when *testb
+ resultb << value
+ else
+ resultc << value
+ end
+ end
+
+ assert_equal [1,7], resulta
+ assert_equal [5], resultb
+ assert_equal [3,8], resultc
+end
+
+assert('External command execution.') do
+ module Kernel
+ sym = '`'.to_sym
+ alias_method :old_cmd, sym
+
+ results = []
+ define_method(sym) do |str|
+ results.push str
+ str
+ end
+
+ `test` # NOVAL NODE_XSTR
+ `test dynamic #{sym}` # NOVAL NODE_DXSTR
+ assert_equal ['test', 'test dynamic `'], results
+
+ t = `test` # VAL NODE_XSTR
+ assert_equal 'test', t
+ assert_equal ['test', 'test dynamic `', 'test'], results
+
+ t = `test dynamic #{sym}` # VAL NODE_DXSTR
+ assert_equal 'test dynamic `', t
+ assert_equal ['test', 'test dynamic `', 'test', 'test dynamic `'], results
+
+ alias_method sym, :old_cmd
+ end
+ true
+end
+
+assert('parenthesed do-block in cmdarg') do
+ class ParenDoBlockCmdArg
+ def test(block)
+ block.call
+ end
+ end
+ x = ParenDoBlockCmdArg.new
+ result = x.test (Proc.new do :ok; end)
+ assert_equal :ok, result
+end
+
+assert('method definition in cmdarg') do
+ if false
+ bar def foo; self.each do end end
+ end
+ true
+end
+
+assert('optional argument in the rhs default expressions') do
+ class OptArgInRHS
+ def foo
+ "method called"
+ end
+ def t(foo = foo)
+ foo
+ end
+ def t2(foo = foo())
+ foo
+ end
+ end
+ o = OptArgInRHS.new
+ assert_nil(o.t)
+ assert_equal("method called", o.t2)
+end
+
+assert('optional block argument in the rhs default expressions') do
+ assert_nil(Proc.new {|foo = foo| foo}.call)
+end
+
+assert('multiline comments work correctly') do
+=begin
+this is a comment with nothing after begin and end
+=end
+=begin this is a comment
+this is a comment with extra after =begin
+=end
+=begin
+this is a comment that has =end with spaces after it
+=end
+=begin this is a comment
+this is a comment that has extra after =begin and =end with spaces after it
+=end
+ line = __LINE__
+=begin this is a comment
+this is a comment that has extra after =begin and =end with tabs after it
+=end xxxxxxxxxxxxxxxxxxxxxxxxxx
+ assert_equal(line + 4, __LINE__)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/true.rb b/web/server/h2o/libh2o/deps/mruby/test/t/true.rb
new file mode 100644
index 00000000..74f605ef
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/true.rb
@@ -0,0 +1,31 @@
+##
+# TrueClass ISO Test
+
+assert('TrueClass', '15.2.5') do
+ assert_equal Class, TrueClass.class
+end
+
+assert('TrueClass true', '15.2.5.1') do
+ assert_true true
+ assert_equal TrueClass, true.class
+ assert_false TrueClass.method_defined? :new
+end
+
+assert('TrueClass#&', '15.2.5.3.1') do
+ assert_true true.&(true)
+ assert_false true.&(false)
+end
+
+assert('TrueClass#^', '15.2.5.3.2') do
+ assert_false true.^(true)
+ assert_true true.^(false)
+end
+
+assert('TrueClass#to_s', '15.2.5.3.3') do
+ assert_equal 'true', true.to_s
+end
+
+assert('TrueClass#|', '15.2.5.3.4') do
+ assert_true true.|(true)
+ assert_true true.|(false)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/typeerror.rb b/web/server/h2o/libh2o/deps/mruby/test/t/typeerror.rb
new file mode 100644
index 00000000..32536a74
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/typeerror.rb
@@ -0,0 +1,6 @@
+##
+# TypeError ISO Test
+
+assert('TypeError', '15.2.29') do
+ assert_equal Class, TypeError.class
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/test/t/unicode.rb b/web/server/h2o/libh2o/deps/mruby/test/t/unicode.rb
new file mode 100644
index 00000000..8622ae08
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/test/t/unicode.rb
@@ -0,0 +1,39 @@
+# Test of the \u notation
+
+assert('bare \u notation test') do
+ # Mininum and maximum one byte characters
+ assert_equal("\x00", "\u0000")
+ assert_equal("\x7F", "\u007F")
+
+ # Mininum and maximum two byte characters
+ assert_equal("\xC2\x80", "\u0080")
+ assert_equal("\xDF\xBF", "\u07FF")
+
+ # Mininum and maximum three byte characters
+ assert_equal("\xE0\xA0\x80", "\u0800")
+ assert_equal("\xEF\xBF\xBF", "\uFFFF")
+
+ # Four byte characters require the \U notation
+end
+
+assert('braced \u notation test') do
+ # Mininum and maximum one byte characters
+ assert_equal("\x00", "\u{0000}")
+ assert_equal("\x7F", "\u{007F}")
+
+ # Mininum and maximum two byte characters
+ assert_equal("\xC2\x80", "\u{0080}")
+ assert_equal("\xDF\xBF", "\u{07FF}")
+
+ # Mininum and maximum three byte characters
+ assert_equal("\xE0\xA0\x80", "\u{0800}")
+ assert_equal("\xEF\xBF\xBF", "\u{FFFF}")
+
+ # Mininum and maximum four byte characters
+ assert_equal("\xF0\x90\x80\x80", "\u{10000}")
+ assert_equal("\xF4\x8F\xBF\xBF", "\u{10FFFF}")
+end
+
+assert('braced multiple \u notation test') do
+ assert_equal("ABC", "\u{41 42 43}")
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/travis_config.rb b/web/server/h2o/libh2o/deps/mruby/travis_config.rb
new file mode 100644
index 00000000..5904d688
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/travis_config.rb
@@ -0,0 +1,53 @@
+MRuby::Build.new('debug') do |conf|
+ toolchain :gcc
+ enable_debug
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.cc.flags += %w(-Werror=declaration-after-statement)
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA MRB_METHOD_CACHE)
+ end
+
+ build_mrbc_exec
+end
+
+MRuby::Build.new('full-debug') do |conf|
+ toolchain :gcc
+ enable_debug
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK)
+
+ conf.enable_test
+end
+
+MRuby::Build.new do |conf|
+ toolchain :gcc
+
+ # include all core GEMs
+ conf.gembox 'full-core'
+ conf.cc.flags += %w(-Werror=declaration-after-statement)
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_GC_FIXED_ARENA)
+ end
+ conf.enable_bintest
+ conf.enable_test
+end
+
+MRuby::Build.new('cxx_abi') do |conf|
+ toolchain :gcc
+
+ conf.gembox 'full-core'
+ conf.cc.flags += %w(-Werror=declaration-after-statement)
+ conf.compilers.each do |c|
+ c.defines += %w(MRB_GC_FIXED_ARENA)
+ end
+ conf.enable_bintest
+ conf.enable_test
+
+ enable_cxx_abi
+
+ build_mrbc_exec
+end