mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Compare commits
337 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9d113f764 | |||
| 5e01674b72 | |||
| b652a4ff14 | |||
| 7dc0fe66c7 | |||
| 1cdcd00cc0 | |||
| 9f4b5227fe | |||
| d464fe5003 | |||
| 6b839b2319 | |||
| 45bd372755 | |||
| f5ee7df7f3 | |||
| e77e6e9d12 | |||
| a2b87c033a | |||
| b3c5d94bd1 | |||
| d029549c2f | |||
| 6e13467ce8 | |||
| 508ac2030e | |||
| 4b81bce48d | |||
| 3486675e00 | |||
| 3d46f1b620 | |||
| 63c7ff341a | |||
| a8ab74a6dc | |||
| 7ab5353f80 | |||
| d7df30bdd8 | |||
| d317ee144b | |||
| 3cef380b20 | |||
| 707933aa8e | |||
| 068b16a352 | |||
| c7ab4cf616 | |||
| e3875ae8c5 | |||
| 226fcb4f2a | |||
| d22b72a7cc | |||
| 15dec83832 | |||
| 5acd802d2b | |||
| 9b15860ddb | |||
| 0dacc9a62a | |||
| 67606170e3 | |||
| cc1db2d117 | |||
| b3d4ab0cd8 | |||
| 5bf5a2cc6e | |||
| e15e6e761e | |||
| 1cc270f0cc | |||
| 55f3202650 | |||
| a8d508c567 | |||
| 7c85a1ff07 | |||
| dd6f5e4607 | |||
| ab1465d9d5 | |||
| 66c44b8568 | |||
| 6ee24fe1bc | |||
| 4398bae56a | |||
| 20f9128f73 | |||
| 6901752723 | |||
| 886355007c | |||
| f45549edbf | |||
| 5a4b9fd877 | |||
| f319c5fb26 | |||
| 4687f8790c | |||
| 30eaee30fa | |||
| 8df49ea955 | |||
| 7905431fe9 | |||
| 96d727177e | |||
| be86bd3c49 | |||
| 260dc6d741 | |||
| 3ba32e80af | |||
| ac5ec1a153 | |||
| 34be5acc99 | |||
| 4713502083 | |||
| 2f6afb52a9 | |||
| 20597b6d36 | |||
| 0301d8a89b | |||
| 736ea1f5c7 | |||
| ffb55e51f1 | |||
| 6d9109bf70 | |||
| 4c6d524c47 | |||
| 3c67d9b1c0 | |||
| 8020374d6b | |||
| db64bd42d3 | |||
| 724c90f369 | |||
| c0a6439a69 | |||
| 10c2b7ee1c | |||
| f34623fb03 | |||
| c8f4d72302 | |||
| 7771c215e4 | |||
| ff5d1914ab | |||
| e7e999414c | |||
| 36efc33650 | |||
| 364c47610f | |||
| 59464f3528 | |||
| 7d9a49efab | |||
| e24b4a1e19 | |||
| f7abda1437 | |||
| ff57c0278f | |||
| 2742ded32f | |||
| 70e5746896 | |||
| fc8fb41451 | |||
| dc86e35cac | |||
| 2124b9b4c9 | |||
| dbba0ca517 | |||
| afad939173 | |||
| 3e4e10ffb6 | |||
| c60bccaa94 | |||
| 59756aef14 | |||
| 874797f36f | |||
| b545f62aeb | |||
| ca71eb7eef | |||
| ccf28775b8 | |||
| 2532e625ed | |||
| 111045ecad | |||
| 282f907f1b | |||
| 541185ef14 | |||
| d82e91898d | |||
| 00f5c92149 | |||
| 9174b18f34 | |||
| b9c78c3fcc | |||
| 021f228f9d | |||
| 40b8490fa4 | |||
| 7247e4cf1b | |||
| b49bc17f48 | |||
| 7ed26ead9b | |||
| 20d3882469 | |||
| fd1cff7735 | |||
| 943fbb2bea | |||
| 28c8e29c4d | |||
| b493229a23 | |||
| 83e502b847 | |||
| 93d0e5d9fb | |||
| 5e519cdbb5 | |||
| b96fa664b0 | |||
| 4327f36940 | |||
| b97ebf2aeb | |||
| e9de5a7a5c | |||
| bb98fd78c3 | |||
| d2f34a8455 | |||
| 26e6e75ba6 | |||
| 03244b52a0 | |||
| d15e56dab0 | |||
| ff16331754 | |||
| d8a5163b24 | |||
| ed8491cde6 | |||
| 7e6355975e | |||
| 716102fff3 | |||
| ef6805f599 | |||
| d6b898685f | |||
| 0b2d54f4f1 | |||
| d4cbe6271c | |||
| f92867a59e | |||
| d062528653 | |||
| b63f1912df | |||
| 18248cfd00 | |||
| 0f89a91607 | |||
| bb0aec1d94 | |||
| 10e9f193ca | |||
| 38fdca82c6 | |||
| 49301ed785 | |||
| 212d12f269 | |||
| a562a9aa93 | |||
| f08d9b288d | |||
| dc15c2838f | |||
| 0bd3a67dea | |||
| 572958ece3 | |||
| fa90bcb9ab | |||
| 5974d53ab0 | |||
| 66349bcef1 | |||
| 9f1167f7c9 | |||
| 089bb6acad | |||
| 06e09fc7a9 | |||
| 2fe78a0c7c | |||
| de17f63b45 | |||
| fee3c1c242 | |||
| 74f564b0bb | |||
| acef52c35e | |||
| 5cc595cb2a | |||
| ef8621cb61 | |||
| e8299a89da | |||
| 19fa77ddbb | |||
| adf358363c | |||
| 64e9f278b3 | |||
| 9cde967321 | |||
| 87809742f5 | |||
| fcde80a4d0 | |||
| 868ba8464e | |||
| 429f6defdd | |||
| 7f0e1fc90b | |||
| 6df6bd4ac7 | |||
| f0b8c9ec06 | |||
| 815e0c400a | |||
| 4c1667a5f6 | |||
| f507ff4842 | |||
| 29ecc3840a | |||
| 8bc9a79e65 | |||
| 6a22fa7f47 | |||
| 854c61c3ab | |||
| 85b4ed623e | |||
| fc5a9c2be2 | |||
| cc6d17423b | |||
| 4bdb1eb5aa | |||
| d2f2f9db51 | |||
| cc52fa66e8 | |||
| 184ad732df | |||
| 69619aeeb1 | |||
| 6d9ac89f92 | |||
| 5b30f789e5 | |||
| c18a8c53e8 | |||
| ec1ef925a9 | |||
| 6c5ee8f79e | |||
| e18aa4d893 | |||
| 81de1f159c | |||
| 9c4c82ed1c | |||
| 7192429e83 | |||
| 994da0fd73 | |||
| bf431e77b8 | |||
| 543a9f84d1 | |||
| 56de911b7a | |||
| 0893ee492c | |||
| 694089fafe | |||
| fb9e92e828 | |||
| f7a0f11c36 | |||
| 0011652a28 | |||
| 72d57ad094 | |||
| 8267993988 | |||
| ef644120e4 | |||
| cf6ae0de6a | |||
| 2456d3abc0 | |||
| 1ca4fdc4c7 | |||
| d908a73b04 | |||
| 6e5c861fff | |||
| e6033e00fe | |||
| 52318b3359 | |||
| a030446a94 | |||
| bc22991ac3 | |||
| ea1911d23f | |||
| 54f2ed6afd | |||
| 6973539005 | |||
| 3c67872805 | |||
| a53f28275e | |||
| ef95a9fa93 | |||
| 25b5b79cc3 | |||
| 49653b81ea | |||
| 5eb08a0d1a | |||
| df437eebcc | |||
| 75e96c6927 | |||
| 1680f2c95e | |||
| 17ec885270 | |||
| f4b528e07a | |||
| 190649e591 | |||
| ec957ec5ee | |||
| ff15a586a0 | |||
| f9bd414350 | |||
| a89d15cdde | |||
| 1d1c81258e | |||
| ce553fa834 | |||
| b3e6a993a9 | |||
| 375c1ebc41 | |||
| 6cf99d12ac | |||
| 56f9106d94 | |||
| 8bcf44669c | |||
| d81e4d71c1 | |||
| a2df247063 | |||
| 8596edba09 | |||
| 1bb1df19d8 | |||
| 125c660974 | |||
| 351c9c80e7 | |||
| 57a56ddaa2 | |||
| 79e73dd86a | |||
| 3241a7e5a8 | |||
| bd87799673 | |||
| 9de7130a9a | |||
| 74310f41d7 | |||
| a367373fe3 | |||
| 04baaab311 | |||
| c9f156ef0c | |||
| 455930fbc4 | |||
| db43738397 | |||
| 079aff1779 | |||
| 29133b2fe2 | |||
| 37c8cbe76b | |||
| ac917983c5 | |||
| 1259564c01 | |||
| edbc6d8ab5 | |||
| c268e36e44 | |||
| 067c11f65d | |||
| b5946822af | |||
| cc54257de5 | |||
| a72917541f | |||
| e50344b5da | |||
| 1a0c799898 | |||
| ac213907d7 | |||
| 7750c61e29 | |||
| 8ff001ef30 | |||
| 962776fe25 | |||
| 0f64cb421e | |||
| 45aa5081e4 | |||
| c10e191ac7 | |||
| ea2424d36d | |||
| 1cc0180a81 | |||
| b5bb981959 | |||
| ee86721ef9 | |||
| 4841754aba | |||
| 2166cc2e80 | |||
| bf0b591b2f | |||
| 5812d05b71 | |||
| 7a06e49008 | |||
| 8cbee9695b | |||
| 7e03f47370 | |||
| ad7f9b3542 | |||
| e4d078b520 | |||
| 1dc0da8218 | |||
| a9e27933a9 | |||
| fdc0219db5 | |||
| ecdc6c6507 | |||
| f68212cc7a | |||
| e23840a3fc | |||
| 34f68d0104 | |||
| 23cb78a0ff | |||
| 552bd9daff | |||
| 799ad0e1c7 | |||
| 8710a22c31 | |||
| db0a4d9045 | |||
| 9c99451607 | |||
| 4b14c4633a | |||
| 39a0a25f20 | |||
| 85e34f1ca4 | |||
| b4262972dc | |||
| 06bd4ffdaf | |||
| 4eb8fca140 | |||
| fa85f91e0e | |||
| 9540a8309c | |||
| 11184e9186 | |||
| 2f0bf1e110 | |||
| 41c43234a7 | |||
| 1aacde20fa | |||
| 941b99955a | |||
| 0701cc493c | |||
| 7047c52d7b | |||
| fddefeb7ee | |||
| 347729a7c0 | |||
| 7957f75bd8 | |||
| 4877dbf2a9 |
@@ -0,0 +1,24 @@
|
||||
name: CIFuzz
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'mruby'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'mruby'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure()
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
|
||||
+1601
-401
File diff suppressed because it is too large
Load Diff
+1
-6
@@ -9,11 +9,6 @@ matrix:
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gperf
|
||||
|
||||
env:
|
||||
- MRUBY_CONFIG=travis_config.rb
|
||||
script: "./minirake -j4 all test"
|
||||
script: "rake -m && rake test"
|
||||
|
||||
@@ -42,3 +42,4 @@ of this list.
|
||||
Masahiro Wakame
|
||||
YAMAMOTO Masaya
|
||||
KOBAYASHI Shuji
|
||||
RIZAL Reckordp
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ 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```)
|
||||
* Test your changes before creating a pull request (```rake 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
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "mruby"
|
||||
PROJECT_NUMBER = 2.1.0
|
||||
PROJECT_NUMBER = 2.1.1
|
||||
|
||||
PROJECT_BRIEF = "mruby is the lightweight implementation of the Ruby language"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2019 mruby developers
|
||||
Copyright (c) 2020 mruby developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# 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
|
||||
RAKE = rake
|
||||
|
||||
all :
|
||||
$(RAKE)
|
||||
|
||||
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
|
||||
|
||||
## How to get mruby
|
||||
|
||||
The stable version 2.1.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.0.zip](https://github.com/mruby/mruby/archive/2.1.0.zip)
|
||||
The stable version 2.1.1 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.1.zip](https://github.com/mruby/mruby/archive/2.1.1.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)
|
||||
|
||||
@@ -30,11 +30,11 @@ You can also install and compile mruby using [ruby-install](https://github.com/p
|
||||
|
||||
## mruby home-page
|
||||
|
||||
The URL of the mruby home-page is: [http://www.mruby.org](http://www.mruby.org).
|
||||
The URL of the mruby home-page is: https://mruby.org.
|
||||
|
||||
## Mailing list
|
||||
|
||||
We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby).
|
||||
We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby/issues).
|
||||
|
||||
## How to compile and install (mruby and gems)
|
||||
|
||||
@@ -44,11 +44,7 @@ See the [compile.md](https://github.com/mruby/mruby/blob/master/doc/guides/compi
|
||||
|
||||
To run the tests, execute the following from the project's root directory.
|
||||
|
||||
$ make test
|
||||
|
||||
Or
|
||||
|
||||
$ ruby ./minirake test
|
||||
$ rake test
|
||||
|
||||
## Building documentation
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ 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')
|
||||
|
||||
Rake.verbose(false) if Rake.verbose == Rake::DSL::DEFAULT
|
||||
|
||||
$LOAD_PATH << File.join(MRUBY_ROOT, "lib")
|
||||
|
||||
# load build systems
|
||||
@@ -33,10 +35,9 @@ load "#{MRUBY_ROOT}/tasks/gitlab.rake"
|
||||
load "#{MRUBY_ROOT}/tasks/doc.rake"
|
||||
|
||||
def install_D(src, dst)
|
||||
opts = { :verbose => $verbose }
|
||||
FileUtils.rm_f dst, opts
|
||||
FileUtils.mkdir_p File.dirname(dst), opts
|
||||
FileUtils.cp src, dst, opts
|
||||
rm_f dst
|
||||
mkdir_p File.dirname(dst)
|
||||
cp src, dst
|
||||
end
|
||||
|
||||
##############################
|
||||
@@ -62,7 +63,7 @@ MRuby.each_target do |target|
|
||||
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}/
|
||||
if current_build_dir !~ /^#{Regexp.escape(build_dir)}/
|
||||
current_build_dir = "#{build_dir}/mrbgems/#{gem.name}"
|
||||
end
|
||||
|
||||
@@ -144,16 +145,16 @@ 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 }
|
||||
rm_rf t.build_dir
|
||||
end
|
||||
FileUtils.rm_f depfiles, { :verbose => $verbose }
|
||||
rm_f depfiles
|
||||
puts "Cleaned up target build folder"
|
||||
end
|
||||
|
||||
desc "clean everything!"
|
||||
task :deep_clean => ["clean", "clean_doc"] do
|
||||
MRuby.each_target do |t|
|
||||
FileUtils.rm_rf t.gem_clone_dir, { :verbose => $verbose }
|
||||
rm_rf t.gem_clone_dir
|
||||
end
|
||||
puts "Cleaned up mrbgems build folder"
|
||||
end
|
||||
|
||||
@@ -14,10 +14,18 @@ environment:
|
||||
# Visual Studio 2017 64bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
|
||||
# Visual Studio 2017 32bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
|
||||
machine: x86
|
||||
|
||||
# Visual Studio 2015 64bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
|
||||
machine: amd64
|
||||
|
||||
# Visual Studio 2015 32bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
|
||||
machine: x86
|
||||
|
||||
# Visual Studio 2013 64bit
|
||||
- visualcpp: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat
|
||||
machine: amd64
|
||||
|
||||
+1
-14
@@ -1,23 +1,10 @@
|
||||
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 MRB_METHOD_CACHE)
|
||||
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.cc.defines += %w(MRB_GC_STRESS MRB_METHOD_CACHE MRB_ENABLE_DEBUG_HOOK)
|
||||
|
||||
conf.enable_test
|
||||
end
|
||||
|
||||
+6
-6
@@ -30,9 +30,9 @@ MRuby::Build.new do |conf|
|
||||
# cc.flags = [ENV['CFLAGS'] || %w()]
|
||||
# cc.include_paths = ["#{root}/include"]
|
||||
# cc.defines = %w()
|
||||
# cc.option_include_path = '-I%s'
|
||||
# cc.option_include_path = %q[-I"%s"]
|
||||
# cc.option_define = '-D%s'
|
||||
# cc.compile_options = "%{flags} -MMD -o %{outfile} -c %{infile}"
|
||||
# cc.compile_options = %Q[%{flags} -MMD -o "%{outfile}" -c "%{infile}"]
|
||||
# end
|
||||
|
||||
# mrbc settings
|
||||
@@ -50,25 +50,25 @@ MRuby::Build.new do |conf|
|
||||
# linker.library_paths = []
|
||||
# linker.option_library = '-l%s'
|
||||
# linker.option_library_path = '-L%s'
|
||||
# linker.link_options = "%{flags} -o %{outfile} %{objs} %{libs}"
|
||||
# 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}'
|
||||
# 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}'
|
||||
# yacc.compile_options = %q[-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}'
|
||||
# gperf.compile_options = %q[-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" "%{infile}" > "%{outfile}"]
|
||||
# end
|
||||
|
||||
# file extensions
|
||||
|
||||
@@ -32,10 +32,10 @@ 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`.
|
||||
To compile just call `rake` inside of the mruby source root. To
|
||||
generate and execute the test tools call `rake test`. To clean
|
||||
all build files call `rake clean`. To see full command line on
|
||||
build, call `rake -v`.
|
||||
|
||||
## Build Configuration
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
|
||||
|
||||
```bash
|
||||
$ mrdb --version
|
||||
mruby 2.1.0 (2019-10-18)
|
||||
mruby 2.1.1 (2020-06-04)
|
||||
```
|
||||
|
||||
## 2.2 Basic Operation
|
||||
|
||||
@@ -54,17 +54,13 @@ You can use mrbconfs with following ways:
|
||||
* When defined removes floating point numbers from mruby.
|
||||
* It makes mruby easier to handle in "Microcontroller without FPU" and "Kernel Space".
|
||||
|
||||
`MRB_INT16`
|
||||
* When defined `int16_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT32` and `MRB_INT64`.
|
||||
|
||||
`MRB_INT32`
|
||||
* When defined, or both `MRB_INT16` and `MRB_INT64` are not defined on 32-bit CPU mode, `int32_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16` and `MRB_INT64`.
|
||||
* When defined, or `MRB_INT64` are not defined on 32-bit CPU mode, `mrb_int` will be defined as `int32_t`.
|
||||
* Conflicts with `MRB_INT64`.
|
||||
|
||||
`MRB_INT64`
|
||||
* When defined, or both `MRB_INT16` and `MRB_INT32` are not defined on 64-bit CPU mode, `int64_t` will be defined as `mrb_int`.
|
||||
* Conflicts with `MRB_INT16` and `MRB_INT32`.
|
||||
* When defined, or `MRB_INT32` are not defined on 64-bit CPU mode, `mrb_int` will be defined as `int64_t`.
|
||||
* Conflicts with `MRB_INT32`.
|
||||
|
||||
## Garbage collector configuration.
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@ conf.gem mgem: 'mruby-redis', checksum_hash: '3446d19fc4a3f9697b5ddbf2a904f301c4
|
||||
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```.
|
||||
To pull all gems from remote GIT repository on build, call ```rake -p```,
|
||||
or ```rake --pull-gems```.
|
||||
|
||||
NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version.
|
||||
|
||||
@@ -235,7 +235,7 @@ 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.
|
||||
Exported include_paths are automatically appended to GEM local include_paths by rake.
|
||||
You can use `spec.export_include_paths` accessor if you want more complex build.
|
||||
|
||||
|
||||
|
||||
+10
-10
@@ -38,7 +38,7 @@ puts [1,2,3]
|
||||
3
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
```
|
||||
[1, 2, 3]
|
||||
@@ -61,7 +61,7 @@ end
|
||||
|
||||
`ZeroDivisionError` is raised.
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
No exception is raised.
|
||||
|
||||
@@ -89,7 +89,7 @@ p Liste.new "foobar"
|
||||
|
||||
` [] `
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
`ArgumentError` is raised.
|
||||
|
||||
@@ -119,7 +119,7 @@ false
|
||||
true
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
```
|
||||
true
|
||||
@@ -156,7 +156,7 @@ p 'ok'
|
||||
ok
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
```
|
||||
test.rb:8: undefined method 'test_func' (NoMethodError)
|
||||
@@ -178,7 +178,7 @@ defined?(Foo)
|
||||
nil
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
`NameError` is raised.
|
||||
|
||||
@@ -195,7 +195,7 @@ alias $a $__a__
|
||||
|
||||
` nil `
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
Syntax error
|
||||
|
||||
@@ -217,7 +217,7 @@ end
|
||||
`ArgumentError` is raised.
|
||||
The re-defined `+` operator does not accept any arguments.
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
` 'ab' `
|
||||
Behavior of the operator wasn't changed.
|
||||
@@ -233,7 +233,7 @@ $ ruby -e 'puts Proc.new {}.binding'
|
||||
#<Binding:0x00000e9deabb9950>
|
||||
```
|
||||
|
||||
#### mruby [2.1.0 (2019-10-18)]
|
||||
#### mruby [2.1.1 (2020-06-04)]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'puts Proc.new {}.binding'
|
||||
@@ -255,7 +255,7 @@ $ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
[[{"a"=>1}], {:b=>2}]
|
||||
```
|
||||
|
||||
#### mruby [mruby 2.1.0]
|
||||
#### mruby [mruby 2.1.1]
|
||||
|
||||
```
|
||||
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||
|
||||
@@ -42,7 +42,7 @@ MRuby::CrossBuild.new("ArduinoDue") do |conf|
|
||||
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}"
|
||||
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
|
||||
#configuration for low memory environment
|
||||
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
||||
@@ -64,7 +64,7 @@ MRuby::CrossBuild.new("ArduinoDue") do |conf|
|
||||
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{BIN_PATH}/arm-none-eabi-ar"
|
||||
archiver.archive_options = 'rcs %{outfile} %{objs}'
|
||||
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
|
||||
end
|
||||
|
||||
#no executables
|
||||
|
||||
@@ -32,7 +32,7 @@ MRuby::CrossBuild.new('core2-32-poky-linux') do |conf|
|
||||
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.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
cc.defines = %w(ENABLE_READLINE)
|
||||
end
|
||||
|
||||
@@ -47,7 +47,7 @@ MRuby::CrossBuild.new('core2-32-poky-linux') do |conf|
|
||||
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{POKY_EDISON_BIN_PATH}/i586-poky-linux-ar"
|
||||
archiver.archive_options = 'rcs %{outfile} %{objs}'
|
||||
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
|
||||
end
|
||||
|
||||
conf.linker do |linker|
|
||||
|
||||
@@ -39,7 +39,7 @@ MRuby::CrossBuild.new("Galileo") do |conf|
|
||||
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}"
|
||||
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
end
|
||||
|
||||
conf.cxx do |cxx|
|
||||
@@ -54,7 +54,7 @@ MRuby::CrossBuild.new("Galileo") do |conf|
|
||||
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{GALILEO_BIN_PATH}/i586-poky-linux-uclibc-ar"
|
||||
archiver.archive_options = 'rcs %{outfile} %{objs}'
|
||||
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
|
||||
end
|
||||
|
||||
conf.linker do |linker|
|
||||
|
||||
@@ -27,7 +27,7 @@ MRuby::CrossBuild.new("RX630") do |conf|
|
||||
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}"
|
||||
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
|
||||
#configuration for low memory environment
|
||||
cc.defines << %w(MRB_USE_FLOAT)
|
||||
@@ -53,7 +53,7 @@ MRuby::CrossBuild.new("RX630") do |conf|
|
||||
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{BIN_PATH}/rx-elf-ar"
|
||||
archiver.archive_options = 'rcs %{outfile} %{objs}'
|
||||
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
|
||||
end
|
||||
|
||||
#no executables
|
||||
|
||||
@@ -39,7 +39,7 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
|
||||
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}"
|
||||
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
|
||||
#configuration for low memory environment
|
||||
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
||||
@@ -60,7 +60,7 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
|
||||
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{PIC32_PATH}/compiler/pic32-tools/bin/pic32-ar"
|
||||
archiver.archive_options = 'rcs %{outfile} %{objs}'
|
||||
archiver.archive_options = 'rcs "%{outfile}" %{objs}'
|
||||
end
|
||||
|
||||
#no executables
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
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 the Sega Dreamcast
|
||||
# This configuration requires KallistiOS (KOS)
|
||||
# https://dreamcast.wiki
|
||||
#
|
||||
# Tested on GNU/Linux, MinGW-w64/MSYS2, Cygwin, macOS and MinGW/MSYS (see below)
|
||||
#
|
||||
MRuby::CrossBuild.new("dreamcast") do |conf|
|
||||
toolchain :gcc
|
||||
|
||||
# Support for DreamSDK (based on MinGW/MSYS)
|
||||
# To compile mruby with DreamSDK, RubyInstaller for Windows should be installed
|
||||
DREAMSDK_HOME = ENV["DREAMSDK_HOME"]
|
||||
MSYS_ROOT = !(DREAMSDK_HOME.nil? || DREAMSDK_HOME.empty?) ? "#{DREAMSDK_HOME}/msys/1.0" : ""
|
||||
|
||||
# Setting paths
|
||||
DREAMCAST_PATH = "#{MSYS_ROOT}/opt/toolchains/dc"
|
||||
KOS_PATH = "#{DREAMCAST_PATH}/kos"
|
||||
BIN_PATH = "#{DREAMCAST_PATH}/sh-elf/bin"
|
||||
|
||||
# C compiler
|
||||
# Flags were extracted from KallistiOS environment files
|
||||
conf.cc do |cc|
|
||||
cc.command = "#{BIN_PATH}/sh-elf-gcc"
|
||||
cc.include_paths << ["#{KOS_PATH}/include", "#{KOS_PATH}/kernel/arch/dreamcast/include", "#{KOS_PATH}/addons/include", "#{KOS_PATH}/../kos-ports/include"]
|
||||
cc.flags << ["-O2", "-fomit-frame-pointer", "-ml", "-m4-single-only", "-ffunction-sections", "-fdata-sections", "-Wall", "-g", "-fno-builtin", "-ml", "-m4-single-only", "-Wl,-Ttext=0x8c010000", "-Wl,--gc-sections", "-T#{KOS_PATH}/utils/ldscripts/shlelf.xc", "-nodefaultlibs"]
|
||||
cc.compile_options = %Q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
cc.defines << %w(_arch_dreamcast)
|
||||
cc.defines << %w(_arch_sub_pristine)
|
||||
end
|
||||
|
||||
# C++ compiler
|
||||
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
|
||||
|
||||
# Linker
|
||||
# There is an issue when making the mruby library with KallistiOS:
|
||||
# 'newlib_kill.o' and 'newlib_getpid.o' aren't found so they are explicitly
|
||||
# specified here at least for now.
|
||||
conf.linker do |linker|
|
||||
linker.command="#{BIN_PATH}/sh-elf-gcc"
|
||||
linker.flags << ["#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_kill.o", "#{MSYS_ROOT}/opt/toolchains/dc/kos/kernel/build/newlib_getpid.o", "-Wl,--start-group -lkallisti -lc -lgcc -Wl,--end-group"]
|
||||
linker.library_paths << ["#{KOS_PATH}/lib/dreamcast", "#{KOS_PATH}/addons/lib/dreamcast", "#{KOS_PATH}/../kos-ports/lib"]
|
||||
end
|
||||
|
||||
# Archiver
|
||||
conf.archiver do |archiver|
|
||||
archiver.command = "#{BIN_PATH}/sh-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
|
||||
# removing mruby-io
|
||||
conf.gem :core => "mruby-metaprog"
|
||||
conf.gem :core => "mruby-pack"
|
||||
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-compar-ext"
|
||||
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-enumerator"
|
||||
conf.gem :core => "mruby-enum-lazy"
|
||||
conf.gem :core => "mruby-toplevel-ext"
|
||||
conf.gem :core => "mruby-kernel-ext"
|
||||
conf.gem :core => "mruby-class-ext"
|
||||
conf.gem :core => "mruby-compiler"
|
||||
end
|
||||
+9
-10
@@ -38,21 +38,23 @@
|
||||
|
||||
/* add -DMRB_METHOD_T_STRUCT on machines that use higher bits of pointers */
|
||||
/* no MRB_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */
|
||||
//#define MRB_METHOD_T_STRUCT
|
||||
#ifndef MRB_METHOD_T_STRUCT
|
||||
// can't use highest 2 bits of function pointers on 32bit Windows.
|
||||
# if defined(_WIN32) && !defined(_WIN64)
|
||||
# define MRB_METHOD_T_STRUCT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT32 and MRB_INT64 */
|
||||
//#define MRB_INT16
|
||||
|
||||
/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT16 and MRB_INT64;
|
||||
/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT64;
|
||||
Default for 32-bit CPU mode. */
|
||||
//#define MRB_INT32
|
||||
|
||||
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 and MRB_INT32;
|
||||
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT32;
|
||||
Default for 64-bit CPU mode. */
|
||||
//#define MRB_INT64
|
||||
|
||||
/* if no specific integer type is chosen */
|
||||
#if !defined(MRB_INT16) && !defined(MRB_INT32) && !defined(MRB_INT64)
|
||||
#if !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
|
||||
@@ -62,9 +64,6 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MRB_COMPLEX_NUMBERS
|
||||
#define MRB_RATIONAL_NUMBERS
|
||||
|
||||
/* define on big endian machines; used by MRB_NAN_BOXING, etc. */
|
||||
#ifndef MRB_ENDIAN_BIG
|
||||
# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
|
||||
|
||||
+7
-6
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** mruby - An embeddable Ruby implementation
|
||||
**
|
||||
** Copyright (c) mruby developers 2010-2019
|
||||
** Copyright (c) mruby developers 2010-2020
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
@@ -70,6 +70,11 @@
|
||||
|
||||
#include "mrbconf.h"
|
||||
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/version.h>
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
#ifndef FLT_EPSILON
|
||||
#define FLT_EPSILON (1.19209290e-07f)
|
||||
@@ -88,11 +93,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <mruby/common.h>
|
||||
#include <mruby/value.h>
|
||||
#include <mruby/gc.h>
|
||||
#include <mruby/version.h>
|
||||
|
||||
/**
|
||||
* MRuby C API entry point
|
||||
*/
|
||||
@@ -1232,6 +1232,7 @@ MRB_API mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char
|
||||
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 mrb_noreturn void mrb_frozen_error(mrb_state *mrb, void *frozen_obj);
|
||||
MRB_API mrb_noreturn void mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max);
|
||||
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);
|
||||
|
||||
@@ -17,7 +17,7 @@ MRB_BEGIN_DECL
|
||||
|
||||
typedef struct mrb_shared_array {
|
||||
int refcnt;
|
||||
mrb_int len;
|
||||
mrb_ssize len;
|
||||
mrb_value *ptr;
|
||||
} mrb_shared_array;
|
||||
|
||||
@@ -26,9 +26,9 @@ struct RArray {
|
||||
MRB_OBJECT_HEADER;
|
||||
union {
|
||||
struct {
|
||||
mrb_int len;
|
||||
mrb_ssize len;
|
||||
union {
|
||||
mrb_int capa;
|
||||
mrb_ssize capa;
|
||||
mrb_shared_array *shared;
|
||||
} aux;
|
||||
mrb_value *ptr;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#endif
|
||||
|
||||
#define MRB_FIXNUM_SHIFT 0
|
||||
#define MRB_SYMBOL_SHIFT 0
|
||||
|
||||
/* value representation by nan-boxing:
|
||||
* float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define MRUBY_BOXING_NO_H
|
||||
|
||||
#define MRB_FIXNUM_SHIFT 0
|
||||
#define MRB_SYMBOL_SHIFT 0
|
||||
|
||||
union mrb_value_union {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
|
||||
+28
-27
@@ -7,10 +7,6 @@
|
||||
#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
|
||||
@@ -34,41 +30,46 @@ enum mrb_special_consts {
|
||||
MRB_Qundef = 20,
|
||||
};
|
||||
|
||||
#define MRB_FIXNUM_SHIFT 1
|
||||
#define MRB_SYMBOL_SHIFT 2
|
||||
#define MRB_FIXNUM_FLAG (1 << (MRB_FIXNUM_SHIFT - 1))
|
||||
#define MRB_SYMBOL_FLAG (1 << (MRB_SYMBOL_SHIFT - 1))
|
||||
#define MRB_FIXNUM_MASK ((1 << MRB_FIXNUM_SHIFT) - 1)
|
||||
#define MRB_SYMBOL_MASK ((1 << MRB_SYMBOL_SHIFT) - 1)
|
||||
#define MRB_IMMEDIATE_MASK 0x07
|
||||
|
||||
#ifdef MRB_64BIT
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
|
||||
#define MRB_SYMBOL_MAX UINT32_MAX
|
||||
#if defined(MRB_64BIT) && defined(MRB_INT32)
|
||||
#define MRB_FIXNUM_SHIFT 0
|
||||
#else
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT - MRB_SYMBOL_SHIFT)
|
||||
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SYMBOL_SHIFT)
|
||||
#define MRB_FIXNUM_SHIFT BOXWORD_FIXNUM_SHIFT
|
||||
#endif
|
||||
#define MRB_SYMBOL_SHIFT BOXWORD_SYMBOL_SHIFT
|
||||
|
||||
#define BOXWORD_FIXNUM_BIT_POS 1
|
||||
#define BOXWORD_SYMBOL_BIT_POS 2
|
||||
#define BOXWORD_FIXNUM_SHIFT BOXWORD_FIXNUM_BIT_POS
|
||||
#ifdef MRB_64BIT
|
||||
#define BOXWORD_SYMBOL_SHIFT 0
|
||||
#else
|
||||
#define BOXWORD_SYMBOL_SHIFT BOXWORD_SYMBOL_BIT_POS
|
||||
#endif
|
||||
#define BOXWORD_FIXNUM_FLAG (1 << (BOXWORD_FIXNUM_BIT_POS - 1))
|
||||
#define BOXWORD_SYMBOL_FLAG (1 << (BOXWORD_SYMBOL_BIT_POS - 1))
|
||||
#define BOXWORD_FIXNUM_MASK ((1 << BOXWORD_FIXNUM_BIT_POS) - 1)
|
||||
#define BOXWORD_SYMBOL_MASK ((1 << BOXWORD_SYMBOL_BIT_POS) - 1)
|
||||
#define BOXWORD_IMMEDIATE_MASK 0x07
|
||||
|
||||
#define BOXWORD_SHIFT_VALUE(o,n,t) \
|
||||
((((t)(o).w)) >> MRB_##n##_SHIFT)
|
||||
(t)(((long)(o).w) >> BOXWORD_##n##_SHIFT)
|
||||
#define BOXWORD_SET_SHIFT_VALUE(o,n,v) \
|
||||
((o).w = (((unsigned long)(v)) << MRB_##n##_SHIFT) | MRB_##n##_FLAG)
|
||||
((o).w = (((unsigned long)(v)) << BOXWORD_##n##_SHIFT) | BOXWORD_##n##_FLAG)
|
||||
#define BOXWORD_SHIFT_VALUE_P(o,n) \
|
||||
(((o).w & MRB_##n##_MASK) == MRB_##n##_FLAG)
|
||||
(((o).w & BOXWORD_##n##_MASK) == BOXWORD_##n##_FLAG)
|
||||
#define BOXWORD_OBJ_TYPE_P(o,n) \
|
||||
(!mrb_immediate_p(o) && (o).value.bp->tt == MRB_TT_##n)
|
||||
|
||||
/*
|
||||
* mrb_value representation:
|
||||
*
|
||||
* nil : ...0000 0000 (all bits are zero)
|
||||
* false : ...0000 0100
|
||||
* nil : ...0000 0000 (all bits are 0)
|
||||
* false : ...0000 0100 (mrb_fixnum(v) != 0)
|
||||
* true : ...0000 1100
|
||||
* undef : ...0001 0100
|
||||
* fixnum: ...IIII III1
|
||||
* symbol: ...SSSS SS10 (high-order 32-bit are symbol value in 64-bit mode)
|
||||
* object: ...PPPP P000
|
||||
* symbol: ...SSSS SS10 (use only upper 32-bit as symbol value on 64-bit CPU)
|
||||
* object: ...PPPP P000 (any bits are 1)
|
||||
*/
|
||||
typedef union mrb_value {
|
||||
union {
|
||||
@@ -114,10 +115,10 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||
#endif
|
||||
#define mrb_bool(o) (((o).w & ~(unsigned long)MRB_Qfalse) != 0)
|
||||
|
||||
#define mrb_immediate_p(o) ((o).w & MRB_IMMEDIATE_MASK || (o).w == MRB_Qnil)
|
||||
#define mrb_immediate_p(o) ((o).w & BOXWORD_IMMEDIATE_MASK || (o).w == MRB_Qnil)
|
||||
#define mrb_fixnum_p(o) BOXWORD_SHIFT_VALUE_P(o, FIXNUM)
|
||||
#ifdef MRB_64BIT
|
||||
#define mrb_symbol_p(o) ((o).value.sym_flag == MRB_SYMBOL_FLAG)
|
||||
#define mrb_symbol_p(o) ((o).value.sym_flag == BOXWORD_SYMBOL_FLAG)
|
||||
#else
|
||||
#define mrb_symbol_p(o) BOXWORD_SHIFT_VALUE_P(o, SYMBOL)
|
||||
#endif
|
||||
@@ -159,7 +160,7 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||
#define SET_BOOL_VALUE(r,b) ((b) ? SET_TRUE_VALUE(r) : SET_FALSE_VALUE(r))
|
||||
#define SET_INT_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, FIXNUM, n)
|
||||
#ifdef MRB_64BIT
|
||||
#define SET_SYM_VALUE(r,v) ((r).value.sym = v, (r).value.sym_flag = MRB_SYMBOL_FLAG)
|
||||
#define SET_SYM_VALUE(r,v) ((r).value.sym = v, (r).value.sym_flag = BOXWORD_SYMBOL_FLAG)
|
||||
#else
|
||||
#define SET_SYM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, SYMBOL, n)
|
||||
#endif
|
||||
|
||||
@@ -90,10 +90,17 @@ mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
|
||||
void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
|
||||
mrb_bool mrb_const_name_p(mrb_state*, const char*, mrb_int);
|
||||
mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
|
||||
mrb_value mrb_mod_to_s(mrb_state*, mrb_value);
|
||||
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*);
|
||||
|
||||
#ifdef MRB_METHOD_CACHE
|
||||
void mrb_mc_clear_by_class(mrb_state *mrb, struct RClass* c);
|
||||
#else
|
||||
#define mrb_mc_clear_by_class(mrb,c)
|
||||
#endif
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_CLASS_H */
|
||||
|
||||
@@ -74,6 +74,16 @@ MRB_BEGIN_DECL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Declare mingw versions */
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
# include <_mingw.h>
|
||||
# if defined(__MINGW64_VERSION_MAJOR)
|
||||
# define MRB_MINGW64_VERSION (__MINGW64_VERSION_MAJOR * 1000 + __MINGW64_VERSION_MINOR)
|
||||
# elif defined(__MINGW32_MAJOR_VERSION)
|
||||
# define MRB_MINGW32_VERSION (__MINGW32_MAJOR_VERSION * 1000 + __MINGW32_MINOR_VERSION)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
#endif /* MRUBY_COMMON_H */
|
||||
|
||||
@@ -161,6 +161,7 @@ struct mrb_parser_state {
|
||||
uint16_t current_filename_index;
|
||||
|
||||
struct mrb_jmpbuf* jmp;
|
||||
mrb_ast_node *nvars;
|
||||
};
|
||||
|
||||
MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*);
|
||||
|
||||
@@ -52,7 +52,7 @@ mrb_break_value_get(struct RBreak *brk)
|
||||
{
|
||||
mrb_value val;
|
||||
val.value = brk->value;
|
||||
val.tt = brk->flags & RBREAK_VALUE_TT_MASK;
|
||||
val.tt = (enum mrb_vtype)(brk->flags & RBREAK_VALUE_TT_MASK);
|
||||
return val;
|
||||
}
|
||||
static inline void
|
||||
|
||||
@@ -23,9 +23,9 @@ struct RString {
|
||||
MRB_OBJECT_HEADER;
|
||||
union {
|
||||
struct {
|
||||
mrb_int len;
|
||||
mrb_ssize len;
|
||||
union {
|
||||
mrb_int capa;
|
||||
mrb_ssize capa;
|
||||
struct mrb_shared_string *shared;
|
||||
struct RString *fshared;
|
||||
} aux;
|
||||
@@ -54,7 +54,7 @@ struct RStringEmbed {
|
||||
RSTR_SET_EMBED_LEN((s),(n));\
|
||||
}\
|
||||
else {\
|
||||
(s)->as.heap.len = (mrb_int)(n);\
|
||||
(s)->as.heap.len = (mrb_ssize)(n);\
|
||||
}\
|
||||
} while (0)
|
||||
#define RSTR_EMBED_PTR(s) (((struct RStringEmbed*)(s))->ary)
|
||||
@@ -115,8 +115,8 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
|
||||
#define MRB_STR_POOL 16 /* status flags from here */
|
||||
#define MRB_STR_ASCII 32
|
||||
#define MRB_STR_EMBED_LEN_SHIFT 6
|
||||
#define MRB_STR_EMBED_LEN_BITSIZE 5
|
||||
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BITSIZE) - 1) << MRB_STR_EMBED_LEN_SHIFT)
|
||||
#define MRB_STR_EMBED_LEN_BIT 5
|
||||
#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT)
|
||||
#define MRB_STR_TYPE_MASK (MRB_STR_POOL - 1)
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
|
||||
*/
|
||||
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_value mrb_str_pool(mrb_state *mrb, const char *s, mrb_int len, mrb_bool nofree);
|
||||
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
|
||||
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
|
||||
|
||||
@@ -465,7 +465,8 @@ mrb_bool mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp);
|
||||
mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len);
|
||||
|
||||
#ifdef MRB_UTF8_STRING
|
||||
mrb_int mrb_utf8_len(const char *str, mrb_int byte_len);
|
||||
mrb_int mrb_utf8len(const char *str, const char *end);
|
||||
mrb_int mrb_utf8_strlen(const char *str, mrb_int byte_len);
|
||||
#endif
|
||||
|
||||
MRB_END_DECL
|
||||
|
||||
+9
-15
@@ -34,10 +34,6 @@ 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"
|
||||
@@ -63,14 +59,6 @@ struct mrb_state;
|
||||
# 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
|
||||
@@ -169,9 +157,15 @@ typedef void mrb_value;
|
||||
#include "boxing_no.h"
|
||||
#endif
|
||||
|
||||
#if !defined(MRB_SYMBOL_BITSIZE)
|
||||
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
|
||||
#define MRB_SYMBOL_MAX UINT32_MAX
|
||||
#define MRB_SYMBOL_BIT (sizeof(mrb_sym) * CHAR_BIT - MRB_SYMBOL_SHIFT)
|
||||
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SYMBOL_SHIFT)
|
||||
|
||||
#if INTPTR_MAX < MRB_INT_MAX
|
||||
typedef intptr_t mrb_ssize;
|
||||
# define MRB_SSIZE_MAX (INTPTR_MAX>>MRB_FIXNUM_SHIFT)
|
||||
#else
|
||||
typedef mrb_int mrb_ssize;
|
||||
# define MRB_SSIZE_MAX MRB_INT_MAX
|
||||
#endif
|
||||
|
||||
#ifndef mrb_immediate_p
|
||||
|
||||
@@ -47,7 +47,7 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Tiny release version number.
|
||||
*/
|
||||
#define MRUBY_RELEASE_TEENY 0
|
||||
#define MRUBY_RELEASE_TEENY 1
|
||||
|
||||
/*
|
||||
* The mruby version.
|
||||
@@ -62,17 +62,17 @@ MRB_BEGIN_DECL
|
||||
/*
|
||||
* Release year.
|
||||
*/
|
||||
#define MRUBY_RELEASE_YEAR 2019
|
||||
#define MRUBY_RELEASE_YEAR 2020
|
||||
|
||||
/*
|
||||
* Release month.
|
||||
*/
|
||||
#define MRUBY_RELEASE_MONTH 10
|
||||
#define MRUBY_RELEASE_MONTH 6
|
||||
|
||||
/*
|
||||
* Release day.
|
||||
*/
|
||||
#define MRUBY_RELEASE_DAY 18
|
||||
#define MRUBY_RELEASE_DAY 4
|
||||
|
||||
/*
|
||||
* Release date as a string.
|
||||
|
||||
+1
-20
@@ -20,27 +20,8 @@ class String
|
||||
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
|
||||
return if Rake.verbose
|
||||
|
||||
width = 5
|
||||
template = options[:indent] ? "%#{width*options[:indent]}s %s %s" : "%-#{width}s %s %s"
|
||||
|
||||
+3
-11
@@ -173,7 +173,7 @@ module MRuby
|
||||
obj = objfile(cxx_src) if obj.nil?
|
||||
|
||||
file cxx_src => [src, __FILE__] do |t|
|
||||
FileUtils.mkdir_p File.dirname t.name
|
||||
mkdir_p File.dirname t.name
|
||||
IO.write t.name, <<EOS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
@@ -276,14 +276,6 @@ EOS
|
||||
end
|
||||
end
|
||||
|
||||
def cygwin_filename(name)
|
||||
if name.is_a?(Array)
|
||||
name.flatten.map { |n| cygwin_filename(n) }
|
||||
else
|
||||
`cygpath -w "#{filename(name)}"`.strip
|
||||
end
|
||||
end
|
||||
|
||||
def exefile(name)
|
||||
if name.is_a?(Array)
|
||||
name.flatten.map { |n| exefile(n) }
|
||||
@@ -320,7 +312,7 @@ EOS
|
||||
end
|
||||
|
||||
def verbose_flag
|
||||
$verbose ? ' -v' : ''
|
||||
Rake.verbose ? ' -v' : ''
|
||||
end
|
||||
|
||||
def run_test
|
||||
@@ -386,7 +378,7 @@ EOS
|
||||
end
|
||||
|
||||
def run_test
|
||||
@test_runner.runner_options << ' -v' if $verbose
|
||||
@test_runner.runner_options << verbose_flag
|
||||
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
||||
if (@test_runner.command == nil)
|
||||
puts "You should run #{mrbtest} on target device."
|
||||
|
||||
+54
-63
@@ -4,7 +4,7 @@ module MRuby
|
||||
class Command
|
||||
include Rake::DSL
|
||||
extend Forwardable
|
||||
def_delegators :@build, :filename, :objfile, :libfile, :exefile, :cygwin_filename
|
||||
def_delegators :@build, :filename, :objfile, :libfile, :exefile
|
||||
attr_accessor :build, :command
|
||||
|
||||
def initialize(build)
|
||||
@@ -24,6 +24,14 @@ module MRuby
|
||||
target
|
||||
end
|
||||
|
||||
def shellquote(s)
|
||||
if ENV['OS'] == 'Windows_NT'
|
||||
"\"#{s}\""
|
||||
else
|
||||
"#{s}"
|
||||
end
|
||||
end
|
||||
|
||||
NotFoundCommands = {}
|
||||
|
||||
private
|
||||
@@ -50,9 +58,9 @@ module MRuby
|
||||
@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}'
|
||||
@option_include_path = %q[-I"%s"]
|
||||
@option_define = %q[-D"%s"]
|
||||
@compile_options = %q[%{flags} -o "%{outfile}" -c "%{infile}"]
|
||||
@cxx_invalid_flags = []
|
||||
end
|
||||
|
||||
@@ -71,25 +79,16 @@ module MRuby
|
||||
def all_flags(_defines=[], _include_paths=[], _flags=[])
|
||||
define_flags = [defines, _defines].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
|
||||
option_include_path % filename(f)
|
||||
end
|
||||
[flags, define_flags, include_path_flags, _flags].flatten.join(' ')
|
||||
end
|
||||
|
||||
def run(outfile, infile, _defines=[], _include_paths=[], _flags=[])
|
||||
FileUtils.mkdir_p File.dirname(outfile)
|
||||
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(_defines, _include_paths, _flags),
|
||||
:infile => cygwin_filename(infile), :outfile => cygwin_filename(outfile) }
|
||||
else
|
||||
_run compile_options, { :flags => all_flags(_defines, _include_paths, _flags),
|
||||
:infile => filename(infile), :outfile => filename(outfile) }
|
||||
end
|
||||
_run compile_options, { :flags => all_flags(_defines, _include_paths, _flags),
|
||||
:infile => filename(infile), :outfile => filename(outfile) }
|
||||
end
|
||||
|
||||
def define_rules(build_dir, source_dir='')
|
||||
@@ -176,18 +175,14 @@ module MRuby
|
||||
@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}"
|
||||
@option_library = %q[-l"%s"]
|
||||
@option_library_path = %q[-L"%s"]
|
||||
@link_options = %Q[%{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
|
||||
option_library_path % filename(f)
|
||||
end
|
||||
[flags, library_path_flags, _flags].flatten.join(' ')
|
||||
end
|
||||
@@ -197,23 +192,15 @@ module MRuby
|
||||
end
|
||||
|
||||
def run(outfile, objfiles, _libraries=[], _library_paths=[], _flags=[], _flags_before_libraries=[], _flags_after_libraries=[])
|
||||
FileUtils.mkdir_p File.dirname(outfile)
|
||||
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
|
||||
_run link_options, { :flags => all_flags(_library_paths, _flags),
|
||||
:outfile => filename(outfile) , :objs => filename(objfiles).map{|f| %Q["#{f}"]}.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
|
||||
|
||||
@@ -223,17 +210,13 @@ module MRuby
|
||||
def initialize(build)
|
||||
super
|
||||
@command = ENV['AR'] || 'ar'
|
||||
@archive_options = 'rs %{outfile} %{objs}'
|
||||
@archive_options = 'rs "%{outfile}" %{objs}'
|
||||
end
|
||||
|
||||
def run(outfile, objfiles)
|
||||
FileUtils.mkdir_p File.dirname(outfile)
|
||||
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
|
||||
_run archive_options, { :outfile => filename(outfile), :objs => filename(objfiles).map{|f| %Q["#{f}"]}.join(' ') }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -243,11 +226,11 @@ module MRuby
|
||||
def initialize(build)
|
||||
super
|
||||
@command = 'bison'
|
||||
@compile_options = '-o %{outfile} %{infile}'
|
||||
@compile_options = %q[-o "%{outfile}" "%{infile}"]
|
||||
end
|
||||
|
||||
def run(outfile, infile)
|
||||
FileUtils.mkdir_p File.dirname(outfile)
|
||||
mkdir_p File.dirname(outfile)
|
||||
_pp "YACC", infile.relative_path, outfile.relative_path
|
||||
_run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) }
|
||||
end
|
||||
@@ -259,11 +242,11 @@ module MRuby
|
||||
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}'
|
||||
@compile_options = %q[-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)
|
||||
mkdir_p File.dirname(outfile)
|
||||
_pp "GPERF", infile.relative_path, outfile.relative_path
|
||||
_run compile_options, { :outfile => filename(outfile) , :infile => filename(infile) }
|
||||
end
|
||||
@@ -271,44 +254,50 @@ module MRuby
|
||||
|
||||
class Command::Git < Command
|
||||
attr_accessor :flags
|
||||
attr_accessor :clone_options, :pull_options, :checkout_options, :reset_options
|
||||
attr_accessor :clone_options, :pull_options, :checkout_options, :checkout_detach_options, :reset_options
|
||||
|
||||
def initialize(build)
|
||||
super
|
||||
@command = 'git'
|
||||
@flags = %w[]
|
||||
@clone_options = "clone %{flags} %{url} %{dir}"
|
||||
@pull_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' pull"
|
||||
@checkout_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' checkout %{checksum_hash}"
|
||||
@reset_options = "--git-dir '%{repo_dir}/.git' --work-tree '%{repo_dir}' reset %{checksum_hash}"
|
||||
@pull_options = "--git-dir %{repo_dir}/.git --work-tree %{repo_dir} pull"
|
||||
@checkout_options = "--git-dir %{repo_dir}/.git --work-tree %{repo_dir} checkout %{checksum_hash}"
|
||||
@checkout_detach_options = "--git-dir %{repo_dir}/.git --work-tree %{repo_dir} checkout --detach %{checksum_hash}"
|
||||
@reset_options = "--git-dir %{repo_dir}/.git --work-tree %{repo_dir} reset %{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) }
|
||||
_run clone_options, { :flags => [flags, _flags].flatten.join(' '), :url => shellquote(url), :dir => shellquote(filename(dir)) }
|
||||
end
|
||||
|
||||
def run_pull(dir, url)
|
||||
_pp "GIT PULL", url, dir.relative_path
|
||||
_run pull_options, { :repo_dir => dir }
|
||||
_run pull_options, { :repo_dir => shellquote(dir) }
|
||||
end
|
||||
|
||||
def run_checkout(dir, checksum_hash)
|
||||
_pp "GIT CHECKOUT", checksum_hash
|
||||
_run checkout_options, { :checksum_hash => checksum_hash, :repo_dir => dir }
|
||||
_pp "GIT CHECKOUT", dir, checksum_hash
|
||||
_run checkout_options, { :checksum_hash => checksum_hash, :repo_dir => shellquote(dir) }
|
||||
end
|
||||
|
||||
def run_checkout_detach(dir, checksum_hash)
|
||||
_pp "GIT CHECKOUT DETACH", dir, checksum_hash
|
||||
_run checkout_detach_options, { :checksum_hash => checksum_hash, :repo_dir => shellquote(dir) }
|
||||
end
|
||||
|
||||
def run_reset_hard(dir, checksum_hash)
|
||||
_pp "GIT RESET", checksum_hash
|
||||
_run reset_options, { :checksum_hash => checksum_hash, :repo_dir => dir }
|
||||
_pp "GIT RESET", dir, checksum_hash
|
||||
_run reset_options, { :checksum_hash => checksum_hash, :repo_dir => shellquote(dir) }
|
||||
end
|
||||
|
||||
def commit_hash(dir)
|
||||
`#{@command} --git-dir '#{dir}/.git' --work-tree '#{dir}' rev-parse --verify HEAD`.strip
|
||||
`#{@command} --git-dir #{shellquote(dir +'/.git')} --work-tree #{shellquote(dir)} rev-parse --verify HEAD`.strip
|
||||
end
|
||||
|
||||
def current_branch(dir)
|
||||
`#{@command} --git-dir '#{dir}/.git' --work-tree '#{dir}' rev-parse --abbrev-ref HEAD`.strip
|
||||
`#{@command} --git-dir #{shellquote(dir + '/.git')} --work-tree #{shellquote(dir)} rev-parse --abbrev-ref HEAD`.strip
|
||||
end
|
||||
end
|
||||
|
||||
@@ -327,7 +316,9 @@ module MRuby
|
||||
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|
|
||||
cmd = %Q["#{filename @command}" #{@compile_options % {:funcname => funcname}} #{filename(infiles).map{|f| %Q["#{f}"]}.join(' ')}]
|
||||
puts cmd if Rake.verbose
|
||||
IO.popen(cmd, 'r+') do |io|
|
||||
out.puts io.read
|
||||
end
|
||||
# if mrbc execution fail, drop the file
|
||||
|
||||
@@ -13,13 +13,12 @@ module MRuby
|
||||
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
|
||||
caller_dir = File.expand_path(File.dirname(caller(1,1)[0][/^(.*?):\d/,1]))
|
||||
gemdir = File.expand_path(gemdir, caller_dir)
|
||||
end
|
||||
|
||||
@@ -58,7 +57,7 @@ module MRuby
|
||||
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
|
||||
mkdir_p mgem_list_dir
|
||||
git.run_clone mgem_list_dir, mgem_list_url, "--depth 1"
|
||||
end
|
||||
|
||||
@@ -87,28 +86,27 @@ module MRuby
|
||||
|
||||
if File.exist?(gemdir)
|
||||
if $pull_gems
|
||||
git.run_pull gemdir, url
|
||||
# Jump to the top of the branch
|
||||
git.run_checkout(gemdir, branch)
|
||||
git.run_reset_hard gemdir, "origin/#{branch}"
|
||||
git.run_checkout gemdir, branch
|
||||
git.run_pull gemdir, url
|
||||
elsif params[:checksum_hash]
|
||||
git.run_reset_hard(gemdir, params[:checksum_hash])
|
||||
git.run_checkout_detach gemdir, params[:checksum_hash]
|
||||
elsif lock
|
||||
git.run_reset_hard(gemdir, lock['commit'])
|
||||
git.run_checkout_detach gemdir, lock['commit']
|
||||
end
|
||||
else
|
||||
options = [params[:options]] || []
|
||||
options << "--recursive"
|
||||
options << "--branch \"#{branch}\""
|
||||
options << "--depth 1" unless params[:checksum_hash]
|
||||
FileUtils.mkdir_p "#{gem_clone_dir}"
|
||||
mkdir_p "#{gem_clone_dir}"
|
||||
git.run_clone gemdir, url, options
|
||||
|
||||
# Jump to the specified commit
|
||||
if params[:checksum_hash]
|
||||
git.run_reset_hard gemdir, params[:checksum_hash]
|
||||
git.run_checkout_detach gemdir, params[:checksum_hash]
|
||||
elsif lock
|
||||
git.run_reset_hard gemdir, lock['commit']
|
||||
git.run_checkout_detach gemdir, lock['commit']
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+10
-1
@@ -106,6 +106,15 @@ module MRuby
|
||||
define_gem_init_builder if @generate_functions
|
||||
end
|
||||
|
||||
def for_windows?
|
||||
if build.kind_of?(MRuby::CrossBuild)
|
||||
return %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target)
|
||||
elsif build.kind_of?(MRuby::Build)
|
||||
return ('A'..'Z').to_a.any? { |vol| Dir.exist?("#{vol}:") }
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def add_dependency(name, *requirements)
|
||||
default_gem = requirements.last.kind_of?(Hash) ? requirements.pop : nil
|
||||
requirements = ['>= 0.0.0'] if requirements.empty?
|
||||
@@ -157,7 +166,7 @@ module MRuby
|
||||
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
|
||||
mkdir_p build_dir
|
||||
generate_gem_init("#{build_dir}/gem_init.c")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -54,6 +54,14 @@ module MRuby
|
||||
end
|
||||
end
|
||||
|
||||
def shellquote(s)
|
||||
if ENV['OS'] == 'Windows_NT'
|
||||
"\"#{s}\""
|
||||
else
|
||||
"'#{s}'"
|
||||
end
|
||||
end
|
||||
|
||||
def mruby
|
||||
mruby = {
|
||||
'version' => MRuby::Source::MRUBY_VERSION,
|
||||
@@ -62,7 +70,7 @@ module MRuby
|
||||
|
||||
git_dir = "#{MRUBY_ROOT}/.git"
|
||||
if File.directory?(git_dir)
|
||||
mruby['git_commit'] = `git --git-dir '#{git_dir}' --work-tree '#{MRUBY_ROOT}' rev-parse --verify HEAD`.strip
|
||||
mruby['git_commit'] = `git --git-dir #{shellquote(git_dir)} --work-tree #{shellquote(MRUBY_ROOT)} rev-parse --verify HEAD`.strip
|
||||
end
|
||||
|
||||
mruby
|
||||
|
||||
@@ -1,621 +1,2 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# Original is https://github.com/jimweirich/rake/
|
||||
# Copyright (c) 2003 Jim Weirich
|
||||
# License: MIT-LICENSE
|
||||
|
||||
require 'getoptlong'
|
||||
require 'fileutils'
|
||||
|
||||
$rake_fiber_table = {}
|
||||
$rake_jobs = 1
|
||||
$rake_failed = []
|
||||
|
||||
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
|
||||
|
||||
def done?; @done end
|
||||
def running?; @running end
|
||||
|
||||
# Invoke the task if it is needed. Prerequisites are invoked first.
|
||||
def invoke
|
||||
puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
|
||||
return if @already_invoked
|
||||
prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
|
||||
prerequisites.each do |n|
|
||||
t = Task[n]
|
||||
unless t.done?
|
||||
return prerequisites.select{|v| v = Task[v]; v && (!v.done? || !v.running?) }
|
||||
end
|
||||
end
|
||||
|
||||
@already_invoked = true
|
||||
|
||||
if needed?
|
||||
@running = true
|
||||
if $rake_root_fiber
|
||||
return Fiber.new do
|
||||
self.execute
|
||||
$rake_root_fiber.transfer
|
||||
end
|
||||
else
|
||||
self.execute
|
||||
end
|
||||
end
|
||||
|
||||
@done = true
|
||||
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
|
||||
@done = true
|
||||
@running = false
|
||||
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, level=0)
|
||||
fail "Rule Recursion Too Deep: #{task_name}" if level >= 16
|
||||
RULES.each do |pattern, extensions, block|
|
||||
next unless pattern && pattern.match(task_name)
|
||||
sources = extensions.flat_map do |ext|
|
||||
case ext
|
||||
when /%/
|
||||
task_name.pathmap(ext)
|
||||
when %r{/}
|
||||
ext
|
||||
when /^\./
|
||||
source = task_name.sub(pattern, ext)
|
||||
source == ext ? task_name.ext(ext) : source
|
||||
when String
|
||||
ext
|
||||
when Proc, Method
|
||||
ext.arity == 1 ? ext.call(task_name) : ext.call
|
||||
else
|
||||
fail "Don't know how to handle rule dependent: #{ext.inspect}"
|
||||
end
|
||||
end
|
||||
prereqs = sources.map do |source|
|
||||
if File.exist?(source) || TASKS[source]
|
||||
source
|
||||
elsif parent = enhance_with_matching_rule(source, level + 1)
|
||||
parent.name
|
||||
else
|
||||
break nil
|
||||
end
|
||||
end
|
||||
if prereqs
|
||||
task = FileTask.define_task(task_name => prereqs, &block)
|
||||
task.source = prereqs.first
|
||||
return task
|
||||
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
|
||||
|
||||
if !$rake_root_fiber || Fiber.current == $rake_root_fiber
|
||||
system(cmd) or fail "Command Failed: [#{cmd}]"
|
||||
return
|
||||
end
|
||||
|
||||
pid = Process.spawn(cmd)
|
||||
$rake_fiber_table[pid] = {
|
||||
fiber: Fiber.current,
|
||||
command: cmd,
|
||||
process_waiter: Process.detach(pid)
|
||||
}
|
||||
$rake_root_fiber.transfer
|
||||
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."],
|
||||
['--jobs', '-j', GetoptLong::REQUIRED_ARGUMENT,
|
||||
'Execute rake with parallel jobs.']
|
||||
]
|
||||
|
||||
# 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
|
||||
when '--jobs'
|
||||
$rake_jobs = [value.to_i, 1].max
|
||||
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
|
||||
|
||||
unless $rake_root_fiber
|
||||
require 'fiber'
|
||||
$rake_root_fiber = Fiber.current
|
||||
end
|
||||
|
||||
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
|
||||
root_tasks = []
|
||||
ARGV.each do |task_name|
|
||||
if /^(\w+)=(.*)/.match(task_name)
|
||||
ENV[$1] = $2
|
||||
else
|
||||
root_tasks << task_name
|
||||
end
|
||||
end
|
||||
puts "(in #{Dir.pwd})"
|
||||
$rakefile = @rakefile
|
||||
load @rakefile
|
||||
if $show_tasks
|
||||
display_tasks
|
||||
else
|
||||
root_tasks.push("default") if root_tasks.empty?
|
||||
# revese tasks for popping
|
||||
root_tasks.reverse!
|
||||
|
||||
tasks = []
|
||||
until root_tasks.empty?
|
||||
root_name = root_tasks.pop
|
||||
tasks << root_name
|
||||
until tasks.empty?
|
||||
task_name = tasks.pop
|
||||
t = MiniRake::Task[task_name]
|
||||
f = t.invoke
|
||||
|
||||
# append additional tasks to task queue
|
||||
if f.kind_of?(Array)
|
||||
tasks.push(*f)
|
||||
tasks.uniq!
|
||||
end
|
||||
|
||||
unless f.kind_of? Fiber
|
||||
tasks.insert 0, task_name unless t.done?
|
||||
if root_name == task_name
|
||||
wait_process
|
||||
end
|
||||
next
|
||||
end
|
||||
|
||||
wait_process while $rake_fiber_table.size >= $rake_jobs
|
||||
|
||||
f.transfer
|
||||
end
|
||||
end
|
||||
|
||||
wait_process until $rake_fiber_table.empty?
|
||||
end
|
||||
rescue Exception => e
|
||||
begin
|
||||
$rake_failed << e
|
||||
wait_process until $rake_fiber_table.empty?
|
||||
rescue Exception => next_e
|
||||
e = next_e
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
return if $rake_failed.empty?
|
||||
|
||||
puts "rake aborted!"
|
||||
$rake_failed.each do |ex|
|
||||
puts ex.message
|
||||
if $trace || $verbose
|
||||
puts ex.backtrace.join("\n")
|
||||
else
|
||||
puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
||||
end
|
||||
end
|
||||
exit 1
|
||||
end
|
||||
|
||||
def wait_process(count = 0)
|
||||
dur = [0.0001 * (10 ** count), 1].min
|
||||
sleep dur
|
||||
|
||||
exited = []
|
||||
$rake_fiber_table.each do |pid, v|
|
||||
exited << pid unless v[:process_waiter].alive?
|
||||
end
|
||||
|
||||
exited.each do |pid|
|
||||
ent = $rake_fiber_table.delete pid
|
||||
st = ent[:process_waiter].value
|
||||
|
||||
# ignore process that isn't created by `sh` method
|
||||
return if ent.nil?
|
||||
|
||||
if st.exitstatus != 0
|
||||
raise "Command Failed: [#{ent[:command]}]"
|
||||
end
|
||||
|
||||
fail 'task scheduling bug!' if $rake_fiber_table.size >= $rake_jobs
|
||||
|
||||
ent[:fiber].transfer
|
||||
end
|
||||
|
||||
wait_process(count + 1) if !$rake_fiber_table.empty? && exited.empty?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if __FILE__ == $0 then
|
||||
RakeApp.new.run
|
||||
end
|
||||
#! /usr/bin/env ruby
|
||||
exec "rake", *ARGV
|
||||
|
||||
@@ -686,37 +686,6 @@ class Array
|
||||
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
|
||||
|
||||
@@ -195,12 +195,6 @@ assert("Array#reverse_each") do
|
||||
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
|
||||
@@ -305,19 +299,6 @@ end
|
||||
#assert("Array#bsearch_index") do
|
||||
#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 }
|
||||
|
||||
@@ -17,7 +17,7 @@ unless MRuby::Build.current.kind_of?(MRuby::CrossBuild)
|
||||
}]
|
||||
tmplt = File.read(tmplt_path)
|
||||
File.write(t.name, tmplt.gsub(/(#{Regexp.union(*config.keys)})\b/, config))
|
||||
FileUtils.chmod(0755, t.name)
|
||||
chmod(0755, t.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
require 'open3'
|
||||
require 'tempfile'
|
||||
require 'strscan'
|
||||
|
||||
class BinTest_MrubyBinDebugger
|
||||
@debug1=false
|
||||
@debug2=true
|
||||
# @debug1=false
|
||||
# @debug2=true
|
||||
def self.test(rubysource, testcase)
|
||||
script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
|
||||
|
||||
@@ -19,10 +20,20 @@ class BinTest_MrubyBinDebugger
|
||||
|
||||
stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
|
||||
|
||||
prompt = /^\(#{Regexp.escape(script.path)}:\d+\) /
|
||||
["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
|
||||
o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
|
||||
scanner = StringScanner.new(o)
|
||||
scanner.skip_until(prompt)
|
||||
testcase.each do |tc|
|
||||
exp = tc[:exp]
|
||||
if exp
|
||||
act = scanner.scan_until(/\n/)
|
||||
break unless assert_operator act, :start_with?, exp
|
||||
end
|
||||
scanner.skip_until(prompt)
|
||||
end
|
||||
|
||||
exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
|
||||
=begin
|
||||
if @debug1
|
||||
o.split("\n").each_with_index do |i,actual|
|
||||
@@ -41,14 +52,6 @@ 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
|
||||
@@ -90,8 +93,8 @@ assert('mruby-bin-debugger(print) error') do
|
||||
|
||||
# test case
|
||||
tc = []
|
||||
tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'}
|
||||
tc << {:cmd=>"p bar", :exp=>'$2 = (eval):2: undefined method'}
|
||||
tc << {:cmd=>"p (1+2", :exp=>'$1 = line 1: syntax error'}
|
||||
tc << {:cmd=>"p bar", :exp=>'$2 = undefined method'}
|
||||
|
||||
BinTest_MrubyBinDebugger.test(src, tc)
|
||||
end
|
||||
@@ -588,7 +591,7 @@ SRC
|
||||
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 = (eval):2: undefined method'}
|
||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = undefined method'}
|
||||
|
||||
BinTest_MrubyBinDebugger.test(src, tc)
|
||||
end
|
||||
@@ -626,7 +629,7 @@ SRC
|
||||
tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
|
||||
|
||||
tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
|
||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'}
|
||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = undefined method'}
|
||||
|
||||
BinTest_MrubyBinDebugger.test(src, tc)
|
||||
end
|
||||
@@ -694,8 +697,7 @@ SRC
|
||||
tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
|
||||
|
||||
tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
|
||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'}
|
||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = undefined method'}
|
||||
|
||||
BinTest_MrubyBinDebugger.test(src, tc)
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
#define MRDBCONF_H
|
||||
|
||||
#ifndef MRB_ENABLE_DEBUG_HOOK
|
||||
# error Need 'MRB_ENABLE_DEBUG_HOOK' configuration in your 'build_config.rb'
|
||||
# error mruby-bin-debugger need 'MRB_ENABLE_DEBUG_HOOK' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error mruby-bin-debugger conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
/* configuration options: */
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error mruby-bin-mirb conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/compile.h>
|
||||
@@ -17,7 +22,6 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error mruby-bin-mrbc conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mruby.h>
|
||||
#include <mruby/compile.h>
|
||||
#include <mruby/dump.h>
|
||||
#include <mruby/proc.h>
|
||||
@@ -183,7 +187,7 @@ partial_hook(struct mrb_parser_state *p)
|
||||
return -1;
|
||||
}
|
||||
fn = args->argv[args->idx++];
|
||||
p->f = fopen(fn, "r");
|
||||
p->f = fopen(fn, "rb");
|
||||
if (p->f == NULL) {
|
||||
fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
|
||||
return -1;
|
||||
@@ -210,7 +214,7 @@ load_file(mrb_state *mrb, struct mrbc_args *args)
|
||||
}
|
||||
else {
|
||||
need_close = TRUE;
|
||||
if ((infile = fopen(input, "r")) == NULL) {
|
||||
if ((infile = fopen(input, "rb")) == NULL) {
|
||||
fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ assert '$0 value' do
|
||||
assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp
|
||||
end
|
||||
|
||||
assert 'ARGV value' do
|
||||
assert_mruby(%{["ab", "cde"]\n}, "", true, %w[-e p(ARGV) ab cde])
|
||||
assert_mruby("[]\n", "", true, %w[-e p(ARGV)])
|
||||
end
|
||||
|
||||
assert('float literal') do
|
||||
script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb')
|
||||
File.write script.path, 'p [3.21, 2e308.infinite?, -2e308.infinite?]'
|
||||
@@ -80,10 +85,8 @@ assert('mruby -c option') do
|
||||
end
|
||||
|
||||
assert('mruby -d option') do
|
||||
o = `#{cmd('mruby')} -e #{shellquote('p $DEBUG')}`
|
||||
assert_equal "false\n", o
|
||||
o = `#{cmd('mruby')} -d -e #{shellquote('p $DEBUG')}`
|
||||
assert_equal "true\n", o
|
||||
assert_mruby("false\n", "", true, ["-e", "p $DEBUG"])
|
||||
assert_mruby("true\n", "", true, ["-dep $DEBUG"])
|
||||
end
|
||||
|
||||
assert('mruby -e option (no code specified)') do
|
||||
@@ -125,6 +128,20 @@ assert('mruby -r option (file not found)') do
|
||||
assert_mruby("", /\A.*: Cannot open library file: .*\n\z/, false, %w[-r _no_exists_])
|
||||
end
|
||||
|
||||
assert('mruby -v option') do
|
||||
ver_re = '\Amruby \d+\.\d+\.\d+ \(\d+-\d+-\d+\)\n'
|
||||
assert_mruby(/#{ver_re}\z/, "", true, %w[-v])
|
||||
assert_mruby(/#{ver_re}^[^\n]*NODE.*\n:end\n\z/m, "", true, %w[-v -e p(:end)])
|
||||
end
|
||||
|
||||
assert('mruby --verbose option') do
|
||||
assert_mruby(/\A[^\n]*NODE.*\n:end\n\z/m, "", true, %w[--verbose -e p(:end)])
|
||||
end
|
||||
|
||||
assert('mruby --') do
|
||||
assert_mruby(%{["-x", "1"]\n}, "", true, %w[-e p(ARGV) -- -x 1])
|
||||
end
|
||||
|
||||
assert('mruby invalid short option') do
|
||||
assert_mruby("", /\A.*: invalid option -1 .*\n\z/, false, %w[-1])
|
||||
end
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error mruby-bin-mruby conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mruby.h>
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/compile.h>
|
||||
#include <mruby/dump.h>
|
||||
@@ -9,18 +13,27 @@
|
||||
|
||||
struct _args {
|
||||
FILE *rfp;
|
||||
char* cmdline;
|
||||
char *cmdline;
|
||||
mrb_bool fname : 1;
|
||||
mrb_bool mrbfile : 1;
|
||||
mrb_bool check_syntax : 1;
|
||||
mrb_bool verbose : 1;
|
||||
mrb_bool version : 1;
|
||||
mrb_bool debug : 1;
|
||||
int argc;
|
||||
char** argv;
|
||||
char **argv;
|
||||
int libc;
|
||||
char **libv;
|
||||
};
|
||||
|
||||
struct options {
|
||||
int argc;
|
||||
char **argv;
|
||||
char *program;
|
||||
char *opt;
|
||||
char short_opt[2];
|
||||
};
|
||||
|
||||
static void
|
||||
usage(const char *name)
|
||||
{
|
||||
@@ -44,6 +57,64 @@ usage(const char *name)
|
||||
printf(" %s\n", *p++);
|
||||
}
|
||||
|
||||
static void
|
||||
options_init(struct options *opts, int argc, char **argv)
|
||||
{
|
||||
opts->argc = argc;
|
||||
opts->argv = argv;
|
||||
opts->program = *argv;
|
||||
*opts->short_opt = 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
options_opt(struct options *opts)
|
||||
{
|
||||
/* concatenated short options (e.g. `-cv`) */
|
||||
if (*opts->short_opt && *++opts->opt) {
|
||||
short_opt:
|
||||
opts->short_opt[0] = *opts->opt;
|
||||
opts->short_opt[1] = 0;
|
||||
return opts->short_opt;
|
||||
}
|
||||
|
||||
while (++opts->argv, --opts->argc) {
|
||||
opts->opt = *opts->argv;
|
||||
|
||||
/* empty || not start with `-` || `-` */
|
||||
if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
|
||||
|
||||
if (opts->opt[1] == '-') {
|
||||
/* `--` */
|
||||
if (!opts->opt[2]) {
|
||||
++opts->argv, --opts->argc;
|
||||
return NULL;
|
||||
}
|
||||
/* long option */
|
||||
opts->opt += 2;
|
||||
*opts->short_opt = 0;
|
||||
return opts->opt;
|
||||
}
|
||||
else {
|
||||
/* short option */
|
||||
++opts->opt;
|
||||
goto short_opt;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
options_arg(struct options *opts)
|
||||
{
|
||||
if (*opts->short_opt && opts->opt[1]) {
|
||||
/* concatenated short option and option argument (e.g. `-rLIBRARY`) */
|
||||
*opts->short_opt = 0;
|
||||
return opts->opt + 1;
|
||||
}
|
||||
--opts->argc, ++opts->argv;
|
||||
return opts->argc ? *opts->argv : NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
dup_arg_item(mrb_state *mrb, const char *item)
|
||||
{
|
||||
@@ -56,40 +127,24 @@ dup_arg_item(mrb_state *mrb, const char *item)
|
||||
static int
|
||||
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
||||
{
|
||||
char **origargv = argv;
|
||||
static const struct _args args_zero = { 0 };
|
||||
struct options opts[1];
|
||||
const char *opt, *item;
|
||||
|
||||
*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':
|
||||
options_init(opts, argc, argv);
|
||||
while ((opt = options_opt(opts))) {
|
||||
if (strcmp(opt, "b") == 0) {
|
||||
args->mrbfile = TRUE;
|
||||
break;
|
||||
case 'c':
|
||||
}
|
||||
else if (strcmp(opt, "c") == 0) {
|
||||
args->check_syntax = TRUE;
|
||||
break;
|
||||
case 'd':
|
||||
}
|
||||
else if (strcmp(opt, "d") == 0) {
|
||||
args->debug = TRUE;
|
||||
break;
|
||||
case 'e':
|
||||
if (item[0]) {
|
||||
goto append_cmdline;
|
||||
}
|
||||
else if (argc > 1) {
|
||||
argc--; argv++;
|
||||
item = argv[0];
|
||||
append_cmdline:
|
||||
}
|
||||
else if (strcmp(opt, "e") == 0) {
|
||||
if ((item = options_arg(opts))) {
|
||||
if (!args->cmdline) {
|
||||
args->cmdline = dup_arg_item(mrb, item);
|
||||
}
|
||||
@@ -106,59 +161,65 @@ append_cmdline:
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: No code specified for -e\n", *origargv);
|
||||
fprintf(stderr, "%s: No code specified for -e\n", opts->program);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
usage(*origargv);
|
||||
}
|
||||
else if (strcmp(opt, "h") == 0) {
|
||||
usage(opts->program);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'r':
|
||||
if (!item[0]) {
|
||||
if (argc <= 1) {
|
||||
fprintf(stderr, "%s: No library specified for -r\n", *origargv);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else if (strcmp(opt, "r") == 0) {
|
||||
if ((item = options_arg(opts))) {
|
||||
if (args->libc == 0) {
|
||||
args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
|
||||
}
|
||||
argc--; argv++;
|
||||
item = argv[0];
|
||||
}
|
||||
if (args->libc == 0) {
|
||||
args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
|
||||
else {
|
||||
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
|
||||
}
|
||||
args->libv[args->libc++] = dup_arg_item(mrb, item);
|
||||
}
|
||||
else {
|
||||
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
|
||||
fprintf(stderr, "%s: No library specified for -r\n", opts->program);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
args->libv[args->libc++] = dup_arg_item(mrb, item);
|
||||
break;
|
||||
case 'v':
|
||||
if (!args->verbose) mrb_show_version(mrb);
|
||||
args->verbose = TRUE;
|
||||
break;
|
||||
case '-':
|
||||
if (strcmp((*argv) + 2, "version") == 0) {
|
||||
}
|
||||
else if (strcmp(opt, "v") == 0) {
|
||||
if (!args->verbose) {
|
||||
mrb_show_version(mrb);
|
||||
exit(EXIT_SUCCESS);
|
||||
args->version = TRUE;
|
||||
}
|
||||
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:
|
||||
fprintf(stderr, "%s: invalid option %s (-h will show valid options)\n", *origargv, *argv);
|
||||
args->verbose = TRUE;
|
||||
}
|
||||
else if (strcmp(opt, "version") == 0) {
|
||||
mrb_show_version(mrb);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if (strcmp(opt, "verbose") == 0) {
|
||||
args->verbose = TRUE;
|
||||
}
|
||||
else if (strcmp(opt, "copyright") == 0) {
|
||||
mrb_show_copyright(mrb);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
|
||||
opts->program, opt[1] ? "--" : "-", opt);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->rfp == NULL && args->cmdline == NULL) {
|
||||
if (*argv == NULL) args->rfp = stdin;
|
||||
argc = opts->argc; argv = opts->argv;
|
||||
if (args->cmdline == NULL) {
|
||||
if (*argv == NULL) {
|
||||
if (args->version) exit(EXIT_SUCCESS);
|
||||
args->rfp = stdin;
|
||||
}
|
||||
else {
|
||||
args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
|
||||
args->rfp = strcmp(argv[0], "-") == 0 ?
|
||||
stdin : fopen(argv[0], args->mrbfile ? "rb" : "r");
|
||||
if (args->rfp == NULL) {
|
||||
fprintf(stderr, "%s: Cannot open program file: %s\n", *origargv, *argv);
|
||||
fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
args->fname = TRUE;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error mruby-bin-strip conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mruby.h>
|
||||
#include <mruby/irep.h>
|
||||
#include <mruby/dump.h>
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
static mrb_value
|
||||
mrb_mod_name(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
return mrb_class_path(mrb, mrb_class_ptr(self));
|
||||
mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self));
|
||||
if (mrb_string_p(name)) {
|
||||
MRB_SET_FROZEN_FLAG(mrb_basic_ptr(name));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
|
||||
@@ -599,7 +599,7 @@ new_lit(codegen_scope *s, mrb_value val)
|
||||
|
||||
switch (mrb_type(val)) {
|
||||
case MRB_TT_STRING:
|
||||
*pv = mrb_str_pool(s->mrb, val);
|
||||
*pv = mrb_str_pool(s->mrb, RSTRING_PTR(val), RSTRING_LEN(val), RSTR_NOFREE_P(RSTRING(val)));
|
||||
break;
|
||||
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
@@ -771,7 +771,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
|
||||
s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
|
||||
| ((ra & 0x1) << 6)
|
||||
| ((pa & 0x1f) << 1)
|
||||
| (kd & 0x1);
|
||||
| ((ka | kd) != 0 ? 0x01 : 0x00);
|
||||
genop_W(s, OP_ENTER, a);
|
||||
/* generate jump table for optional arguments initializer */
|
||||
pos = new_label(s);
|
||||
@@ -1122,6 +1122,10 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NODE_NVAR:
|
||||
idx = nint(tree);
|
||||
codegen_error(s, "Can't assign to numbered parameter");
|
||||
break;
|
||||
case NODE_IVAR:
|
||||
idx = new_sym(s, nsym(tree));
|
||||
genop_2(s, OP_SETIV, sp, idx);
|
||||
@@ -2340,6 +2344,17 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_NVAR:
|
||||
if (val) {
|
||||
int idx = nint(tree);
|
||||
|
||||
gen_move(s, cursp(), idx, val);
|
||||
if (val && on_eval(s)) genop_0(s, OP_NOP);
|
||||
|
||||
push();
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_GVAR:
|
||||
{
|
||||
int sym = new_sym(s, nsym(tree));
|
||||
|
||||
@@ -51,6 +51,7 @@ enum node_type {
|
||||
NODE_IVAR,
|
||||
NODE_CONST,
|
||||
NODE_CVAR,
|
||||
NODE_NVAR,
|
||||
NODE_NTH_REF,
|
||||
NODE_BACK_REF,
|
||||
NODE_MATCH,
|
||||
|
||||
+269
-160
@@ -71,23 +71,8 @@ typedef unsigned int stack_type;
|
||||
#define nint(x) ((node*)(intptr_t)(x))
|
||||
#define intn(x) ((int)(intptr_t)(x))
|
||||
|
||||
#if defined(MRB_COMPLEX_NUMBERS) || defined(MRB_RATIONAL_NUMBERS)
|
||||
#define MRB_SUFFIX_SUPPORT
|
||||
|
||||
#ifdef MRB_RATIONAL_NUMBERS
|
||||
#define NUM_SUFFIX_R (1<<0)
|
||||
#else
|
||||
#define NUM_SUFFIX_R 0
|
||||
#endif
|
||||
|
||||
#ifdef MRB_COMPLEX_NUMBERS
|
||||
#define NUM_SUFFIX_I (1<<1)
|
||||
#else
|
||||
#define NUM_SUFFIX_I 0
|
||||
#endif
|
||||
|
||||
#define NUM_SUFFIX_ALL (NUM_SUFFIX_R | NUM_SUFFIX_I)
|
||||
#endif
|
||||
#define NUM_SUFFIX_R (1<<0)
|
||||
#define NUM_SUFFIX_I (1<<1)
|
||||
|
||||
static inline mrb_sym
|
||||
intern_cstr_gen(parser_state *p, const char *s)
|
||||
@@ -103,12 +88,7 @@ intern_gen(parser_state *p, const char *s, size_t 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))
|
||||
#define intern_lit(s) mrb_intern_lit(p->mrb, s)
|
||||
|
||||
static void
|
||||
cons_free_gen(parser_state *p, node *cons)
|
||||
@@ -335,6 +315,24 @@ locals_node(parser_state *p)
|
||||
return p->locals ? p->locals->car : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
nvars_nest(parser_state *p)
|
||||
{
|
||||
p->nvars = cons(nint(0), p->nvars);
|
||||
}
|
||||
|
||||
static void
|
||||
nvars_block(parser_state *p)
|
||||
{
|
||||
p->nvars = cons(nint(-2), p->nvars);
|
||||
}
|
||||
|
||||
static void
|
||||
nvars_unnest(parser_state *p)
|
||||
{
|
||||
p->nvars = p->nvars->cdr;
|
||||
}
|
||||
|
||||
/* (:scope (vars..) (prog...)) */
|
||||
static node*
|
||||
new_scope(parser_state *p, node *body)
|
||||
@@ -669,6 +667,16 @@ new_cvar(parser_state *p, mrb_sym sym)
|
||||
return cons((node*)NODE_CVAR, nsym(sym));
|
||||
}
|
||||
|
||||
/* (:nvar . a) */
|
||||
static node*
|
||||
new_nvar(parser_state *p, int num)
|
||||
{
|
||||
int nvars = intn(p->nvars->car);
|
||||
|
||||
p->nvars->car = nint(nvars > num ? nvars : num);
|
||||
return cons((node*)NODE_NVAR, nint(num));
|
||||
}
|
||||
|
||||
/* (:const . a) */
|
||||
static node*
|
||||
new_const(parser_state *p, mrb_sym sym)
|
||||
@@ -793,15 +801,15 @@ new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
|
||||
|
||||
local_add_blk(p, blk);
|
||||
|
||||
// allocate register for keywords arguments
|
||||
// order is for Proc#parameters
|
||||
/* allocate register for keywords arguments */
|
||||
/* order is for Proc#parameters */
|
||||
for (k = kws; k; k = k->cdr) {
|
||||
if (!k->car->cdr->cdr->car) { // allocate required keywords
|
||||
if (!k->car->cdr->cdr->car) { /* allocate required keywords */
|
||||
local_add_f(p, sym(k->car->cdr->car));
|
||||
}
|
||||
}
|
||||
for (k = kws; k; k = k->cdr) {
|
||||
if (k->car->cdr->cdr->car) { // allocate keywords with default
|
||||
if (k->car->cdr->cdr->car) { /* allocate keywords with default */
|
||||
local_add_lv(p, k->car->cdr->cdr->car->cdr);
|
||||
k->car->cdr->cdr->car = k->car->cdr->cdr->car->car;
|
||||
local_add_f(p, sym(k->car->cdr->car));
|
||||
@@ -826,10 +834,41 @@ new_block_arg(parser_state *p, node *a)
|
||||
return cons((node*)NODE_BLOCK_ARG, a);
|
||||
}
|
||||
|
||||
static node*
|
||||
setup_numparams(parser_state *p, node *a)
|
||||
{
|
||||
int nvars = intn(p->nvars->car);
|
||||
if (nvars > 0) {
|
||||
int i;
|
||||
mrb_sym sym;
|
||||
// m || opt || rest || tail
|
||||
if (a && (a->car || (a->cdr && a->cdr->car) || (a->cdr->cdr && a->cdr->cdr->car) || (a->cdr->cdr->cdr->cdr && a->cdr->cdr->cdr->cdr->car))) {
|
||||
yyerror(p, "ordinary parameter is defined");
|
||||
}
|
||||
else if (p->locals) {
|
||||
/* p->locals should not be NULL unless error happens before the point */
|
||||
node* args = 0;
|
||||
for (i = nvars; i > 0; i--) {
|
||||
char buf[3];
|
||||
|
||||
buf[0] = '_';
|
||||
buf[1] = i+'0';
|
||||
buf[2] = '\0';
|
||||
sym = intern_cstr(buf);
|
||||
args = cons(new_arg(p, sym), args);
|
||||
p->locals->car = cons(nsym(sym), p->locals->car);
|
||||
}
|
||||
a = new_args(p, args, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* (:block arg body) */
|
||||
static node*
|
||||
new_block(parser_state *p, node *a, node *b)
|
||||
{
|
||||
a = setup_numparams(p, a);
|
||||
return list4((node*)NODE_BLOCK, locals_node(p), a, b);
|
||||
}
|
||||
|
||||
@@ -871,37 +910,29 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
|
||||
return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
|
||||
}
|
||||
|
||||
#ifdef MRB_COMPLEX_NUMBERS
|
||||
static node*
|
||||
new_imaginary(parser_state *p, node *imaginary)
|
||||
{
|
||||
return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
|
||||
return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MRB_RATIONAL_NUMBERS
|
||||
static node*
|
||||
new_rational(parser_state *p, node *rational)
|
||||
{
|
||||
return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Rational"), list1(list1(rational)), 1);
|
||||
return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Rational"), list1(list1(rational)), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* (:int . i) */
|
||||
static node*
|
||||
new_int(parser_state *p, const char *s, int base, int suffix)
|
||||
{
|
||||
node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base));
|
||||
#ifdef MRB_RATIONAL_NUMBERS
|
||||
if (suffix & NUM_SUFFIX_R) {
|
||||
result = new_rational(p, result);
|
||||
}
|
||||
#endif
|
||||
#ifdef MRB_COMPLEX_NUMBERS
|
||||
if (suffix & NUM_SUFFIX_I) {
|
||||
result = new_imaginary(p, result);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -911,16 +942,12 @@ static node*
|
||||
new_float(parser_state *p, const char *s, int suffix)
|
||||
{
|
||||
node* result = cons((node*)NODE_FLOAT, (node*)strdup(s));
|
||||
#ifdef MRB_RATIONAL_NUMBERS
|
||||
if (suffix & NUM_SUFFIX_R) {
|
||||
result = new_rational(p, result);
|
||||
}
|
||||
#endif
|
||||
#ifdef MRB_COMPLEX_NUMBERS
|
||||
if (suffix & NUM_SUFFIX_I) {
|
||||
result = new_imaginary(p, result);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@@ -1281,7 +1308,6 @@ 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;
|
||||
@@ -1366,6 +1392,7 @@ heredoc_end(parser_state *p)
|
||||
%token <nd> tSTRING tSTRING_PART tSTRING_MID
|
||||
%token <nd> tNTH_REF tBACK_REF
|
||||
%token <num> tREGEXP_END
|
||||
%token <num> tNUMPARAM
|
||||
|
||||
%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
|
||||
%type <nd> literal numeric cpath symbol
|
||||
@@ -1498,11 +1525,13 @@ top_stmt : stmt
|
||||
| keyword_BEGIN
|
||||
{
|
||||
$<nd>$ = local_switch(p);
|
||||
nvars_block(p);
|
||||
}
|
||||
'{' top_compstmt '}'
|
||||
{
|
||||
yyerror(p, "BEGIN not supported");
|
||||
local_resume(p, $<nd>2);
|
||||
nvars_unnest(p);
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
@@ -1620,9 +1649,9 @@ command_asgn : lhs '=' command_rhs
|
||||
{
|
||||
$$ = new_op_asgn(p, $1, $2, $3);
|
||||
}
|
||||
| primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
|
||||
| primary_value '[' opt_call_args ']' tOP_ASGN command_rhs
|
||||
{
|
||||
$$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
|
||||
$$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
|
||||
}
|
||||
| primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
|
||||
{
|
||||
@@ -1700,6 +1729,7 @@ block_command : block_call
|
||||
cmd_brace_block : tLBRACE_ARG
|
||||
{
|
||||
local_nest(p);
|
||||
nvars_nest(p);
|
||||
}
|
||||
opt_block_param
|
||||
compstmt
|
||||
@@ -1707,6 +1737,7 @@ cmd_brace_block : tLBRACE_ARG
|
||||
{
|
||||
$$ = new_block(p, $3, $4);
|
||||
local_unnest(p);
|
||||
nvars_unnest(p);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1849,9 +1880,9 @@ mlhs_node : variable
|
||||
{
|
||||
assignable(p, $1);
|
||||
}
|
||||
| primary_value '[' opt_call_args rbracket
|
||||
| primary_value '[' opt_call_args ']'
|
||||
{
|
||||
$$ = new_call(p, $1, intern("[]",2), $3, '.');
|
||||
$$ = new_call(p, $1, intern_lit("[]"), $3, '.');
|
||||
}
|
||||
| primary_value call_op tIDENTIFIER
|
||||
{
|
||||
@@ -1888,9 +1919,9 @@ lhs : variable
|
||||
{
|
||||
assignable(p, $1);
|
||||
}
|
||||
| primary_value '[' opt_call_args rbracket
|
||||
| primary_value '[' opt_call_args ']'
|
||||
{
|
||||
$$ = new_call(p, $1, intern("[]",2), $3, '.');
|
||||
$$ = new_call(p, $1, intern_lit("[]"), $3, '.');
|
||||
}
|
||||
| primary_value call_op tIDENTIFIER
|
||||
{
|
||||
@@ -1921,6 +1952,10 @@ lhs : variable
|
||||
backref_error(p, $1);
|
||||
$$ = 0;
|
||||
}
|
||||
| tNUMPARAM
|
||||
{
|
||||
yyerror(p, "can't assign to numbered parameter");
|
||||
}
|
||||
;
|
||||
|
||||
cname : tIDENTIFIER
|
||||
@@ -1974,36 +2009,36 @@ undef_list : fsym
|
||||
}
|
||||
;
|
||||
|
||||
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); }
|
||||
| tDSTAR { $$ = intern("**",2); }
|
||||
| '!' { $$ = intern_c('!'); }
|
||||
| '~' { $$ = intern_c('~'); }
|
||||
| tUPLUS { $$ = intern("+@",2); }
|
||||
| tUMINUS { $$ = intern("-@",2); }
|
||||
| tAREF { $$ = intern("[]",2); }
|
||||
| tASET { $$ = intern("[]=",3); }
|
||||
| '`' { $$ = intern_c('`'); }
|
||||
op : '|' { $$ = intern_lit("|"); }
|
||||
| '^' { $$ = intern_lit("^"); }
|
||||
| '&' { $$ = intern_lit("&"); }
|
||||
| tCMP { $$ = intern_lit("<=>"); }
|
||||
| tEQ { $$ = intern_lit("=="); }
|
||||
| tEQQ { $$ = intern_lit("==="); }
|
||||
| tMATCH { $$ = intern_lit("=~"); }
|
||||
| tNMATCH { $$ = intern_lit("!~"); }
|
||||
| '>' { $$ = intern_lit(">"); }
|
||||
| tGEQ { $$ = intern_lit(">="); }
|
||||
| '<' { $$ = intern_lit("<"); }
|
||||
| tLEQ { $$ = intern_lit("<="); }
|
||||
| tNEQ { $$ = intern_lit("!="); }
|
||||
| tLSHFT { $$ = intern_lit("<<"); }
|
||||
| tRSHFT { $$ = intern_lit(">>"); }
|
||||
| '+' { $$ = intern_lit("+"); }
|
||||
| '-' { $$ = intern_lit("-"); }
|
||||
| '*' { $$ = intern_lit("*"); }
|
||||
| tSTAR { $$ = intern_lit("*"); }
|
||||
| '/' { $$ = intern_lit("/"); }
|
||||
| '%' { $$ = intern_lit("%"); }
|
||||
| tPOW { $$ = intern_lit("**"); }
|
||||
| tDSTAR { $$ = intern_lit("**"); }
|
||||
| '!' { $$ = intern_lit("!"); }
|
||||
| '~' { $$ = intern_lit("~"); }
|
||||
| tUPLUS { $$ = intern_lit("+@"); }
|
||||
| tUMINUS { $$ = intern_lit("-@"); }
|
||||
| tAREF { $$ = intern_lit("[]"); }
|
||||
| tASET { $$ = intern_lit("[]="); }
|
||||
| '`' { $$ = intern_lit("`"); }
|
||||
;
|
||||
|
||||
reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
|
||||
@@ -2028,9 +2063,9 @@ arg : lhs '=' arg_rhs
|
||||
{
|
||||
$$ = new_op_asgn(p, $1, $2, $3);
|
||||
}
|
||||
| primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
|
||||
| primary_value '[' opt_call_args ']' tOP_ASGN arg_rhs
|
||||
{
|
||||
$$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
|
||||
$$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
|
||||
}
|
||||
| primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
|
||||
{
|
||||
@@ -2226,7 +2261,7 @@ arg_rhs : arg %prec tOP_ASGN
|
||||
}
|
||||
;
|
||||
|
||||
paren_args : '(' opt_call_args rparen
|
||||
paren_args : '(' opt_call_args ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
@@ -2237,18 +2272,18 @@ opt_paren_args : none
|
||||
;
|
||||
|
||||
opt_call_args : none
|
||||
| call_args
|
||||
| args ','
|
||||
| call_args opt_terms
|
||||
| args comma
|
||||
{
|
||||
$$ = cons($1,0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| args comma assocs ','
|
||||
| args comma assocs comma
|
||||
{
|
||||
$$ = cons(push($1, new_kw_hash(p, $3)), 0);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| assocs ','
|
||||
| assocs comma
|
||||
{
|
||||
$$ = cons(list1(new_kw_hash(p, $1)), 0);
|
||||
NODE_LINENO($$, $1);
|
||||
@@ -2311,7 +2346,7 @@ opt_block_arg : comma block_arg
|
||||
;
|
||||
|
||||
comma : ','
|
||||
| ',' heredoc_bodies
|
||||
| ',' opt_nl heredoc_bodies
|
||||
;
|
||||
|
||||
args : arg
|
||||
@@ -2362,6 +2397,10 @@ primary : literal
|
||||
| heredoc
|
||||
| var_ref
|
||||
| backref
|
||||
| tNUMPARAM
|
||||
{
|
||||
$$ = new_nvar(p, $1);
|
||||
}
|
||||
| tFID
|
||||
{
|
||||
$$ = new_fcall(p, $1, 0);
|
||||
@@ -2514,6 +2553,7 @@ primary : literal
|
||||
if (p->in_def || p->in_single)
|
||||
yyerror(p, "class definition in method body");
|
||||
$<nd>$ = local_switch(p);
|
||||
nvars_block(p);
|
||||
}
|
||||
bodystmt
|
||||
keyword_end
|
||||
@@ -2521,6 +2561,7 @@ primary : literal
|
||||
$$ = new_class(p, $2, $3, $5);
|
||||
SET_LINENO($$, $1);
|
||||
local_resume(p, $<nd>4);
|
||||
nvars_unnest(p);
|
||||
}
|
||||
| keyword_class
|
||||
tLSHFT expr
|
||||
@@ -2531,6 +2572,7 @@ primary : literal
|
||||
term
|
||||
{
|
||||
$<nd>$ = cons(local_switch(p), nint(p->in_single));
|
||||
nvars_block(p);
|
||||
p->in_single = 0;
|
||||
}
|
||||
bodystmt
|
||||
@@ -2539,6 +2581,7 @@ primary : literal
|
||||
$$ = new_sclass(p, $3, $7);
|
||||
SET_LINENO($$, $1);
|
||||
local_resume(p, $<nd>6->car);
|
||||
nvars_unnest(p);
|
||||
p->in_def = $<num>4;
|
||||
p->in_single = intn($<nd>6->cdr);
|
||||
}
|
||||
@@ -2548,6 +2591,7 @@ primary : literal
|
||||
if (p->in_def || p->in_single)
|
||||
yyerror(p, "module definition in method body");
|
||||
$<nd>$ = local_switch(p);
|
||||
nvars_block(p);
|
||||
}
|
||||
bodystmt
|
||||
keyword_end
|
||||
@@ -2555,6 +2599,7 @@ primary : literal
|
||||
$$ = new_module(p, $2, $4);
|
||||
SET_LINENO($$, $1);
|
||||
local_resume(p, $<nd>3);
|
||||
nvars_unnest(p);
|
||||
}
|
||||
| keyword_def fname
|
||||
{
|
||||
@@ -2564,6 +2609,7 @@ primary : literal
|
||||
{
|
||||
p->in_def++;
|
||||
$<nd>$ = local_switch(p);
|
||||
nvars_block(p);
|
||||
}
|
||||
f_arglist
|
||||
bodystmt
|
||||
@@ -2572,6 +2618,7 @@ primary : literal
|
||||
$$ = new_def(p, $2, $5, $6);
|
||||
SET_LINENO($$, $1);
|
||||
local_resume(p, $<nd>4);
|
||||
nvars_unnest(p);
|
||||
p->in_def--;
|
||||
p->cmdarg_stack = $<stack>3;
|
||||
}
|
||||
@@ -2586,6 +2633,7 @@ primary : literal
|
||||
p->in_single++;
|
||||
p->lstate = EXPR_ENDFN; /* force for args */
|
||||
$<nd>$ = local_switch(p);
|
||||
nvars_block(p);
|
||||
}
|
||||
f_arglist
|
||||
bodystmt
|
||||
@@ -2594,6 +2642,7 @@ primary : literal
|
||||
$$ = new_sdef(p, $2, $5, $7, $8);
|
||||
SET_LINENO($$, $1);
|
||||
local_resume(p, $<nd>6);
|
||||
nvars_unnest(p);
|
||||
p->in_single--;
|
||||
p->cmdarg_stack = $<stack>4;
|
||||
}
|
||||
@@ -2861,6 +2910,7 @@ lambda_body : tLAMBEG compstmt '}'
|
||||
do_block : keyword_do_block
|
||||
{
|
||||
local_nest(p);
|
||||
nvars_nest(p);
|
||||
}
|
||||
opt_block_param
|
||||
bodystmt
|
||||
@@ -2868,6 +2918,7 @@ do_block : keyword_do_block
|
||||
{
|
||||
$$ = new_block(p,$3,$4);
|
||||
local_unnest(p);
|
||||
nvars_unnest(p);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2915,11 +2966,11 @@ method_call : operation paren_args
|
||||
}
|
||||
| primary_value call_op paren_args
|
||||
{
|
||||
$$ = new_call(p, $1, intern("call",4), $3, $2);
|
||||
$$ = new_call(p, $1, intern_lit("call"), $3, $2);
|
||||
}
|
||||
| primary_value tCOLON2 paren_args
|
||||
{
|
||||
$$ = new_call(p, $1, intern("call",4), $3, tCOLON2);
|
||||
$$ = new_call(p, $1, intern_lit("call"), $3, tCOLON2);
|
||||
}
|
||||
| keyword_super paren_args
|
||||
{
|
||||
@@ -2929,15 +2980,16 @@ method_call : operation paren_args
|
||||
{
|
||||
$$ = new_zsuper(p);
|
||||
}
|
||||
| primary_value '[' opt_call_args rbracket
|
||||
| primary_value '[' opt_call_args ']'
|
||||
{
|
||||
$$ = new_call(p, $1, intern("[]",2), $3, '.');
|
||||
$$ = new_call(p, $1, intern_lit("[]"), $3, '.');
|
||||
}
|
||||
;
|
||||
|
||||
brace_block : '{'
|
||||
{
|
||||
local_nest(p);
|
||||
nvars_nest(p);
|
||||
$<num>$ = p->lineno;
|
||||
}
|
||||
opt_block_param
|
||||
@@ -2946,10 +2998,12 @@ brace_block : '{'
|
||||
$$ = new_block(p,$3,$4);
|
||||
SET_LINENO($$, $<num>2);
|
||||
local_unnest(p);
|
||||
nvars_unnest(p);
|
||||
}
|
||||
| keyword_do
|
||||
{
|
||||
local_nest(p);
|
||||
nvars_nest(p);
|
||||
$<num>$ = p->lineno;
|
||||
}
|
||||
opt_block_param
|
||||
@@ -2958,6 +3012,7 @@ brace_block : '{'
|
||||
$$ = new_block(p,$3,$4);
|
||||
SET_LINENO($$, $<num>2);
|
||||
local_unnest(p);
|
||||
nvars_unnest(p);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -3224,6 +3279,10 @@ var_lhs : variable
|
||||
{
|
||||
assignable(p, $1);
|
||||
}
|
||||
| tNUMPARAM
|
||||
{
|
||||
yyerror(p, "can't assign to numbered parameter");
|
||||
}
|
||||
;
|
||||
|
||||
var_ref : variable
|
||||
@@ -3329,11 +3388,13 @@ f_kw : f_label arg
|
||||
|
||||
f_block_kw : f_label primary_value
|
||||
{
|
||||
$$ = new_kw_arg(p, $1, $2);
|
||||
$$ = new_kw_arg(p, $1, cons($2, locals_node(p)));
|
||||
local_unnest(p);
|
||||
}
|
||||
| f_label
|
||||
{
|
||||
$$ = new_kw_arg(p, $1, 0);
|
||||
local_unnest(p);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -3482,6 +3543,11 @@ f_bad_arg : tCONSTANT
|
||||
yyerror(p, "formal argument cannot be a class variable");
|
||||
$$ = 0;
|
||||
}
|
||||
| tNUMPARAM
|
||||
{
|
||||
yyerror(p, "formal argument cannot be a numbered parameter");
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
f_norm_arg : f_bad_arg
|
||||
@@ -3643,24 +3709,28 @@ assocs : assoc
|
||||
$$ = list1($1);
|
||||
NODE_LINENO($$, $1);
|
||||
}
|
||||
| assocs ',' assoc
|
||||
| assocs comma assoc
|
||||
{
|
||||
$$ = push($1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
label_tag : tLABEL_TAG
|
||||
| tLABEL_TAG heredoc_bodies
|
||||
;
|
||||
|
||||
assoc : arg tASSOC arg
|
||||
{
|
||||
void_expr_error(p, $1);
|
||||
void_expr_error(p, $3);
|
||||
$$ = cons($1, $3);
|
||||
}
|
||||
| tIDENTIFIER tLABEL_TAG arg
|
||||
| tIDENTIFIER label_tag arg
|
||||
{
|
||||
void_expr_error(p, $3);
|
||||
$$ = cons(new_sym(p, $1), $3);
|
||||
}
|
||||
| string_fragment tLABEL_TAG arg
|
||||
| string_fragment label_tag arg
|
||||
{
|
||||
void_expr_error(p, $3);
|
||||
if ($1->car == (node*)NODE_DSTR) {
|
||||
@@ -3722,14 +3792,11 @@ opt_nl : /* none */
|
||||
| nl
|
||||
;
|
||||
|
||||
rparen : opt_nl ')'
|
||||
;
|
||||
|
||||
rbracket : opt_nl ']'
|
||||
rparen : opt_terms ')'
|
||||
;
|
||||
|
||||
trailer : /* none */
|
||||
| nl
|
||||
| terms
|
||||
| comma
|
||||
;
|
||||
|
||||
@@ -3899,6 +3966,27 @@ 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
|
||||
nextc0(parser_state *p)
|
||||
{
|
||||
int c;
|
||||
#ifndef MRB_DISABLE_STDIO
|
||||
if (p->f) {
|
||||
if (feof(p->f)) return -1;
|
||||
c = fgetc(p->f);
|
||||
if (c == EOF) return -1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!p->s || p->s >= p->send) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
c = (unsigned char)*p->s++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline int
|
||||
nextc(parser_state *p)
|
||||
{
|
||||
@@ -3913,24 +4001,19 @@ nextc(parser_state *p)
|
||||
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++;
|
||||
}
|
||||
c = nextc0(p);
|
||||
if (c < 0) goto eof;
|
||||
}
|
||||
if (c >= 0) {
|
||||
p->column++;
|
||||
}
|
||||
if (c == '\r') {
|
||||
const int lf = nextc0(p);
|
||||
if (lf == '\n') {
|
||||
return '\n';
|
||||
}
|
||||
if (lf > 0) pushback(p, lf);
|
||||
}
|
||||
return c;
|
||||
|
||||
eof:
|
||||
@@ -4387,12 +4470,7 @@ parse_string(parser_state *p)
|
||||
}
|
||||
}
|
||||
if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
|
||||
if (c < 0) {
|
||||
p->parsing_heredoc = NULL;
|
||||
}
|
||||
else {
|
||||
return tHEREDOC_END;
|
||||
}
|
||||
return tHEREDOC_END;
|
||||
}
|
||||
}
|
||||
if (c < 0) {
|
||||
@@ -4596,13 +4674,13 @@ parse_string(parser_state *p)
|
||||
return tSTRING;
|
||||
}
|
||||
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
static int
|
||||
number_literal_suffix(parser_state *p, int mask)
|
||||
number_literal_suffix(parser_state *p)
|
||||
{
|
||||
int c, result = 0;
|
||||
node *list = 0;
|
||||
int column = p->column;
|
||||
int mask = NUM_SUFFIX_R|NUM_SUFFIX_I;
|
||||
|
||||
while ((c = nextc(p)) != -1) {
|
||||
list = push(list, (node*)(intptr_t)c);
|
||||
@@ -4634,7 +4712,6 @@ number_literal_suffix(parser_state *p, int mask)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
heredoc_identifier(parser_state *p)
|
||||
@@ -4819,7 +4896,7 @@ parser_yylex(parser_state *p)
|
||||
case '*':
|
||||
if ((c = nextc(p)) == '*') {
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern("**",2);
|
||||
pylval.id = intern_lit("**");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -4837,7 +4914,7 @@ parser_yylex(parser_state *p)
|
||||
}
|
||||
else {
|
||||
if (c == '=') {
|
||||
pylval.id = intern_c('*');
|
||||
pylval.id = intern_lit("*");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -4953,7 +5030,7 @@ parser_yylex(parser_state *p)
|
||||
}
|
||||
if (c == '<') {
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern("<<",2);
|
||||
pylval.id = intern_lit("<<");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -4975,7 +5052,7 @@ parser_yylex(parser_state *p)
|
||||
}
|
||||
if (c == '>') {
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern(">>",2);
|
||||
pylval.id = intern_lit(">>");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5083,7 +5160,7 @@ parser_yylex(parser_state *p)
|
||||
if ((c = nextc(p)) == '&') {
|
||||
p->lstate = EXPR_BEG;
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern("&&",2);
|
||||
pylval.id = intern_lit("&&");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5095,7 +5172,7 @@ parser_yylex(parser_state *p)
|
||||
return tANDDOT;
|
||||
}
|
||||
else if (c == '=') {
|
||||
pylval.id = intern_c('&');
|
||||
pylval.id = intern_lit("&");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5122,7 +5199,7 @@ parser_yylex(parser_state *p)
|
||||
if ((c = nextc(p)) == '|') {
|
||||
p->lstate = EXPR_BEG;
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern("||",2);
|
||||
pylval.id = intern_lit("||");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5130,7 +5207,7 @@ parser_yylex(parser_state *p)
|
||||
return tOROP;
|
||||
}
|
||||
if (c == '=') {
|
||||
pylval.id = intern_c('|');
|
||||
pylval.id = intern_lit("|");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5154,7 +5231,7 @@ parser_yylex(parser_state *p)
|
||||
return '+';
|
||||
}
|
||||
if (c == '=') {
|
||||
pylval.id = intern_c('+');
|
||||
pylval.id = intern_lit("+");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5182,7 +5259,7 @@ parser_yylex(parser_state *p)
|
||||
return '-';
|
||||
}
|
||||
if (c == '=') {
|
||||
pylval.id = intern_c('-');
|
||||
pylval.id = intern_lit("-");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5257,9 +5334,7 @@ parser_yylex(parser_state *p)
|
||||
no_digits();
|
||||
}
|
||||
else if (nondigit) goto trailing_uc;
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_int(p, tok(p), 16, suffix);
|
||||
return tINTEGER;
|
||||
}
|
||||
@@ -5284,9 +5359,7 @@ parser_yylex(parser_state *p)
|
||||
no_digits();
|
||||
}
|
||||
else if (nondigit) goto trailing_uc;
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_int(p, tok(p), 2, suffix);
|
||||
return tINTEGER;
|
||||
}
|
||||
@@ -5311,9 +5384,7 @@ parser_yylex(parser_state *p)
|
||||
no_digits();
|
||||
}
|
||||
else if (nondigit) goto trailing_uc;
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_int(p, tok(p), 10, suffix);
|
||||
return tINTEGER;
|
||||
}
|
||||
@@ -5347,9 +5418,7 @@ parser_yylex(parser_state *p)
|
||||
pushback(p, c);
|
||||
tokfix(p);
|
||||
if (nondigit) goto trailing_uc;
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_int(p, tok(p), 8, suffix);
|
||||
return tINTEGER;
|
||||
}
|
||||
@@ -5367,9 +5436,7 @@ parser_yylex(parser_state *p)
|
||||
}
|
||||
else {
|
||||
pushback(p, c);
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_int(p, "0", 10, suffix);
|
||||
return tINTEGER;
|
||||
}
|
||||
@@ -5459,16 +5526,12 @@ parser_yylex(parser_state *p)
|
||||
yywarning_s(p, "float out of range", tok(p));
|
||||
errno = 0;
|
||||
}
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_float(p, tok(p), suffix);
|
||||
return tFLOAT;
|
||||
#endif
|
||||
}
|
||||
#ifdef MRB_SUFFIX_SUPPORT
|
||||
suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
|
||||
#endif
|
||||
suffix = number_literal_suffix(p);
|
||||
pylval.nd = new_int(p, tok(p), 10, suffix);
|
||||
return tINTEGER;
|
||||
}
|
||||
@@ -5516,7 +5579,7 @@ parser_yylex(parser_state *p)
|
||||
return tREGEXP_BEG;
|
||||
}
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern_c('/');
|
||||
pylval.id = intern_lit("/");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5535,7 +5598,7 @@ parser_yylex(parser_state *p)
|
||||
|
||||
case '^':
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern_c('^');
|
||||
pylval.id = intern_lit("^");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5712,7 +5775,7 @@ parser_yylex(parser_state *p)
|
||||
}
|
||||
}
|
||||
if ((c = nextc(p)) == '=') {
|
||||
pylval.id = intern_c('%');
|
||||
pylval.id = intern_lit("%");
|
||||
p->lstate = EXPR_BEG;
|
||||
return tOP_ASGN;
|
||||
}
|
||||
@@ -5766,7 +5829,7 @@ parser_yylex(parser_state *p)
|
||||
tokadd(p, '$');
|
||||
tokadd(p, c);
|
||||
tokfix(p);
|
||||
pylval.id = intern_cstr(tok(p));
|
||||
pylval.id = intern(tok(p), toklen(p));
|
||||
return tGVAR;
|
||||
|
||||
case '-':
|
||||
@@ -5776,7 +5839,7 @@ parser_yylex(parser_state *p)
|
||||
pushback(p, c);
|
||||
gvar:
|
||||
tokfix(p);
|
||||
pylval.id = intern_cstr(tok(p));
|
||||
pylval.id = intern(tok(p), toklen(p));
|
||||
return tGVAR;
|
||||
|
||||
case '&': /* $&: last match */
|
||||
@@ -5914,6 +5977,39 @@ parser_yylex(parser_state *p)
|
||||
result = tIVAR;
|
||||
break;
|
||||
|
||||
case '_':
|
||||
if (toklen(p) == 2 && ISDIGIT(tok(p)[1]) && p->nvars) {
|
||||
int n = tok(p)[1] - '0';
|
||||
int nvar;
|
||||
|
||||
if (n > 0) {
|
||||
node *nvars = p->nvars->cdr;
|
||||
|
||||
while (nvars) {
|
||||
nvar = intn(nvars->car);
|
||||
if (nvar == -2) break; /* top of the scope */
|
||||
if (nvar > 0) {
|
||||
yywarning(p, "numbered parameter used in outer block");
|
||||
break;
|
||||
}
|
||||
nvars->car = nint(-1);
|
||||
nvars = nvars->cdr;
|
||||
}
|
||||
nvar = intn(p->nvars->car);
|
||||
if (nvar == -1) {
|
||||
yywarning(p, "numbered parameter used in inner block");
|
||||
}
|
||||
if (nvar >= -1) {
|
||||
pylval.num = n;
|
||||
p->lstate = EXPR_END;
|
||||
return tNUMPARAM;
|
||||
}
|
||||
else {
|
||||
yywarning(p, "identifier for numbered parameter; consider another name");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
if (toklast(p) == '!' || toklast(p) == '?') {
|
||||
result = tFID;
|
||||
@@ -5929,6 +6025,15 @@ parser_yylex(parser_state *p)
|
||||
else {
|
||||
pushback(p, c);
|
||||
}
|
||||
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;
|
||||
@@ -5942,7 +6047,7 @@ parser_yylex(parser_state *p)
|
||||
if (IS_LABEL_SUFFIX(0)) {
|
||||
p->lstate = EXPR_END;
|
||||
tokfix(p);
|
||||
pylval.id = intern_cstr(tok(p));
|
||||
pylval.id = intern(tok(p), toklen(p));
|
||||
return tIDENTIFIER;
|
||||
}
|
||||
}
|
||||
@@ -6001,7 +6106,7 @@ parser_yylex(parser_state *p)
|
||||
}
|
||||
}
|
||||
{
|
||||
mrb_sym ident = intern_cstr(tok(p));
|
||||
mrb_sym ident = intern(tok(p), toklen(p));
|
||||
|
||||
pylval.id = ident;
|
||||
if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) {
|
||||
@@ -6896,6 +7001,10 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
|
||||
printf("NODE_CVAR %s\n", mrb_sym_name(mrb, sym(tree)));
|
||||
break;
|
||||
|
||||
case NODE_NVAR:
|
||||
printf("NODE_NVAR %d\n", intn(tree));
|
||||
break;
|
||||
|
||||
case NODE_CONST:
|
||||
printf("NODE_CONST %s\n", mrb_sym_name(mrb, sym(tree)));
|
||||
break;
|
||||
|
||||
@@ -26,7 +26,7 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
||||
|
||||
# Parser
|
||||
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
|
||||
FileUtils.mkdir_p File.dirname t.name
|
||||
mkdir_p File.dirname t.name
|
||||
yacc.run t.name, t.prerequisites.first
|
||||
end
|
||||
|
||||
|
||||
@@ -3,8 +3,5 @@ MRuby::Gem::Specification.new('mruby-complex') do |spec|
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Complex class'
|
||||
|
||||
spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog'
|
||||
spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext'
|
||||
spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext'
|
||||
spec.add_dependency 'mruby-math', core: 'mruby-math'
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Complex < Numeric
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#{real}#{'+' unless imaginary.negative?}#{imaginary}i"
|
||||
"#{real}#{'+' unless imaginary < 0}#{imaginary}i"
|
||||
end
|
||||
|
||||
def +@
|
||||
@@ -56,7 +56,7 @@ class Complex < Numeric
|
||||
if rhs.is_a? Complex
|
||||
real == rhs.real && imaginary == rhs.imaginary
|
||||
elsif rhs.is_a? Numeric
|
||||
imaginary.zero? && real == rhs
|
||||
imaginary == 0 && real == rhs
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,14 +106,14 @@ class Complex < Numeric
|
||||
|
||||
[Fixnum, Float].each do |cls|
|
||||
[:+, :-, :*, :/, :==].each do |op|
|
||||
cls.instance_exec do
|
||||
cls.instance_eval do
|
||||
original_operator_name = "__original_operator_#{op}_complex"
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Complex
|
||||
Complex(self).send(op, rhs)
|
||||
Complex(self).__send__(op, rhs)
|
||||
else
|
||||
send(original_operator_name, rhs)
|
||||
__send__(original_operator_name, rhs)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ 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();
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
if (state) { *state = FALSE; }
|
||||
|
||||
@@ -34,7 +34,7 @@ mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure,
|
||||
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
|
||||
struct mrb_jmpbuf c_jmp;
|
||||
mrb_value result;
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
MRB_TRY(&c_jmp) {
|
||||
mrb->jmp = &c_jmp;
|
||||
@@ -71,7 +71,7 @@ mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_fun
|
||||
mrb_value result;
|
||||
mrb_bool error_matched = FALSE;
|
||||
mrb_int i;
|
||||
mrb_int ai = mrb_gc_arena_save(mrb);
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
MRB_TRY(&c_jmp) {
|
||||
mrb->jmp = &c_jmp;
|
||||
|
||||
@@ -110,8 +110,8 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||
insn = iseq[i];
|
||||
switch(insn){
|
||||
case OP_EPUSH:
|
||||
b = PEEK_S(iseq+i+1);
|
||||
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||
a = PEEK_B(iseq+i+1);
|
||||
patch_irep(mrb, irep->reps[a], bnest + 1, top);
|
||||
break;
|
||||
|
||||
case OP_LAMBDA:
|
||||
@@ -390,7 +390,7 @@ 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_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
|
||||
mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -4,12 +4,17 @@
|
||||
static mrb_value
|
||||
f_exit(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_int i = EXIT_SUCCESS;
|
||||
mrb_value status = mrb_true_value();
|
||||
int istatus;
|
||||
|
||||
mrb_get_args(mrb, "|o", &status);
|
||||
istatus = mrb_true_p(status) ? EXIT_SUCCESS :
|
||||
mrb_false_p(status) ? EXIT_FAILURE :
|
||||
(int)mrb_int(mrb, status);
|
||||
exit(istatus);
|
||||
|
||||
mrb_get_args(mrb, "|i", &i);
|
||||
exit((int)i);
|
||||
/* not reached */
|
||||
return mrb_nil_value();
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -409,7 +409,7 @@ mrb_mruby_fiber_gem_init(mrb_state* mrb)
|
||||
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, "initialize", fiber_init, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
|
||||
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());
|
||||
|
||||
@@ -2,7 +2,5 @@ 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
|
||||
|
||||
@@ -53,10 +53,8 @@ hash_slice(mrb_state *mrb, mrb_value hash)
|
||||
mrb_int argc, i;
|
||||
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
if (argc == 0) {
|
||||
return mrb_hash_new_capa(mrb, argc);
|
||||
}
|
||||
result = mrb_hash_new_capa(mrb, argc);
|
||||
if (argc == 0) return result; /* empty hash */
|
||||
for (i = 0; i < argc; i++) {
|
||||
mrb_value key = argv[i];
|
||||
mrb_value val;
|
||||
|
||||
@@ -269,10 +269,8 @@ assert("Hash#transform_keys") do
|
||||
h.transform_keys{|k| k+"!"})
|
||||
assert_equal({1 => 100, 2 => 200},
|
||||
h.transform_keys{|k|k.to_i})
|
||||
assert_equal({"1.0" => 100, "2.1" => 200},
|
||||
h.transform_keys.with_index{|k, i| "#{k}.#{i}"})
|
||||
assert_equal(h, h.transform_keys!{|k|k.to_i})
|
||||
assert_equal(h, {1 => 100, 2 => 200})
|
||||
assert_same(h, h.transform_keys!{|k|k.to_i})
|
||||
assert_equal({1 => 100, 2 => 200}, h)
|
||||
end
|
||||
|
||||
assert("Hash#transform_values") do
|
||||
@@ -281,9 +279,7 @@ assert("Hash#transform_values") do
|
||||
h.transform_values{|v| v * v + 1})
|
||||
assert_equal({a: "1", b: "2", c: "3"},
|
||||
h.transform_values{|v|v.to_s})
|
||||
assert_equal({a: "1.0", b: "2.1", c: "3.2"},
|
||||
h.transform_values.with_index{|v, i| "#{v}.#{i}"})
|
||||
assert_equal(h, h.transform_values!{|v|v.to_s})
|
||||
assert_same(h, h.transform_values!{|v|v.to_s})
|
||||
assert_equal({a: "1", b: "2", c: "3"}, h)
|
||||
end
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ Add the line below to your `build_config.rb`:
|
||||
## License
|
||||
|
||||
Copyright (c) 2013 Internet Initiative Japan Inc.
|
||||
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"),
|
||||
|
||||
@@ -5,10 +5,24 @@
|
||||
#ifndef MRUBY_IO_H
|
||||
#define MRUBY_IO_H
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error IO and File conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(MRB_WITHOUT_IO_PREAD_PWRITE)
|
||||
# undef MRB_WITH_IO_PREAD_PWRITE
|
||||
#elif !defined(MRB_WITH_IO_PREAD_PWRITE)
|
||||
# if defined(__unix__)
|
||||
# define MRB_WITH_IO_PREAD_PWRITE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
struct mrb_io {
|
||||
int fd; /* file descriptor, or -1 */
|
||||
int fd2; /* file descriptor to write if it's different from fd, or -1 */
|
||||
@@ -19,18 +33,36 @@ struct mrb_io {
|
||||
is_socket: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 MRB_O_RDONLY 0x0000
|
||||
#define MRB_O_WRONLY 0x0001
|
||||
#define MRB_O_RDWR 0x0002
|
||||
#define MRB_O_ACCMODE (MRB_O_RDONLY | MRB_O_WRONLY | MRB_O_RDWR)
|
||||
#define MRB_O_NONBLOCK 0x0004
|
||||
#define MRB_O_APPEND 0x0008
|
||||
#define MRB_O_SYNC 0x0010
|
||||
#define MRB_O_NOFOLLOW 0x0020
|
||||
#define MRB_O_CREAT 0x0040
|
||||
#define MRB_O_TRUNC 0x0080
|
||||
#define MRB_O_EXCL 0x0100
|
||||
#define MRB_O_NOCTTY 0x0200
|
||||
#define MRB_O_DIRECT 0x0400
|
||||
#define MRB_O_BINARY 0x0800
|
||||
#define MRB_O_SHARE_DELETE 0x1000
|
||||
#define MRB_O_TMPFILE 0x2000
|
||||
#define MRB_O_NOATIME 0x4000
|
||||
#define MRB_O_DSYNC 0x00008000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
|
||||
#define MRB_O_RSYNC 0x00010000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
|
||||
|
||||
#define MRB_O_RDONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_RDONLY))
|
||||
#define MRB_O_WRONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_WRONLY))
|
||||
#define MRB_O_RDWR_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_RDWR))
|
||||
#define MRB_O_READABLE_P(f) ((mrb_bool)((((f) & MRB_O_ACCMODE) | 2) == 2))
|
||||
#define MRB_O_WRITABLE_P(f) ((mrb_bool)(((((f) & MRB_O_ACCMODE) + 1) & 2) == 2))
|
||||
|
||||
#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);
|
||||
int mrb_io_fileno(mrb_state *mrb, mrb_value io);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern "C" { */
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
MRuby::Gem::Specification.new('mruby-io') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.authors = 'Internet Initiative Japan Inc.'
|
||||
spec.authors = ['Internet Initiative Japan Inc.', 'mruby developers']
|
||||
spec.summary = 'IO and File class'
|
||||
|
||||
spec.cc.include_paths << "#{build.root}/src"
|
||||
|
||||
case RUBY_PLATFORM
|
||||
when /mingw|mswin|msys/
|
||||
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']
|
||||
if for_windows?
|
||||
spec.linker.libraries << "ws2_32"
|
||||
end
|
||||
spec.add_test_dependency 'mruby-time', core: 'mruby-time'
|
||||
end
|
||||
|
||||
@@ -55,46 +55,46 @@ class File < IO
|
||||
s
|
||||
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
|
||||
def self._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 += "/"
|
||||
unless home_dir
|
||||
raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
|
||||
end
|
||||
else
|
||||
expanded_path = concat_path(base_path, _getwd)
|
||||
expanded_path += "/" + path
|
||||
end
|
||||
|
||||
expanded_path
|
||||
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 = concat_path(path, default_dir)
|
||||
expanded_path
|
||||
end
|
||||
|
||||
def self.expand_path(path, default_dir = '.')
|
||||
expanded_path = _concat_path(path, default_dir)
|
||||
drive_prefix = ""
|
||||
if File::ALT_SEPARATOR && expanded_path.size > 2 &&
|
||||
("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
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
|
||||
|
||||
@@ -170,21 +170,16 @@ class IO
|
||||
end
|
||||
|
||||
def _read_buf
|
||||
return @buf if @buf && @buf.bytesize >= 4 # maximum UTF-8 character is 4 bytes
|
||||
@buf ||= ""
|
||||
begin
|
||||
@buf += sysread(BUF_SIZE)
|
||||
rescue EOFError => e
|
||||
raise e if @buf.empty?
|
||||
end
|
||||
return @buf if @buf && @buf.bytesize > 0
|
||||
sysread(BUF_SIZE, @buf)
|
||||
end
|
||||
|
||||
def ungetc(substr)
|
||||
raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
|
||||
if @buf.empty?
|
||||
@buf = substr.dup
|
||||
@buf.replace(substr)
|
||||
else
|
||||
@buf = substr + @buf
|
||||
@buf[0,0] = substr
|
||||
end
|
||||
nil
|
||||
end
|
||||
@@ -288,15 +283,15 @@ class IO
|
||||
|
||||
def readchar
|
||||
_read_buf
|
||||
c = @buf[0]
|
||||
@buf[0] = ""
|
||||
c
|
||||
_readchar(@buf)
|
||||
end
|
||||
|
||||
def getc
|
||||
begin
|
||||
readchar
|
||||
rescue EOFError
|
||||
c = @buf[0]
|
||||
@buf[0,1]="" if c
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,8 +28,4 @@ module Kernel
|
||||
def gets(*args)
|
||||
$stdin.gets(*args)
|
||||
end
|
||||
|
||||
def getc(*args)
|
||||
$stdin.getc(*args)
|
||||
end
|
||||
end
|
||||
|
||||
+171
-11
@@ -7,12 +7,7 @@
|
||||
#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>
|
||||
@@ -53,6 +48,7 @@
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#define PATH_SEPARATOR ";"
|
||||
#define FILE_ALT_SEPARATOR "\\"
|
||||
#define VOLUME_SEPARATOR ":"
|
||||
#else
|
||||
#define PATH_SEPARATOR ":"
|
||||
#endif
|
||||
@@ -70,7 +66,15 @@
|
||||
#define LOCK_UN 8
|
||||
#endif
|
||||
|
||||
#define STAT(p, s) stat(p, s)
|
||||
#ifndef _WIN32
|
||||
typedef struct stat mrb_stat;
|
||||
# define mrb_stat(path, sb) stat(path, sb)
|
||||
# define mrb_fstat(fd, sb) fstat(fd, sb)
|
||||
#else
|
||||
typedef struct __stat64 mrb_stat;
|
||||
# define mrb_stat(path, sb) _stat64(path, sb)
|
||||
# define mrb_fstat(fd, sb) _fstat64(fd, sb)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static int
|
||||
@@ -276,12 +280,59 @@ mrb_file__getwd(mrb_state *mrb, mrb_value klass)
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_FILESEP(x) (x == (*(char*)(FILE_SEPARATOR)) || x == (*(char*)(FILE_ALT_SEPARATOR)))
|
||||
#define IS_VOLSEP(x) (x == (*(char*)(VOLUME_SEPARATOR)))
|
||||
#define IS_DEVICEID(x) (x == '.' || x == '?')
|
||||
#define CHECK_UNCDEV_PATH (IS_FILESEP(path[0]) && IS_FILESEP(path[1]))
|
||||
|
||||
static int
|
||||
is_absolute_traditional_path(const char *path, size_t len)
|
||||
{
|
||||
if (len < 3) return 0;
|
||||
return (ISALPHA(path[0]) && IS_VOLSEP(path[1]) && IS_FILESEP(path[2]));
|
||||
}
|
||||
|
||||
static int
|
||||
is_aboslute_unc_path(const char *path, size_t len) {
|
||||
if (len < 2) return 0;
|
||||
return (CHECK_UNCDEV_PATH && !IS_DEVICEID(path[2]));
|
||||
}
|
||||
|
||||
static int
|
||||
is_absolute_device_path(const char *path, size_t len) {
|
||||
if (len < 4) return 0;
|
||||
return (CHECK_UNCDEV_PATH && IS_DEVICEID(path[2]) && IS_FILESEP(path[3]));
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_file_is_absolute_path(const char *path)
|
||||
{
|
||||
return (path[0] == '/');
|
||||
size_t len = strlen(path);
|
||||
if (IS_FILESEP(path[0])) return 1;
|
||||
if (len > 0)
|
||||
return (
|
||||
is_absolute_traditional_path(path, len) ||
|
||||
is_aboslute_unc_path(path, len) ||
|
||||
is_absolute_device_path(path, len)
|
||||
);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef IS_FILESEP
|
||||
#undef IS_VOLSEP
|
||||
#undef IS_DEVICEID
|
||||
#undef CHECK_UNCDEV_PATH
|
||||
|
||||
#else
|
||||
static int
|
||||
mrb_file_is_absolute_path(const char *path)
|
||||
{
|
||||
return (path[0] == *(char*)(FILE_SEPARATOR));
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_value
|
||||
mrb_file__gethome(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -316,7 +367,7 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass)
|
||||
path = mrb_str_new_cstr(mrb, home);
|
||||
mrb_locale_free(home);
|
||||
return path;
|
||||
#else
|
||||
#else /* _WIN32 */
|
||||
argc = mrb_get_argc(mrb);
|
||||
if (argc == 0) {
|
||||
home = getenv("USERPROFILE");
|
||||
@@ -344,7 +395,7 @@ mrb_file_mtime(mrb_state *mrb, mrb_value self)
|
||||
int fd;
|
||||
|
||||
obj = mrb_obj_value(mrb_class_get(mrb, "Time"));
|
||||
fd = (int)mrb_fixnum(mrb_io_fileno(mrb, self));
|
||||
fd = mrb_io_fileno(mrb, self);
|
||||
if (fstat(fd, &st) == -1)
|
||||
return mrb_false_value();
|
||||
return mrb_funcall(mrb, obj, "at", 1, mrb_fixnum_value(st.st_mtime));
|
||||
@@ -360,7 +411,7 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
int fd;
|
||||
|
||||
mrb_get_args(mrb, "i", &operation);
|
||||
fd = (int)mrb_fixnum(mrb_io_fileno(mrb, self));
|
||||
fd = mrb_io_fileno(mrb, self);
|
||||
|
||||
while (flock(fd, (int)operation) == -1) {
|
||||
switch (errno) {
|
||||
@@ -384,6 +435,95 @@ mrb_file_flock(mrb_state *mrb, mrb_value self)
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_file_size(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_stat st;
|
||||
int fd;
|
||||
|
||||
fd = mrb_io_fileno(mrb, self);
|
||||
if (mrb_fstat(fd, &st) == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "fstat failed");
|
||||
}
|
||||
|
||||
if (st.st_size > MRB_INT_MAX) {
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "File#size too large for MRB_WITHOUT_FLOAT");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)st.st_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
return mrb_fixnum_value((mrb_int)st.st_size);
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_ftruncate(int fd, int64_t length)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return ftruncate(fd, (off_t)length);
|
||||
#else
|
||||
HANDLE file;
|
||||
__int64 cur;
|
||||
|
||||
file = (HANDLE)_get_osfhandle(fd);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cur = _lseeki64(fd, 0, SEEK_CUR);
|
||||
if (cur == -1) return -1;
|
||||
|
||||
if (_lseeki64(fd, (__int64)length, SEEK_SET) == -1) return -1;
|
||||
|
||||
if (!SetEndOfFile(file)) {
|
||||
errno = EINVAL; /* TODO: GetLastError to errno */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_lseeki64(fd, cur, SEEK_SET) == -1) return -1;
|
||||
|
||||
return 0;
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_file_truncate(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
int fd;
|
||||
int64_t length;
|
||||
mrb_value lenv;
|
||||
|
||||
fd = mrb_io_fileno(mrb, self);
|
||||
mrb_get_args(mrb, "o", &lenv);
|
||||
switch (mrb_type(lenv)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
{
|
||||
mrb_float lenf = mrb_float(lenv);
|
||||
if (lenf > INT64_MAX) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "length too large");
|
||||
}
|
||||
length = (int64_t)lenf;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case MRB_TT_FIXNUM:
|
||||
default:
|
||||
{
|
||||
mrb_int leni = mrb_int(mrb, lenv);
|
||||
length = (int64_t)leni;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (mrb_ftruncate(fd, length) != 0) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
|
||||
}
|
||||
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_file_s_symlink(mrb_state *mrb, mrb_value klass)
|
||||
{
|
||||
@@ -474,7 +614,7 @@ mrb_init_file(mrb_state *mrb)
|
||||
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, "umask", mrb_file_s_umask, MRB_ARGS_OPT(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));
|
||||
@@ -490,6 +630,8 @@ mrb_init_file(mrb_state *mrb)
|
||||
|
||||
mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, file, "mtime", mrb_file_mtime, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, file, "size", mrb_file_size, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, file, "truncate", mrb_file_truncate, MRB_ARGS_REQ(1));
|
||||
|
||||
cnst = mrb_define_module_under(mrb, file, "Constants");
|
||||
mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH));
|
||||
@@ -505,4 +647,22 @@ mrb_init_file(mrb_state *mrb)
|
||||
#endif
|
||||
mrb_define_const(mrb, cnst, "NULL", mrb_str_new_cstr(mrb, NULL_FILE));
|
||||
|
||||
mrb_define_const(mrb, cnst, "RDONLY", mrb_fixnum_value(MRB_O_RDONLY));
|
||||
mrb_define_const(mrb, cnst, "WRONLY", mrb_fixnum_value(MRB_O_WRONLY));
|
||||
mrb_define_const(mrb, cnst, "RDWR", mrb_fixnum_value(MRB_O_RDWR));
|
||||
mrb_define_const(mrb, cnst, "APPEND", mrb_fixnum_value(MRB_O_APPEND));
|
||||
mrb_define_const(mrb, cnst, "CREAT", mrb_fixnum_value(MRB_O_CREAT));
|
||||
mrb_define_const(mrb, cnst, "EXCL", mrb_fixnum_value(MRB_O_EXCL));
|
||||
mrb_define_const(mrb, cnst, "TRUNC", mrb_fixnum_value(MRB_O_TRUNC));
|
||||
mrb_define_const(mrb, cnst, "NONBLOCK", mrb_fixnum_value(MRB_O_NONBLOCK));
|
||||
mrb_define_const(mrb, cnst, "NOCTTY", mrb_fixnum_value(MRB_O_NOCTTY));
|
||||
mrb_define_const(mrb, cnst, "BINARY", mrb_fixnum_value(MRB_O_BINARY));
|
||||
mrb_define_const(mrb, cnst, "SHARE_DELETE", mrb_fixnum_value(MRB_O_SHARE_DELETE));
|
||||
mrb_define_const(mrb, cnst, "SYNC", mrb_fixnum_value(MRB_O_SYNC));
|
||||
mrb_define_const(mrb, cnst, "DSYNC", mrb_fixnum_value(MRB_O_DSYNC));
|
||||
mrb_define_const(mrb, cnst, "RSYNC", mrb_fixnum_value(MRB_O_RSYNC));
|
||||
mrb_define_const(mrb, cnst, "NOFOLLOW", mrb_fixnum_value(MRB_O_NOFOLLOW));
|
||||
mrb_define_const(mrb, cnst, "NOATIME", mrb_fixnum_value(MRB_O_NOATIME));
|
||||
mrb_define_const(mrb, cnst, "DIRECT", mrb_fixnum_value(MRB_O_DIRECT));
|
||||
mrb_define_const(mrb, cnst, "TMPFILE", mrb_fixnum_value(MRB_O_TMPFILE));
|
||||
}
|
||||
|
||||
@@ -7,12 +7,7 @@
|
||||
#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>
|
||||
@@ -33,7 +28,6 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
+301
-134
@@ -10,12 +10,7 @@
|
||||
#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>
|
||||
@@ -36,14 +31,21 @@
|
||||
typedef long ftime_t;
|
||||
typedef long fsuseconds_t;
|
||||
typedef int fmode_t;
|
||||
typedef int mrb_io_read_write_size;
|
||||
|
||||
#ifndef O_TMPFILE
|
||||
#define O_TMPFILE O_TEMPORARY
|
||||
#endif
|
||||
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
typedef size_t fsize_t;
|
||||
typedef time_t ftime_t;
|
||||
typedef suseconds_t fsuseconds_t;
|
||||
typedef mode_t fmode_t;
|
||||
typedef ssize_t mrb_io_read_write_size;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -53,9 +55,14 @@ typedef mrb_int pid_t;
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define OPEN_ACCESS_MODE_FLAGS (O_RDONLY | O_WRONLY | O_RDWR)
|
||||
#define OPEN_RDONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDONLY))
|
||||
#define OPEN_WRONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_WRONLY))
|
||||
#define OPEN_RDWR_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDWR))
|
||||
#define OPEN_READABLE_P(f) ((mrb_bool)(OPEN_RDONLY_P(f) || OPEN_RDWR_P(f)))
|
||||
#define OPEN_WRITABLE_P(f) ((mrb_bool)(OPEN_WRONLY_P(f) || OPEN_RDWR_P(f)))
|
||||
|
||||
static void mrb_io_free(mrb_state *mrb, void *ptr);
|
||||
struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
|
||||
@@ -63,17 +70,9 @@ struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
|
||||
|
||||
static struct mrb_io *io_get_open_fptr(mrb_state *mrb, mrb_value self);
|
||||
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 int mrb_io_mode_to_flags(mrb_state *mrb, mrb_value mode);
|
||||
static void fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet);
|
||||
|
||||
#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 struct mrb_io *
|
||||
io_get_open_fptr(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -113,30 +112,33 @@ io_set_process_status(mrb_state *mrb, pid_t pid, int status)
|
||||
static int
|
||||
mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
|
||||
{
|
||||
int flags = 0;
|
||||
int flags;
|
||||
const char *m = mode;
|
||||
|
||||
switch (*m++) {
|
||||
case 'r':
|
||||
flags |= FMODE_READABLE;
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
case 'w':
|
||||
flags |= FMODE_WRITABLE | FMODE_CREATE | FMODE_TRUNC;
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
break;
|
||||
case 'a':
|
||||
flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
|
||||
flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||
break;
|
||||
default:
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode);
|
||||
flags = 0; /* not reached */
|
||||
}
|
||||
|
||||
while (*m) {
|
||||
switch (*m++) {
|
||||
case 'b':
|
||||
flags |= FMODE_BINMODE;
|
||||
#ifdef O_BINARY
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
break;
|
||||
case '+':
|
||||
flags |= FMODE_READWRITE;
|
||||
flags = (flags & ~OPEN_ACCESS_MODE_FLAGS) | O_RDWR;
|
||||
break;
|
||||
case ':':
|
||||
/* XXX: PASSTHROUGH*/
|
||||
@@ -149,38 +151,72 @@ mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
|
||||
}
|
||||
|
||||
static int
|
||||
mrb_io_flags_to_modenum(mrb_state *mrb, int flags)
|
||||
mrb_io_mode_to_flags(mrb_state *mrb, mrb_value mode)
|
||||
{
|
||||
int modenum = 0;
|
||||
if (mrb_nil_p(mode)) {
|
||||
return mrb_io_modestr_to_flags(mrb, "r");
|
||||
}
|
||||
else if (mrb_string_p(mode)) {
|
||||
return mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
}
|
||||
else {
|
||||
int flags = 0;
|
||||
mrb_int flags0 = mrb_int(mrb, mode);
|
||||
|
||||
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;
|
||||
}
|
||||
switch (flags0 & MRB_O_ACCMODE) {
|
||||
case MRB_O_RDONLY:
|
||||
flags |= O_RDONLY;
|
||||
break;
|
||||
case MRB_O_WRONLY:
|
||||
flags |= O_WRONLY;
|
||||
break;
|
||||
case MRB_O_RDWR:
|
||||
flags |= O_RDWR;
|
||||
break;
|
||||
default:
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %v", mode);
|
||||
}
|
||||
|
||||
if (flags & FMODE_APPEND) {
|
||||
modenum |= O_APPEND;
|
||||
}
|
||||
if (flags & FMODE_TRUNC) {
|
||||
modenum |= O_TRUNC;
|
||||
}
|
||||
if (flags & FMODE_CREATE) {
|
||||
modenum |= O_CREAT;
|
||||
}
|
||||
if (flags0 & MRB_O_APPEND) flags |= O_APPEND;
|
||||
if (flags0 & MRB_O_CREAT) flags |= O_CREAT;
|
||||
if (flags0 & MRB_O_EXCL) flags |= O_EXCL;
|
||||
if (flags0 & MRB_O_TRUNC) flags |= O_TRUNC;
|
||||
#ifdef O_NONBLOCK
|
||||
if (flags0 & MRB_O_NONBLOCK) flags |= O_NONBLOCK;
|
||||
#endif
|
||||
#ifdef O_NOCTTY
|
||||
if (flags0 & MRB_O_NOCTTY) flags |= O_NOCTTY;
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
if (flags & FMODE_BINMODE) {
|
||||
modenum |= O_BINARY;
|
||||
}
|
||||
if (flags0 & MRB_O_BINARY) flags |= O_BINARY;
|
||||
#endif
|
||||
#ifdef O_SHARE_DELETE
|
||||
if (flags0 & MRB_O_SHARE_DELETE) flags |= O_SHARE_DELETE;
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
if (flags0 & MRB_O_SYNC) flags |= O_SYNC;
|
||||
#endif
|
||||
#ifdef O_DSYNC
|
||||
if (flags0 & MRB_O_DSYNC) flags |= O_DSYNC;
|
||||
#endif
|
||||
#ifdef O_RSYNC
|
||||
if (flags0 & MRB_O_RSYNC) flags |= O_RSYNC;
|
||||
#endif
|
||||
#ifdef O_NOFOLLOW
|
||||
if (flags0 & MRB_O_NOFOLLOW) flags |= O_NOFOLLOW;
|
||||
#endif
|
||||
#ifdef O_NOATIME
|
||||
if (flags0 & MRB_O_NOATIME) flags |= O_NOATIME;
|
||||
#endif
|
||||
#ifdef O_DIRECT
|
||||
if (flags0 & MRB_O_DIRECT) flags |= O_DIRECT;
|
||||
#endif
|
||||
#ifdef O_TMPFILE
|
||||
if (flags0 & MRB_O_TMPFILE) flags |= O_TMPFILE;
|
||||
#endif
|
||||
|
||||
return modenum;
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -284,16 +320,17 @@ mrb_io_alloc(mrb_state *mrb)
|
||||
#endif
|
||||
|
||||
static int
|
||||
option_to_fd(mrb_state *mrb, mrb_value obj, const char *key)
|
||||
option_to_fd(mrb_state *mrb, mrb_value hash, const char *key)
|
||||
{
|
||||
mrb_value opt = mrb_funcall(mrb, obj, "[]", 1, mrb_symbol_value(mrb_intern_static(mrb, key, strlen(key))));
|
||||
if (mrb_nil_p(opt)) {
|
||||
return -1;
|
||||
}
|
||||
mrb_value opt;
|
||||
|
||||
if (!mrb_hash_p(hash)) return -1;
|
||||
opt = mrb_hash_fetch(mrb, hash, mrb_symbol_value(mrb_intern_static(mrb, key, strlen(key))), mrb_nil_value());
|
||||
if (mrb_nil_p(opt)) return -1;
|
||||
|
||||
switch (mrb_type(opt)) {
|
||||
case MRB_TT_DATA: /* IO */
|
||||
return (int)mrb_fixnum(mrb_io_fileno(mrb, opt));
|
||||
return mrb_io_fileno(mrb, opt);
|
||||
case MRB_TT_FIXNUM:
|
||||
return (int)mrb_fixnum(opt);
|
||||
default:
|
||||
@@ -329,11 +366,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
ofd[0] = INVALID_HANDLE_VALUE;
|
||||
ofd[1] = INVALID_HANDLE_VALUE;
|
||||
|
||||
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
|
||||
mrb_get_args(mrb, "S|oH", &cmd, &mode, &opt);
|
||||
io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
|
||||
|
||||
pname = RSTRING_CSTR(mrb, cmd);
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
flags = mrb_io_mode_to_flags(mrb, mode);
|
||||
|
||||
doexec = (strcmp("-", pname) != 0);
|
||||
opt_in = option_to_fd(mrb, opt, "in");
|
||||
@@ -344,14 +381,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
if (flags & FMODE_READABLE) {
|
||||
if (OPEN_READABLE_P(flags)) {
|
||||
if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
|
||||
|| !SetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)) {
|
||||
mrb_sys_fail(mrb, "pipe");
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FMODE_WRITABLE) {
|
||||
if (OPEN_WRITABLE_P(flags)) {
|
||||
if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
|
||||
|| !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)) {
|
||||
mrb_sys_fail(mrb, "pipe");
|
||||
@@ -365,11 +402,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
si.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
if (flags & FMODE_READABLE) {
|
||||
if (OPEN_READABLE_P(flags)) {
|
||||
si.hStdOutput = ofd[1];
|
||||
si.hStdError = ofd[1];
|
||||
}
|
||||
if (flags & FMODE_WRITABLE) {
|
||||
if (OPEN_WRITABLE_P(flags)) {
|
||||
si.hStdInput = ifd[0];
|
||||
}
|
||||
if (!CreateProcess(
|
||||
@@ -393,8 +430,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
fptr->fd = _open_osfhandle((intptr_t)ofd[0], 0);
|
||||
fptr->fd2 = _open_osfhandle((intptr_t)ifd[1], 0);
|
||||
fptr->pid = pid;
|
||||
fptr->readable = ((flags & FMODE_READABLE) != 0);
|
||||
fptr->writable = ((flags & FMODE_WRITABLE) != 0);
|
||||
fptr->readable = OPEN_READABLE_P(flags);
|
||||
fptr->writable = OPEN_WRITABLE_P(flags);
|
||||
fptr->sync = 0;
|
||||
|
||||
DATA_TYPE(io) = &mrb_io_type;
|
||||
@@ -425,18 +462,18 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
int saved_errno;
|
||||
int opt_in, opt_out, opt_err;
|
||||
|
||||
mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
|
||||
mrb_get_args(mrb, "S|oH", &cmd, &mode, &opt);
|
||||
io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
|
||||
|
||||
pname = RSTRING_CSTR(mrb, cmd);
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
flags = mrb_io_mode_to_flags(mrb, mode);
|
||||
|
||||
doexec = (strcmp("-", pname) != 0);
|
||||
opt_in = option_to_fd(mrb, opt, "in");
|
||||
opt_out = option_to_fd(mrb, opt, "out");
|
||||
opt_err = option_to_fd(mrb, opt, "err");
|
||||
|
||||
if (flags & FMODE_READABLE) {
|
||||
if (OPEN_READABLE_P(flags)) {
|
||||
if (pipe(pr) == -1) {
|
||||
mrb_sys_fail(mrb, "pipe");
|
||||
}
|
||||
@@ -444,7 +481,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
mrb_fd_cloexec(mrb, pr[1]);
|
||||
}
|
||||
|
||||
if (flags & FMODE_WRITABLE) {
|
||||
if (OPEN_WRITABLE_P(flags)) {
|
||||
if (pipe(pw) == -1) {
|
||||
if (pr[0] != -1) close(pr[0]);
|
||||
if (pr[1] != -1) close(pr[1]);
|
||||
@@ -473,14 +510,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
if (opt_err != -1) {
|
||||
dup2(opt_err, 2);
|
||||
}
|
||||
if (flags & FMODE_READABLE) {
|
||||
if (OPEN_READABLE_P(flags)) {
|
||||
close(pr[0]);
|
||||
if (pr[1] != 1) {
|
||||
dup2(pr[1], 1);
|
||||
close(pr[1]);
|
||||
}
|
||||
}
|
||||
if (flags & FMODE_WRITABLE) {
|
||||
if (OPEN_WRITABLE_P(flags)) {
|
||||
close(pw[1]);
|
||||
if (pw[0] != 0) {
|
||||
dup2(pw[0], 0);
|
||||
@@ -499,12 +536,12 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
break;
|
||||
|
||||
default: /* parent */
|
||||
if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) {
|
||||
if (OPEN_RDWR_P(flags)) {
|
||||
close(pr[1]);
|
||||
fd = pr[0];
|
||||
close(pw[0]);
|
||||
write_fd = pw[1];
|
||||
} else if (flags & FMODE_READABLE) {
|
||||
} else if (OPEN_RDONLY_P(flags)) {
|
||||
close(pr[1]);
|
||||
fd = pr[0];
|
||||
} else {
|
||||
@@ -518,8 +555,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
fptr->fd = fd;
|
||||
fptr->fd2 = write_fd;
|
||||
fptr->pid = pid;
|
||||
fptr->readable = ((flags & FMODE_READABLE) != 0);
|
||||
fptr->writable = ((flags & FMODE_WRITABLE) != 0);
|
||||
fptr->readable = OPEN_READABLE_P(flags);
|
||||
fptr->writable = OPEN_WRITABLE_P(flags);
|
||||
fptr->sync = 0;
|
||||
|
||||
DATA_TYPE(io) = &mrb_io_type;
|
||||
@@ -529,11 +566,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
|
||||
|
||||
case -1: /* error */
|
||||
saved_errno = errno;
|
||||
if (flags & FMODE_READABLE) {
|
||||
if (OPEN_READABLE_P(flags)) {
|
||||
close(pr[0]);
|
||||
close(pr[1]);
|
||||
}
|
||||
if (flags & FMODE_WRITABLE) {
|
||||
if (OPEN_WRITABLE_P(flags)) {
|
||||
close(pw[0]);
|
||||
close(pw[1]);
|
||||
}
|
||||
@@ -618,7 +655,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
|
||||
mode = opt = mrb_nil_value();
|
||||
|
||||
mrb_get_args(mrb, "i|So", &fd, &mode, &opt);
|
||||
mrb_get_args(mrb, "i|oo", &fd, &mode, &opt);
|
||||
if (mrb_nil_p(mode)) {
|
||||
mode = mrb_str_new_cstr(mrb, "r");
|
||||
}
|
||||
@@ -626,7 +663,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
opt = mrb_hash_new(mrb);
|
||||
}
|
||||
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
flags = mrb_io_mode_to_flags(mrb, mode);
|
||||
|
||||
mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, ""));
|
||||
|
||||
@@ -641,8 +678,8 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
|
||||
DATA_PTR(io) = fptr;
|
||||
|
||||
fptr->fd = (int)fd;
|
||||
fptr->readable = ((flags & FMODE_READABLE) != 0);
|
||||
fptr->writable = ((flags & FMODE_WRITABLE) != 0);
|
||||
fptr->readable = OPEN_READABLE_P(flags);
|
||||
fptr->writable = OPEN_WRITABLE_P(flags);
|
||||
fptr->sync = 0;
|
||||
return io;
|
||||
}
|
||||
@@ -797,32 +834,48 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
|
||||
mrb_value mode = mrb_nil_value();
|
||||
mrb_int fd, perm = -1;
|
||||
const char *pat;
|
||||
int flags, modenum;
|
||||
int flags;
|
||||
|
||||
mrb_get_args(mrb, "S|Si", &path, &mode, &perm);
|
||||
if (mrb_nil_p(mode)) {
|
||||
mode = mrb_str_new_cstr(mrb, "r");
|
||||
}
|
||||
mrb_get_args(mrb, "S|oi", &path, &mode, &perm);
|
||||
if (perm < 0) {
|
||||
perm = 0666;
|
||||
}
|
||||
|
||||
pat = RSTRING_CSTR(mrb, path);
|
||||
flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
|
||||
modenum = mrb_io_flags_to_modenum(mrb, flags);
|
||||
fd = mrb_cloexec_open(mrb, pat, modenum, perm);
|
||||
flags = mrb_io_mode_to_flags(mrb, mode);
|
||||
fd = mrb_cloexec_open(mrb, pat, flags, perm);
|
||||
return mrb_fixnum_value(fd);
|
||||
}
|
||||
|
||||
static mrb_value mrb_io_sysread_common(mrb_state *mrb,
|
||||
mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t),
|
||||
mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset);
|
||||
|
||||
static mrb_io_read_write_size
|
||||
mrb_sysread_dummy(int fd, void *buf, fsize_t nbytes, off_t offset)
|
||||
{
|
||||
return (mrb_io_read_write_size)read(fd, buf, nbytes);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return mrb_io_sysread_common(mrb, mrb_sysread_dummy, io, buf, maxlen, 0);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_sysread_common(mrb_state *mrb,
|
||||
mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t),
|
||||
mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
int ret;
|
||||
|
||||
if (maxlen < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative expanding string size");
|
||||
}
|
||||
@@ -836,7 +889,8 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
|
||||
|
||||
if (RSTRING_LEN(buf) != maxlen) {
|
||||
buf = mrb_str_resize(mrb, buf, maxlen);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mrb_str_modify(mrb, RSTRING(buf));
|
||||
}
|
||||
|
||||
@@ -844,25 +898,16 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
|
||||
if (!fptr->readable) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
|
||||
}
|
||||
ret = read(fptr->fd, RSTRING_PTR(buf), (fsize_t)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;
|
||||
ret = readfunc(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen, offset);
|
||||
if (ret < 0) {
|
||||
mrb_sys_fail(mrb, "sysread failed");
|
||||
}
|
||||
if (RSTRING_LEN(buf) != ret) {
|
||||
buf = mrb_str_resize(mrb, buf, ret);
|
||||
}
|
||||
if (ret == 0 && maxlen > 0) {
|
||||
mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -894,11 +939,12 @@ mrb_io_sysseek(mrb_state *mrb, mrb_value io)
|
||||
}
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
static mrb_value
|
||||
mrb_io_syswrite_common(mrb_state *mrb,
|
||||
mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t),
|
||||
mrb_value io, mrb_value buf, off_t offset)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
mrb_value str, buf;
|
||||
int fd, length;
|
||||
|
||||
fptr = io_get_open_fptr(mrb, io);
|
||||
@@ -906,19 +952,12 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
mrb_raise(mrb, E_IO_ERROR, "not opened for writing");
|
||||
}
|
||||
|
||||
mrb_get_args(mrb, "S", &str);
|
||||
if (!mrb_string_p(str)) {
|
||||
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), (fsize_t)RSTRING_LEN(buf));
|
||||
length = writefunc(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf), offset);
|
||||
if (length == -1) {
|
||||
mrb_sys_fail(mrb, 0);
|
||||
}
|
||||
@@ -926,6 +965,22 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
return mrb_fixnum_value(length);
|
||||
}
|
||||
|
||||
static mrb_io_read_write_size
|
||||
mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset)
|
||||
{
|
||||
return (mrb_io_read_write_size)write(fd, buf, nbytes);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_io_syswrite(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value buf;
|
||||
|
||||
mrb_get_args(mrb, "S", &buf);
|
||||
|
||||
return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
mrb_io_close(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -1063,7 +1118,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
|
||||
if (argc < 1 || argc > 4) {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 1..4)", argc);
|
||||
mrb_argnum_error(mrb, argc, 1, 4);
|
||||
}
|
||||
|
||||
timeout = mrb_nil_value();
|
||||
@@ -1206,12 +1261,19 @@ retry:
|
||||
return result;
|
||||
}
|
||||
|
||||
mrb_value
|
||||
int
|
||||
mrb_io_fileno(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
struct mrb_io *fptr;
|
||||
fptr = io_get_open_fptr(mrb, io);
|
||||
return mrb_fixnum_value(fptr->fd);
|
||||
return fptr->fd;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_fileno_m(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
int fd = mrb_io_fileno(mrb, io);
|
||||
return mrb_fixnum_value(fd);
|
||||
}
|
||||
|
||||
mrb_value
|
||||
@@ -1294,15 +1356,70 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
|
||||
return mrb_bool_value(fptr->sync);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
io_bufread(mrb_state *mrb, mrb_value self)
|
||||
#ifndef MRB_WITH_IO_PREAD_PWRITE
|
||||
# define mrb_io_pread mrb_notimplement_m
|
||||
# define mrb_io_pwrite mrb_notimplement_m
|
||||
#else
|
||||
static off_t
|
||||
value2off(mrb_state *mrb, mrb_value offv)
|
||||
{
|
||||
mrb_value str, str2;
|
||||
mrb_int len, newlen;
|
||||
switch (mrb_type(offv)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
{
|
||||
mrb_float tmp = mrb_float(offv);
|
||||
if (tmp < INT64_MIN || tmp > INT64_MAX) {
|
||||
/* fall through to use convert by `mrb_int()` (and raise error if out of range) */
|
||||
} else {
|
||||
return (off_t)tmp;
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
#endif /* MRB_WITHOUT_FLOAT */
|
||||
default:
|
||||
return (off_t)mrb_int(mrb, offv);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* pread(maxlen, offset, outbuf = "") -> outbuf
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_io_pread(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value buf = mrb_nil_value();
|
||||
mrb_value off;
|
||||
mrb_int maxlen;
|
||||
|
||||
mrb_get_args(mrb, "io|S!", &maxlen, &off, &buf);
|
||||
|
||||
return mrb_io_sysread_common(mrb, pread, io, buf, maxlen, value2off(mrb, off));
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* pwrite(buffer, offset) -> wrote_bytes
|
||||
*/
|
||||
static mrb_value
|
||||
mrb_io_pwrite(mrb_state *mrb, mrb_value io)
|
||||
{
|
||||
mrb_value buf, off;
|
||||
|
||||
mrb_get_args(mrb, "So", &buf, &off);
|
||||
|
||||
return mrb_io_syswrite_common(mrb, pwrite, io, buf, value2off(mrb, off));
|
||||
}
|
||||
#endif /* MRB_WITH_IO_PREAD_PWRITE */
|
||||
|
||||
static mrb_value
|
||||
io_bufread(mrb_state *mrb, mrb_value str, mrb_int len)
|
||||
{
|
||||
mrb_value str2;
|
||||
mrb_int newlen;
|
||||
struct RString *s;
|
||||
char *p;
|
||||
|
||||
mrb_get_args(mrb, "Si", &str, &len);
|
||||
s = RSTRING(str);
|
||||
mrb_str_modify(mrb, s);
|
||||
p = RSTR_PTR(s);
|
||||
@@ -1315,6 +1432,53 @@ io_bufread(mrb_state *mrb, mrb_value self)
|
||||
return str2;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_bufread(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value str;
|
||||
mrb_int len;
|
||||
|
||||
mrb_get_args(mrb, "Si", &str, &len);
|
||||
return io_bufread(mrb, str, len);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_io_readchar(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value buf;
|
||||
mrb_int len = 1;
|
||||
#ifdef MRB_UTF8_STRING
|
||||
unsigned char c;
|
||||
#endif
|
||||
|
||||
mrb_get_args(mrb, "S", &buf);
|
||||
mrb_assert(RSTRING_PTR(buf) > 0);
|
||||
mrb_str_modify(mrb, RSTRING(buf));
|
||||
#ifdef MRB_UTF8_STRING
|
||||
c = RSTRING_PTR(buf)[0];
|
||||
if (c & 0x80) {
|
||||
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
|
||||
if (len == 1 && RSTRING_LEN(buf) < 4) { /* partial UTF-8 */
|
||||
mrb_int blen = RSTRING_LEN(buf);
|
||||
ssize_t n;
|
||||
|
||||
struct mrb_io *fptr = (struct mrb_io*)io_get_open_fptr(mrb, self);
|
||||
|
||||
if (!fptr->readable) {
|
||||
mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
|
||||
}
|
||||
/* refill the buffer */
|
||||
mrb_str_resize(mrb, buf, 4096);
|
||||
n = read(fptr->fd, RSTRING_PTR(buf)+blen, 4096-blen);
|
||||
if (n < 0) mrb_sys_fail(mrb, "sysread failed");
|
||||
mrb_str_resize(mrb, buf, blen+n);
|
||||
}
|
||||
len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
|
||||
}
|
||||
#endif
|
||||
return io_bufread(mrb, buf, len);
|
||||
}
|
||||
|
||||
void
|
||||
mrb_init_io(mrb_state *mrb)
|
||||
{
|
||||
@@ -1324,23 +1488,23 @@ mrb_init_io(mrb_state *mrb)
|
||||
MRB_SET_INSTANCE_TT(io, MRB_TT_DATA);
|
||||
|
||||
mrb_include_module(mrb, io, mrb_module_get(mrb, "Enumerable")); /* 15.2.20.3 */
|
||||
mrb_define_class_method(mrb, io, "_popen", mrb_io_s_popen, MRB_ARGS_ANY());
|
||||
mrb_define_class_method(mrb, io, "_popen", mrb_io_s_popen, MRB_ARGS_ARG(1,2));
|
||||
mrb_define_class_method(mrb, io, "_sysclose", mrb_io_s_sysclose, MRB_ARGS_REQ(1));
|
||||
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_class_method(mrb, io, "for_fd", mrb_io_s_for_fd, MRB_ARGS_ARG(1,2));
|
||||
mrb_define_class_method(mrb, io, "select", mrb_io_s_select, MRB_ARGS_ARG(1,3));
|
||||
mrb_define_class_method(mrb, io, "sysopen", mrb_io_s_sysopen, MRB_ARGS_ARG(1,2));
|
||||
#if !defined(_WIN32) && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
|
||||
mrb_define_class_method(mrb, io, "_pipe", mrb_io_s_pipe, MRB_ARGS_NONE());
|
||||
#endif
|
||||
|
||||
mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ANY()); /* 15.2.20.5.21 (x)*/
|
||||
mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ARG(1,2)); /* 15.2.20.5.21 (x)*/
|
||||
mrb_define_method(mrb, io, "initialize_copy", mrb_io_initialize_copy, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, io, "_check_readable", mrb_io_check_readable, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, io, "isatty", mrb_io_isatty, MRB_ARGS_NONE());
|
||||
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, "sysread", mrb_io_sysread, MRB_ARGS_ARG(1,1));
|
||||
mrb_define_method(mrb, io, "sysseek", mrb_io_sysseek, MRB_ARGS_ARG(1,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_write", mrb_io_close_write, MRB_ARGS_NONE());
|
||||
@@ -1348,7 +1512,10 @@ mrb_init_io(mrb_state *mrb)
|
||||
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_define_method(mrb, io, "fileno", mrb_io_fileno_m, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, io, "pread", mrb_io_pread, MRB_ARGS_ANY()); /* ruby 2.5 feature */
|
||||
mrb_define_method(mrb, io, "pwrite", mrb_io_pwrite, MRB_ARGS_ANY()); /* ruby 2.5 feature */
|
||||
|
||||
mrb_define_class_method(mrb, io, "_bufread", io_bufread, MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, io, "_readchar", mrb_io_readchar, MRB_ARGS_REQ(1));
|
||||
mrb_define_class_method(mrb, io, "_bufread", mrb_io_bufread, MRB_ARGS_REQ(2));
|
||||
}
|
||||
|
||||
@@ -80,6 +80,22 @@ assert('File#mtime') do
|
||||
end
|
||||
end
|
||||
|
||||
assert('File#size and File#truncate') do
|
||||
fname = "#{$mrbtest_io_wfname}.resize"
|
||||
begin
|
||||
File.open(fname, 'w') do |f|
|
||||
assert_equal 0, f.size
|
||||
assert_equal 0, f.truncate(100)
|
||||
assert_equal 100, f.size
|
||||
assert_equal 0, f.pos
|
||||
assert_equal 0, f.truncate(5)
|
||||
assert_equal 5, f.size
|
||||
end
|
||||
ensure
|
||||
File.delete(fname)
|
||||
end
|
||||
end
|
||||
|
||||
assert('File.join') do
|
||||
assert_equal "", File.join()
|
||||
assert_equal "a", File.join("a")
|
||||
|
||||
@@ -564,6 +564,34 @@ assert('IO#sysseek') do
|
||||
end
|
||||
end
|
||||
|
||||
assert('IO#pread') do
|
||||
skip "IO#pread is not implemented on this configuration" unless MRubyIOTestUtil::MRB_WITH_IO_PREAD_PWRITE
|
||||
|
||||
IO.open(IO.sysopen($mrbtest_io_rfname, 'r'), 'r') do |io|
|
||||
assert_equal $mrbtest_io_msg.byteslice(5, 8), io.pread(8, 5)
|
||||
assert_equal 0, io.pos
|
||||
assert_equal $mrbtest_io_msg.byteslice(1, 5), io.pread(5, 1)
|
||||
assert_equal 0, io.pos
|
||||
assert_raise(RuntimeError) { io.pread(20, -9) }
|
||||
end
|
||||
end
|
||||
|
||||
assert('IO#pwrite') do
|
||||
skip "IO#pwrite is not implemented on this configuration" unless MRubyIOTestUtil::MRB_WITH_IO_PREAD_PWRITE
|
||||
|
||||
IO.open(IO.sysopen($mrbtest_io_wfname, 'w+'), 'w+') do |io|
|
||||
assert_equal 6, io.pwrite("Warld!", 7)
|
||||
assert_equal 0, io.pos
|
||||
assert_equal 7, io.pwrite("Hello, ", 0)
|
||||
assert_equal 0, io.pos
|
||||
assert_equal "Hello, Warld!", io.read
|
||||
assert_equal 6, io.pwrite("world!", 7)
|
||||
assert_equal 13, io.pos
|
||||
io.pos = 0
|
||||
assert_equal "Hello, world!", io.read
|
||||
end
|
||||
end
|
||||
|
||||
assert('IO.pipe') do
|
||||
begin
|
||||
called = false
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <mruby/common.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
@@ -7,7 +9,6 @@
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <direct.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
@@ -18,7 +19,9 @@ typedef int mode_t;
|
||||
#define open _open
|
||||
#define close _close
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(MRB_MINGW32_VERSION) && MRB_MINGW32_VERSION < 3021) || \
|
||||
(defined(MRB_MINGW64_VERSION) && MRB_MINGW64_VERSION < 4000)
|
||||
#include <sys/stat.h>
|
||||
|
||||
static int
|
||||
@@ -50,10 +53,10 @@ mkdtemp(char *temp)
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mruby.h"
|
||||
@@ -61,6 +64,37 @@ mkdtemp(char *temp)
|
||||
#include "mruby/error.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/variable.h"
|
||||
#include <mruby/ext/io.h>
|
||||
|
||||
int wd_save;
|
||||
int socket_available_p;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
static int mrb_io_socket_available()
|
||||
{
|
||||
int fd, retval = 0;
|
||||
struct sockaddr_un sun0;
|
||||
char socketname[] = "tmp.mruby-io-socket-ok.XXXXXXXX";
|
||||
if (!(fd = mkstemp(socketname))) {
|
||||
goto sock_test_out;
|
||||
}
|
||||
unlink(socketname);
|
||||
close(fd);
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd == -1) {
|
||||
goto sock_test_out;
|
||||
}
|
||||
sun0.sun_family = AF_UNIX;
|
||||
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
|
||||
if (bind(fd, (struct sockaddr *)&sun0, sizeof(sun0)) == 0) {
|
||||
retval = 1;
|
||||
}
|
||||
sock_test_out:
|
||||
unlink(socketname);
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
static mrb_value
|
||||
mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
|
||||
@@ -77,6 +111,14 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
int fd2, fd3;
|
||||
struct sockaddr_un sun0;
|
||||
|
||||
if(!(socket_available_p = mrb_io_socket_available())) {
|
||||
char *tmpdir;
|
||||
wd_save = open(".", O_DIRECTORY);
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir) chdir(tmpdir);
|
||||
else chdir("/tmp");
|
||||
}
|
||||
#endif
|
||||
|
||||
mask = umask(077);
|
||||
@@ -134,7 +176,7 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
|
||||
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);
|
||||
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
|
||||
if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
|
||||
mrb_raisef(mrb, E_RUNTIME_ERROR, "can't bind AF_UNIX socket to %s: %d",
|
||||
sun0.sun_path,
|
||||
@@ -173,28 +215,13 @@ mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
|
||||
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 !defined(_WIN32) && !defined(_WIN64)
|
||||
if (symlink("/usr/bin", "test-bin") == -1) {
|
||||
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
|
||||
if(!socket_available_p) {
|
||||
fchdir(wd_save);
|
||||
close(wd_save);
|
||||
}
|
||||
#endif
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -238,6 +265,12 @@ mrb_io_win_p(mrb_state *mrb, mrb_value klass)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MRB_WITH_IO_PREAD_PWRITE
|
||||
# define MRB_WITH_IO_PREAD_PWRITE_ENABLED TRUE
|
||||
#else
|
||||
# define MRB_WITH_IO_PREAD_PWRITE_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
void
|
||||
mrb_mruby_io_gem_test(mrb_state* mrb)
|
||||
{
|
||||
@@ -245,10 +278,9 @@ mrb_mruby_io_gem_test(mrb_state* mrb)
|
||||
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());
|
||||
|
||||
mrb_define_class_method(mrb, io_test, "mkdtemp", mrb_io_test_mkdtemp, MRB_ARGS_REQ(1));
|
||||
mrb_define_class_method(mrb, io_test, "rmdir", mrb_io_test_rmdir, MRB_ARGS_REQ(1));
|
||||
mrb_define_class_method(mrb, io_test, "win?", mrb_io_win_p, MRB_ARGS_NONE());
|
||||
|
||||
mrb_define_const(mrb, io_test, "MRB_WITH_IO_PREAD_PWRITE", mrb_bool_value(MRB_WITH_IO_PREAD_PWRITE_ENABLED));
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb)
|
||||
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, "Integer", mrb_f_integer, MRB_ARGS_ARG(1,1));
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1));
|
||||
#endif
|
||||
|
||||
@@ -49,24 +49,52 @@ assert('Kernel#__method__') do
|
||||
end
|
||||
|
||||
assert('Kernel#Integer') do
|
||||
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_operator(26, :eql?, Integer("0x1a"))
|
||||
assert_operator(930, :eql?, Integer("0930", 10))
|
||||
assert_operator(7, :eql?, Integer("111", 2))
|
||||
assert_operator(0, :eql?, Integer("0"))
|
||||
assert_operator(0, :eql?, Integer("00000"))
|
||||
assert_operator(123, :eql?, Integer('1_2_3'))
|
||||
assert_operator(123, :eql?, Integer("\t\r\n\f\v 123 \t\r\n\f\v"))
|
||||
assert_raise(TypeError) { Integer(nil) }
|
||||
assert_raise(ArgumentError) { Integer('a') }
|
||||
assert_raise(ArgumentError) { Integer('4a5') }
|
||||
assert_raise(ArgumentError) { Integer('1_2__3') }
|
||||
assert_raise(ArgumentError) { Integer('68_') }
|
||||
assert_raise(ArgumentError) { Integer('68_ ') }
|
||||
assert_raise(ArgumentError) { Integer('_68') }
|
||||
assert_raise(ArgumentError) { Integer(' _68') }
|
||||
assert_raise(ArgumentError) { Integer('6 8') }
|
||||
assert_raise(ArgumentError) { Integer("15\0") }
|
||||
assert_raise(ArgumentError) { Integer("15.0") }
|
||||
skip unless Object.const_defined?(:Float)
|
||||
assert_equal(123, Integer(123.999))
|
||||
assert_operator(123, :eql?, Integer(123.999))
|
||||
end
|
||||
|
||||
assert('Kernel#Float') do
|
||||
skip unless Object.const_defined?(:Float)
|
||||
assert_equal(1.0, Float(1))
|
||||
assert_equal(123.456, Float(123.456))
|
||||
assert_equal(123.456, Float("123.456"))
|
||||
assert_operator(1.0, :eql?, Float(1))
|
||||
assert_operator(123.456, :eql?, Float(123.456))
|
||||
assert_operator(123.456, :eql?, Float("123.456"))
|
||||
assert_operator(123.0, :eql?, Float('1_2_3'))
|
||||
assert_operator(12.34, :eql?, Float('1_2.3_4'))
|
||||
assert_operator(0.9, :eql?, Float('.9'))
|
||||
assert_operator(0.9, :eql?, Float(" \t\r\n\f\v.9 \t\r\n\f\v"))
|
||||
assert_operator(16.0, :eql?, Float("0x10"))
|
||||
assert_raise(TypeError) { Float(nil) }
|
||||
assert_raise(ArgumentError) { Float("1. 5") }
|
||||
assert_raise(ArgumentError) { Float("1.5a") }
|
||||
assert_raise(ArgumentError) { Float("1.5\0") }
|
||||
assert_raise(ArgumentError) { Float('a') }
|
||||
assert_raise(ArgumentError) { Float('4a5') }
|
||||
assert_raise(ArgumentError) { Float('1_2__3') }
|
||||
assert_raise(ArgumentError) { Float('68_') }
|
||||
assert_raise(ArgumentError) { Float('68._7') }
|
||||
assert_raise(ArgumentError) { Float('68.7_') }
|
||||
assert_raise(ArgumentError) { Float('68.7_ ') }
|
||||
assert_raise(ArgumentError) { Float('_68') }
|
||||
assert_raise(ArgumentError) { Float(' _68') }
|
||||
assert_raise(ArgumentError) { Float('1_2.3__4') }
|
||||
end
|
||||
|
||||
assert('Kernel#String') do
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
##
|
||||
# Math Test
|
||||
|
||||
def assert_float_and_int(exp_ary, act_ary)
|
||||
assert('assert_float_and_int') do
|
||||
flo_exp, int_exp, flo_act, int_act = *exp_ary, *act_ary
|
||||
assert_float(flo_exp, flo_act)
|
||||
assert_operator(int_exp, :eql?, int_act)
|
||||
end
|
||||
end
|
||||
|
||||
assert('Math.sin 0') do
|
||||
assert_float(0, Math.sin(0))
|
||||
end
|
||||
@@ -109,12 +117,6 @@ assert('Math.hypot') do
|
||||
assert_float(5.0, Math.hypot(3, 4))
|
||||
end
|
||||
|
||||
assert('Math.frexp 1234') do
|
||||
n = 1234
|
||||
fraction, exponent = Math.frexp(n)
|
||||
assert_float(n, Math.ldexp(fraction, exponent))
|
||||
end
|
||||
|
||||
assert('Math.erf 1') do
|
||||
assert_float(0.842700792949715, Math.erf(1))
|
||||
end
|
||||
@@ -130,3 +132,108 @@ end
|
||||
assert('Math.erfc -1') do
|
||||
assert_float(1.8427007929497148, Math.erfc(-1))
|
||||
end
|
||||
|
||||
assert('Math.acos') do
|
||||
assert_float(0 * Math::PI / 4, Math.acos( 1.0))
|
||||
assert_float(1 * Math::PI / 4, Math.acos( 1.0 / Math.sqrt(2)))
|
||||
assert_float(2 * Math::PI / 4, Math.acos( 0.0))
|
||||
assert_float(4 * Math::PI / 4, Math.acos(-1.0))
|
||||
assert_raise(Math::DomainError) { Math.acos(+1.1) }
|
||||
assert_raise(Math::DomainError) { Math.acos(-1.1) }
|
||||
end
|
||||
|
||||
assert('Math.asin') do
|
||||
assert_float( 0 * Math::PI / 4, Math.asin( 0.0))
|
||||
assert_float( 1 * Math::PI / 4, Math.asin( 1.0 / Math.sqrt(2)))
|
||||
assert_float( 2 * Math::PI / 4, Math.asin( 1.0))
|
||||
assert_float(-2 * Math::PI / 4, Math.asin(-1.0))
|
||||
assert_raise(Math::DomainError) { Math.asin(+1.1) }
|
||||
assert_raise(Math::DomainError) { Math.asin(-1.1) }
|
||||
assert_raise(Math::DomainError) { Math.asin(2.0) }
|
||||
end
|
||||
|
||||
assert('Math.atan') do
|
||||
assert_float( 0 * Math::PI / 4, Math.atan( 0.0))
|
||||
assert_float( 1 * Math::PI / 4, Math.atan( 1.0))
|
||||
assert_float( 2 * Math::PI / 4, Math.atan(1.0 / 0.0))
|
||||
assert_float(-1 * Math::PI / 4, Math.atan(-1.0))
|
||||
end
|
||||
|
||||
assert('Math.cosh') do
|
||||
assert_float(1, Math.cosh(0))
|
||||
assert_float((Math::E ** 1 + Math::E ** -1) / 2, Math.cosh(1))
|
||||
assert_float((Math::E ** 2 + Math::E ** -2) / 2, Math.cosh(2))
|
||||
end
|
||||
|
||||
assert('Math.sinh') do
|
||||
assert_float(0, Math.sinh(0))
|
||||
assert_float((Math::E ** 1 - Math::E ** -1) / 2, Math.sinh(1))
|
||||
assert_float((Math::E ** 2 - Math::E ** -2) / 2, Math.sinh(2))
|
||||
end
|
||||
|
||||
assert('Math.tanh') do
|
||||
assert_float(Math.sinh(0) / Math.cosh(0), Math.tanh(0))
|
||||
assert_float(Math.sinh(1) / Math.cosh(1), Math.tanh(1))
|
||||
assert_float(Math.sinh(2) / Math.cosh(2), Math.tanh(2))
|
||||
assert_float(+1.0, Math.tanh(+1000.0))
|
||||
assert_float(-1.0, Math.tanh(-1000.0))
|
||||
end
|
||||
|
||||
assert('Math.acosh') do
|
||||
assert_float(0, Math.acosh(1))
|
||||
assert_float(1, Math.acosh((Math::E ** 1 + Math::E ** -1) / 2))
|
||||
assert_float(2, Math.acosh((Math::E ** 2 + Math::E ** -2) / 2))
|
||||
assert_raise(Math::DomainError) { Math.acosh(0.9) }
|
||||
assert_raise(Math::DomainError) { Math.acosh(0) }
|
||||
end
|
||||
|
||||
assert('Math.asinh') do
|
||||
assert_float(0, Math.asinh(0))
|
||||
assert_float(1, Math.asinh((Math::E ** 1 - Math::E ** -1) / 2))
|
||||
assert_float(2, Math.asinh((Math::E ** 2 - Math::E ** -2) / 2))
|
||||
end
|
||||
|
||||
assert('Math.atanh') do
|
||||
assert_float(0, Math.atanh(Math.sinh(0) / Math.cosh(0)))
|
||||
assert_float(1, Math.atanh(Math.sinh(1) / Math.cosh(1)))
|
||||
assert_float(2, Math.atanh(Math.sinh(2) / Math.cosh(2)))
|
||||
assert_float(Float::INFINITY, Math.atanh(1))
|
||||
assert_float(-Float::INFINITY, Math.atanh(-1))
|
||||
assert_raise(Math::DomainError) { Math.atanh(+1.1) }
|
||||
assert_raise(Math::DomainError) { Math.atanh(-1.1) }
|
||||
end
|
||||
|
||||
assert('Math.atan2') do
|
||||
assert_float(+0.0, Math.atan2(+0.0, +0.0))
|
||||
assert_float(-0.0, Math.atan2(-0.0, +0.0))
|
||||
assert_float(+Math::PI, Math.atan2(+0.0, -0.0))
|
||||
assert_float(-Math::PI, Math.atan2(-0.0, -0.0))
|
||||
|
||||
inf = Float::INFINITY
|
||||
expected = 3.0 * Math::PI / 4.0
|
||||
assert_float(+expected, Math.atan2(+inf, -inf))
|
||||
assert_float(-expected, Math.atan2(-inf, -inf))
|
||||
expected = Math::PI / 4.0
|
||||
assert_float(+expected, Math.atan2(+inf, +inf))
|
||||
assert_float(-expected, Math.atan2(-inf, +inf))
|
||||
|
||||
assert_float(0, Math.atan2(0, 1))
|
||||
assert_float(Math::PI / 4, Math.atan2(1, 1))
|
||||
assert_float(Math::PI / 2, Math.atan2(1, 0))
|
||||
end
|
||||
|
||||
assert('Math.ldexp') do
|
||||
assert_float(0.0, Math.ldexp(0.0, 0.0))
|
||||
assert_float(0.5, Math.ldexp(0.5, 0.0))
|
||||
assert_float(1.0, Math.ldexp(0.5, 1.0))
|
||||
assert_float(2.0, Math.ldexp(0.5, 2.0))
|
||||
assert_float(3.0, Math.ldexp(0.75, 2.0))
|
||||
end
|
||||
|
||||
assert('Math.frexp') do
|
||||
assert_float_and_int([0.0, 0], Math.frexp(0.0))
|
||||
assert_float_and_int([0.5, 0], Math.frexp(0.5))
|
||||
assert_float_and_int([0.5, 1], Math.frexp(1.0))
|
||||
assert_float_and_int([0.5, 2], Math.frexp(2.0))
|
||||
assert_float_and_int([0.75, 2], Math.frexp(3.0))
|
||||
end
|
||||
|
||||
@@ -139,7 +139,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
|
||||
|
||||
proc = mrb->c->ci[-1].proc;
|
||||
|
||||
if (MRB_PROC_CFUNC_P(proc)) {
|
||||
if (proc == NULL || MRB_PROC_CFUNC_P(proc)) {
|
||||
return mrb_ary_new(mrb);
|
||||
}
|
||||
vars = mrb_hash_new(mrb);
|
||||
@@ -172,7 +172,7 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
|
||||
KHASH_DECLARE(st, mrb_sym, char, FALSE)
|
||||
|
||||
static void
|
||||
method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
|
||||
method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, khash_t(st) *undef)
|
||||
{
|
||||
khint_t i;
|
||||
|
||||
@@ -181,20 +181,28 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
|
||||
for (i=0;i<kh_end(h);i++) {
|
||||
if (kh_exist(h, i)) {
|
||||
mrb_method_t m = kh_value(h, i);
|
||||
if (MRB_METHOD_UNDEF_P(m)) continue;
|
||||
kh_put(st, mrb, set, kh_key(h, i));
|
||||
if (MRB_METHOD_UNDEF_P(m)) {
|
||||
if (undef) {
|
||||
kh_put(st, mrb, undef, kh_key(h, i));
|
||||
}
|
||||
}
|
||||
else if (undef == NULL ||
|
||||
kh_get(st, mrb, undef, kh_key(h, i)) == kh_end(undef)) {
|
||||
kh_put(st, mrb, set, kh_key(h, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
|
||||
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);
|
||||
struct RClass *oldklass;
|
||||
khash_t(st) *set = kh_init(st, mrb);
|
||||
khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
|
||||
|
||||
if (!recur && (klass->flags & MRB_FL_CLASS_IS_PREPENDED)) {
|
||||
MRB_CLASS_ORIGIN(klass);
|
||||
@@ -203,7 +211,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
|
||||
|
||||
oldklass = 0;
|
||||
while (klass && (klass != oldklass)) {
|
||||
method_entry_loop(mrb, klass, set);
|
||||
method_entry_loop(mrb, klass, set, undef);
|
||||
if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
|
||||
(klass->tt == MRB_TT_SCLASS)) {
|
||||
}
|
||||
@@ -221,6 +229,7 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
|
||||
}
|
||||
}
|
||||
kh_destroy(st, mrb, set);
|
||||
if (undef) kh_destroy(st, mrb, undef);
|
||||
|
||||
return ary;
|
||||
}
|
||||
@@ -313,18 +322,19 @@ 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);
|
||||
struct RClass *klass;
|
||||
khash_t(st) *set = kh_init(st, mrb);
|
||||
khash_t(st) *undef = (recur ? kh_init(st, mrb) : NULL);
|
||||
|
||||
klass = mrb_class(mrb, obj);
|
||||
|
||||
if (klass && (klass->tt == MRB_TT_SCLASS)) {
|
||||
method_entry_loop(mrb, klass, set);
|
||||
method_entry_loop(mrb, klass, set, undef);
|
||||
klass = klass->super;
|
||||
}
|
||||
if (recur) {
|
||||
while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
|
||||
method_entry_loop(mrb, klass, set);
|
||||
method_entry_loop(mrb, klass, set, undef);
|
||||
klass = klass->super;
|
||||
}
|
||||
}
|
||||
@@ -336,6 +346,7 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
|
||||
}
|
||||
}
|
||||
kh_destroy(st, mrb, set);
|
||||
if (undef) kh_destroy(st, mrb, undef);
|
||||
|
||||
return ary;
|
||||
}
|
||||
@@ -694,8 +705,8 @@ mrb_mruby_metaprog_gem_init(mrb_state* mrb)
|
||||
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, "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, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */
|
||||
mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_REQ(1)|MRB_ARGS_BLOCK());
|
||||
mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.44 */
|
||||
|
||||
mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_OPT(1)); /* 15.2.2.4.19 */
|
||||
mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
|
||||
|
||||
@@ -49,6 +49,7 @@ There is no dependency on other mrbgems.
|
||||
## License
|
||||
|
||||
Copyright (c) 2012 Internet Initiative Japan Inc.
|
||||
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"),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MRuby::Gem::Specification.new('mruby-pack') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.authors = 'Internet Initiative Japan Inc.'
|
||||
spec.authors = ['Internet Initiative Japan Inc.', 'mruby developers']
|
||||
spec.summary = 'Array#pack and String#unpack method'
|
||||
|
||||
spec.cc.include_paths << "#{build.root}/src"
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
** pack.c - Array#pack, String#unpack
|
||||
*/
|
||||
|
||||
#include "mruby.h"
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error pack/unpack conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include "mruby/error.h"
|
||||
#include "mruby/array.h"
|
||||
#include "mruby/class.h"
|
||||
@@ -13,7 +18,6 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct tmpl {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error print conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <mruby/string.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN32)
|
||||
|
||||
@@ -175,8 +175,8 @@ mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
|
||||
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());
|
||||
mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
|
||||
mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
MRuby::Gem::Specification.new('mruby-sleep') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.authors = 'MATSUMOTO Ryosuke'
|
||||
spec.authors = ['MATSUMOTO Ryosuke', 'mruby developers']
|
||||
spec.version = '0.0.1'
|
||||
end
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
** mrb_sleep - sleep methods for mruby
|
||||
**
|
||||
** Copyright (c) mod_mruby developers 2012-
|
||||
** Copyright (c) mruby developers 2018
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -35,6 +35,7 @@ Date: Tue, 21 May 2013 04:31:30 GMT
|
||||
## License
|
||||
|
||||
Copyright (c) 2013 Internet Initiative Japan Inc.
|
||||
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"),
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
MRuby::Gem::Specification.new('mruby-socket') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.authors = 'Internet Initiative Japan'
|
||||
spec.authors = ['Internet Initiative Japan', 'mruby developers']
|
||||
spec.summary = 'standard socket class'
|
||||
|
||||
spec.cc.include_paths << "#{build.root}/src"
|
||||
#spec.cc.defines << "HAVE_SA_LEN=0"
|
||||
|
||||
# If Windows, use winsock
|
||||
if ( /mswin|mingw|win32/ =~ RUBY_PLATFORM ) then
|
||||
if for_windows?
|
||||
spec.linker.libraries << "wsock32"
|
||||
spec.linker.libraries << "ws2_32"
|
||||
end
|
||||
|
||||
@@ -476,7 +476,7 @@ mrb_basicsocket_setsockopt(mrb_state *mrb, mrb_value self)
|
||||
optname = mrb_fixnum(mrb_funcall(mrb, so, "optname", 0));
|
||||
optval = mrb_funcall(mrb, so, "data", 0);
|
||||
} else {
|
||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%i for 3)", argc);
|
||||
mrb_argnum_error(mrb, argc, 3, 3);
|
||||
}
|
||||
|
||||
s = socket_fd(mrb, self);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mruby.h"
|
||||
@@ -8,7 +7,9 @@
|
||||
|
||||
#include <io.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(MRB_MINGW32_VERSION) && MRB_MINGW32_VERSION < 3021) || \
|
||||
(defined(MRB_MINGW64_VERSION) && MRB_MINGW64_VERSION < 4000)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -18,8 +18,8 @@ mrb_mruby_sprintf_gem_init(mrb_state* mrb)
|
||||
}
|
||||
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());
|
||||
mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_REQ(1)|MRB_ARGS_REST());
|
||||
mrb_define_method(mrb, krn, "format", mrb_f_sprintf, MRB_ARGS_REQ(1)|MRB_ARGS_REST());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -6,8 +6,11 @@
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
#ifdef MRB_DISABLE_STDIO
|
||||
# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/hash.h>
|
||||
|
||||
@@ -174,8 +174,8 @@ mrb_str_concat_m(mrb_state *mrb, mrb_value self)
|
||||
str = int_chr_binary(mrb, str);
|
||||
#endif
|
||||
else
|
||||
str = mrb_ensure_string_type(mrb, str);
|
||||
mrb_str_concat(mrb, self, str);
|
||||
mrb_ensure_string_type(mrb, str);
|
||||
mrb_str_cat_str(mrb, self, str);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user