summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.editorconfig43
-rw-r--r--.github/dependabot.yml10
-rw-r--r--.github/workflows/build.yml42
-rw-r--r--.github/workflows/codeql-analysis.yml4
-rw-r--r--.github/workflows/lint.yml43
-rw-r--r--.github/workflows/oss-fuzz.yml6
-rw-r--r--.github/workflows/spell-checker.yml17
-rw-r--r--build_config/clang-asan.rb2
-rw-r--r--build_config/dreamcast_shelf.rb2
-rw-r--r--build_config/host-f32.rb14
-rw-r--r--doc/guides/compile.md146
-rw-r--r--doc/guides/mrbgems.md112
-rw-r--r--doc/mruby3.md2
-rw-r--r--include/mruby/array.h6
-rw-r--r--include/mruby/dump.h5
-rw-r--r--lib/mruby/build.rb2
-rw-r--r--lib/mruby/build/command.rb7
-rw-r--r--lib/mruby/core_ext.rb4
-rw-r--r--lib/mruby/gem.rb15
-rw-r--r--mrbgems/mruby-bin-debugger/bintest/print.rb4
-rw-r--r--mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c14
-rw-r--r--mrbgems/mruby-catch/mrblib/catch.rb24
-rw-r--r--mrbgems/mruby-catch/src/catch.c128
-rw-r--r--mrbgems/mruby-catch/test/catch.rb23
-rw-r--r--mrbgems/mruby-cmath/mrbgem.rake2
-rw-r--r--mrbgems/mruby-cmath/src/cmath.c7
-rw-r--r--mrbgems/mruby-compiler/core/parse.y3
-rw-r--r--mrbgems/mruby-compiler/core/y.tab.c5
-rw-r--r--mrbgems/mruby-hash-ext/src/hash-ext.c2
-rw-r--r--mrbgems/mruby-math/test/math.rb63
-rw-r--r--mrbgems/mruby-rational/src/rational.c4
-rw-r--r--mrbgems/mruby-sleep/src/sleep.c (renamed from mrbgems/mruby-sleep/src/mrb_sleep.c)0
-rw-r--r--mrbgems/mruby-sprintf/test/sprintf.rb10
-rw-r--r--mrbgems/mruby-struct/mrblib/struct.rb165
-rw-r--r--mrbgems/mruby-test/driver.c4
-rw-r--r--mrbgems/mruby-test/mrbgem.rake6
-rw-r--r--src/array.c9
-rw-r--r--src/dump.c24
-rw-r--r--src/hash.c95
-rw-r--r--src/print.c15
-rw-r--r--src/vm.c2
-rw-r--r--tasks/bin.rake2
-rw-r--r--tasks/libmruby.rake9
-rw-r--r--tasks/mrblib.rake2
-rw-r--r--tasks/test.rake7
-rw-r--r--test/t/hash.rb8
46 files changed, 681 insertions, 438 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..705b1f022
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,43 @@
+# About this file, see:
+# Website: https://editorconfig.org/
+# For Emacs users: https://github.com/editorconfig/editorconfig-emacs
+# For Vim users: https://github.com/editorconfig/editorconfig-vim
+
+root = true
+
+[*]
+indent_style = tab
+indent_size = 8
+tab_width = 8
+end_of_line = lf
+charset = utf-8
+insert_final_newline = true
+
+[{Makefile,Makefile.*,makefile,*.mk}]
+trim_trailing_whitespace = true
+#max_line_length = 80
+
+[*.{c,cc,C,cxx,cpp,h,hh,H,hxx,hpp,inc,y}]
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+#max_line_length = 120
+
+[{*.rb,Rakefile,rakefile,*.rake,*.gemspec,*.gembox}]
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+#max_line_length = 120
+
+[*.bat]
+end_of_line = crlf
+charset = latin1
+#max_line_length = 80
+
+[*.{yaml,yml}]
+indent_style = space
+indent_size = 2
+
+[*.md]
+indent_style = space
+indent_size = 2
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..dac4cac33
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+# Basic set up
+
+version: 2
+updates:
+
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 135e39ca7..435118e37 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -3,18 +3,8 @@ name: Build & Test
on: [push, pull_request]
jobs:
- Check-Skip:
- if: |
- !contains(github.event.head_commit.message, '[ci skip]') &&
- !contains(github.event.head_commit.message, '[skip ci]') &&
- !contains(github.event.head_commit.message, '[skip gha]')
- runs-on: ubuntu-latest
- steps:
- - run: echo not skip
-
- Ubuntu-1604:
- needs: Check-Skip
- runs-on: ubuntu-16.04
+ Ubuntu-1804-gcc:
+ runs-on: ubuntu-18.04
env:
MRUBY_CONFIG: ci/gcc-clang
CC: gcc
@@ -27,11 +17,24 @@ jobs:
- name: Build and test
run: rake -m test:build && rake test:run
- Ubuntu-1804-gcc:
- needs: Check-Skip
+ Ubuntu-1804-clang:
runs-on: ubuntu-18.04
env:
MRUBY_CONFIG: ci/gcc-clang
+ CC: clang
+ steps:
+ - uses: actions/checkout@v2
+ - name: Ruby version
+ run: ruby -v
+ - name: Compiler version
+ run: ${{ env.CC }} --version
+ - name: Build and test
+ run: rake -m test:build && rake test:run
+
+ Ubuntu-2004-gcc:
+ runs-on: ubuntu-20.04
+ env:
+ MRUBY_CONFIG: ci/gcc-clang
CC: gcc
steps:
- uses: actions/checkout@v2
@@ -42,9 +45,8 @@ jobs:
- name: Build and test
run: rake -m test:build && rake test:run
- Ubuntu-1804-clang:
- needs: Check-Skip
- runs-on: ubuntu-18.04
+ Ubuntu-2004-clang:
+ runs-on: ubuntu-20.04
env:
MRUBY_CONFIG: ci/gcc-clang
CC: clang
@@ -58,7 +60,6 @@ jobs:
run: rake -m test:build && rake test:run
macOS:
- needs: Check-Skip
runs-on: macos-latest
env:
MRUBY_CONFIG: ci/gcc-clang
@@ -73,7 +74,6 @@ jobs:
run: rake -m test:build && rake test:run
Windows-MinGW:
- needs: Check-Skip
runs-on: windows-latest
env:
MRUBY_CONFIG: ci/gcc-clang
@@ -88,7 +88,6 @@ jobs:
run: rake -m test:build && rake test:run
Windows-Cygwin:
- needs: Check-Skip
runs-on: windows-latest
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
@@ -100,7 +99,7 @@ jobs:
cache-version: v1
steps:
- uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - uses: actions/[email protected]
with:
path: ${{ env.package-dir }}
key: ${{ runner.os }}-cygwin-${{ env.cache-version }}
@@ -134,7 +133,6 @@ jobs:
run: echo '::set-env name=PATH::C:\windows\System32'
Windows-VC:
- needs: Check-Skip
runs-on: windows-latest
env:
MRUBY_CONFIG: ci/msvc
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 19fb63b35..ea9f9bd8e 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -8,10 +8,6 @@ on:
jobs:
CodeQL-Build:
- if: |
- !contains(github.event.head_commit.message, '[ci skip]') &&
- !contains(github.event.head_commit.message, '[skip ci]') &&
- !contains(github.event.head_commit.message, '[skip gha]')
runs-on: ubuntu-latest
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index ed1682b05..474890010 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -3,13 +3,6 @@ name: โ„๏ธ Lint
on: [pull_request]
jobs:
- yamllint:
- name: ๐Ÿถ YAML
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: ๐Ÿงน YAML Lint
- uses: ibiqlik/action-yamllint@v3
markdownlint:
name: ๐Ÿธ Markdown
runs-on: ubuntu-latest
@@ -21,3 +14,39 @@ jobs:
node-version: '12.x'
- run: npm install -g [email protected]
- run: markdownlint '**/*.md'
+ misspell:
+ name: ๐Ÿฅ› Check Spelling
+ runs-on: ubuntu-latest
+ steps:
+ - name: ๐Ÿ’ Check Out
+ uses: actions/checkout@v2
+ - name: ๐Ÿ… Install
+ run: |
+ wget -O - -q https://git.io/misspell | sh -s -- -b .
+ - name: ๐ŸŒถ๏ธ Misspell
+ run: |
+ git ls-files --empty-directory | xargs ./misspell -error
+ trailing-whitespace:
+ name: ๐Ÿง‹ Trailing whitespace
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: ๐Ÿงน Check for trailing whitespace
+ run: "! git grep -EIn $'[ \t]+$'"
+ yamllint:
+ name: ๐Ÿถ YAML
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-python@v2
+ with:
+ python-version: '3.x' # Version range or exact version of a Python version to use, using SemVer's version range syntax
+ architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install yamllint
+ - name: ๐Ÿงน YAML Lint
+ run: |
+ # return non-zero exit code on warnings
+ yamllint --strict .
diff --git a/.github/workflows/oss-fuzz.yml b/.github/workflows/oss-fuzz.yml
index 8f2b24f17..0fd505624 100644
--- a/.github/workflows/oss-fuzz.yml
+++ b/.github/workflows/oss-fuzz.yml
@@ -2,10 +2,6 @@ name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
- if: |
- !contains(github.event.head_commit.message, '[ci skip]') &&
- !contains(github.event.head_commit.message, '[skip ci]') &&
- !contains(github.event.head_commit.message, '[skip gha]')
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
@@ -20,7 +16,7 @@ jobs:
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
- uses: actions/upload-artifact@v1
+ uses: actions/[email protected]
if: failure()
with:
name: artifacts
diff --git a/.github/workflows/spell-checker.yml b/.github/workflows/spell-checker.yml
deleted file mode 100644
index 7e86e0198..000000000
--- a/.github/workflows/spell-checker.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: ๐Ÿ’Ž Spellchecker
-
-on: [pull_request]
-
-jobs:
- misspell:
- name: ๐Ÿงน Check Spelling
- runs-on: ubuntu-latest
- steps:
- - name: ๐Ÿ’ Check Out
- uses: actions/checkout@v2
- - name: ๐Ÿ… Install
- run: |
- wget -O - -q https://git.io/misspell | sh -s -- -b .
- - name: ๐ŸŒถ๏ธ Misspell
- run: |
- git ls-files --empty-directory | xargs ./misspell -error
diff --git a/build_config/clang-asan.rb b/build_config/clang-asan.rb
index 5ee0d9129..19cc53bf0 100644
--- a/build_config/clang-asan.rb
+++ b/build_config/clang-asan.rb
@@ -1,7 +1,7 @@
MRuby::Build.new do |conf|
conf.toolchain :clang
# include the GEM box
- conf.gembox 'default'
+ conf.gembox 'full-core'
# Turn on `enable_debug` for better debugging
conf.enable_sanitizer "address,undefined"
diff --git a/build_config/dreamcast_shelf.rb b/build_config/dreamcast_shelf.rb
index a92770070..7e7d6a52e 100644
--- a/build_config/dreamcast_shelf.rb
+++ b/build_config/dreamcast_shelf.rb
@@ -20,7 +20,7 @@ MRuby::CrossBuild.new("dreamcast") do |conf|
# C compiler
# Flags were extracted from KallistiOS environment files
conf.cc do |cc|
- cc.command = "#{BIN_PATH}/sh-elf-gcc"
+ 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}"]
diff --git a/build_config/host-f32.rb b/build_config/host-f32.rb
new file mode 100644
index 000000000..a449547ae
--- /dev/null
+++ b/build_config/host-f32.rb
@@ -0,0 +1,14 @@
+MRuby::Build.new do |conf|
+ # load specific toolchain settings
+ toolchain :gcc
+
+ # include the GEM box
+ conf.gembox 'default'
+
+ conf.cc.defines << 'MRB_USE_FLOAT32'
+
+ # Turn on `enable_debug` for better debugging
+ conf.enable_debug
+ conf.enable_test
+ conf.enable_bintest
+end
diff --git a/doc/guides/compile.md b/doc/guides/compile.md
index a8e35b65c..eba0c87ff 100644
--- a/doc/guides/compile.md
+++ b/doc/guides/compile.md
@@ -10,19 +10,20 @@ To compile mruby out of the source code you need the following tools:
* C Compiler (e.g. `gcc` or `clang`)
* Linker (e.g. `gcc` or `clang`)
* Archive utility (e.g. `ar`)
-* Parser generator (`bison`)
-* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
+* Ruby 2.5 or later (e.g. `ruby` or `jruby`)
+
+Optional:
+
+* Git (to update mruby source and integrate mrbgems easier)
+* C++ compiler (to use mrbgems which include `*.cpp`, `*.cxx`, `*.cc`)
+* Bison (to compile `mrbgems/mruby-compiler/core/parse.y`)
+* gperf (to compile `mrbgems/mruby-compiler/core/keywords`)
Note that `bison` bundled with MacOS is too old to compile `mruby`.
Try `brew install bison` and follow the instruction shown to update
the `$PATH` to compile `mruby`. We also encourage to upgrade `ruby`
on MacOS in similar manner.
-Optional:
-
-* git (to update mruby source and integrate mrbgems easier)
-* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
-
## Build
To compile `mruby` with the default build configuration, just invoke `rake`
@@ -32,7 +33,7 @@ line on build, call `rake -v`.
You can specify your own configuration file by the `MRUBY_CONFIG` environment
variable (you can use `CONFIG` for shorthand for `MRUBY_CONFIG`). If the path
-doesn't exist, *build_config/${MRUBY_CONFIG}.rb* is used. The default
+doesn't exist, `build_config/${MRUBY_CONFIG}.rb` is used. The default
configuration is defined in the `build_config/default.rb` file.
Those build configuration files contain the build configuration of mruby, for
@@ -48,7 +49,7 @@ All tools necessary to compile mruby can be set or modified here.
## Build Configuration
-We wish you submit a pull-request to *build_config/**PLATFORM**.rb*, once you
+We wish you submit a pull-request to `build_config/PLATFORM.rb`, once you
created a new configuration for a new platform.
Inside of the configuration file, the following options can be
@@ -228,7 +229,7 @@ end
### Preallocated Symbols
-By far, preallocate symbols are highly compatible with the previous versions, so
+By far, preallocated symbols are highly compatible with the previous versions, so
we expect you won't see any problem with them. But just in case you face any
issue, you can disable preallocated symbols by specifying `conf.disable_presym`.
@@ -279,7 +280,7 @@ conf.build_mrbtest_lib_only
### Bintest
Tests for mrbgem tools using CRuby.
-To have bintests place \*.rb scripts to `bintest/` directory of mrbgems.
+To have bintests place `*.rb` scripts to `bintest/` directory of mrbgems.
See `mruby-bin-*/bintest/*.rb` if you need examples.
If you want a temporary files use `tempfile` module of CRuby instead of `/tmp/`.
@@ -354,7 +355,7 @@ end
```
All configuration options of `MRuby::Build` can also be used in
-`MRuby::CrossBuild`. You can find examples under the *build_config*
+`MRuby::CrossBuild`. You can find examples under the `build_config`
directory.
### Mrbtest in Cross-Compilation
@@ -375,49 +376,42 @@ end
## Build process
-During the build process the directory *build* will be created in the
+During the build process the directory `build` will be created in the
root directory. The structure of this directory will look like this:
+- build
|
+- host
|
+ +- LEGAL <- License description
+ |
+- bin <- Binaries (mirb, mrbc and mruby)
|
+- lib <- Libraries (libmruby.a and libmruby_core.a)
|
- +- mrblib
+ +- mrbc <- Minimal mrbc place
|
- +- src
+ +- mrbgems <- Compilation result from mrbgems
|
- +- test <- mrbtest tool
+ +- mrblib <- Compilation result from mrblib
|
- +- tools
- |
- +- mirb
- |
- +- mrbc
- |
- +- mruby
+ +- src <- Compilation result from C sources
The compilation workflow will look like this:
-* compile all files under *src* (object files will be stored
-in *build/host/src*)
-* generate parser grammar out of *src/parse.y* (generated
-result will be stored in *build/host/src/y.tab.c*)
-* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o*
-* create *build/host/lib/libmruby_core.a* out of all object files (C only)
-* create `build/host/bin/mrbc` by compiling *tools/mrbc/mrbc.c* and
-linking with *build/host/lib/libmruby_core.a*
-* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files
-under *mrblib* with `build/host/bin/mrbc`
-* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
-* create *build/host/lib/libmruby.a* out of all object files (C and Ruby)
-* create `build/host/bin/mruby` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
-linking with *build/host/lib/libmruby.a*
-* create `build/host/bin/mirb` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
-linking with *build/host/lib/libmruby.a*
+* compile minimal `mrbc` from `src` and `mrblib` sources
+ * compile all files under `src` (object files will be stored in `build/host/mrbc/src`)
+ * compile `mruby-compiler` gem
+ * create `build/host/mrbc/lib/libmruby_core.a` out of all object files (C only)
+ * create `build/host/mrbc/bin/mrbc` via `mruby-bin-mrbc` gem
+* compile all files under `src` and store result in `build/host/src`
+* create `build/host/mrblib/mrblib.c` by compiling all `*.rb` files under `mrblib` with `build/host/mrbc/bin/mrbc`
+* compile `build/host/mrblib/mrblib.c` to `build/host/mrblib/mrblib.o`
+* create `build/host/lib/libmruby.a` out of all object files (C and Ruby)
+* compile (normal) mrbgems specified in the configuration file
+* create `build/host/lib/libmruby.a` from object files from gems and `libmruby_core.a`
+* create binary commands according to binary gems (e.g. `mirb` and `mruby`)
+* copy binaries under `build/host/bin` to `bin` directory
```
_____ _____ ______ ____ ____ _____ _____ ____
@@ -428,7 +422,7 @@ linking with *build/host/lib/libmruby.a*
### Cross-Compilation
-In case of a cross-compilation to *i386* the *build* directory structure looks
+In case of a cross-compilation to `i386` the `build` directory structure looks
like this:
+- build
@@ -439,63 +433,41 @@ like this:
| |
| +- lib <- Native Libraries
| |
- | +- mrblib
+ | +- mrbgems
| |
| +- src
- | |
- | +- test <- Native mrbtest tool
- | |
- | +- tools
- | |
- | +- mirb
- | |
- | +- mrbc
- | |
- | +- mruby
+ |
+- i386
|
+- bin <- Cross-compiled Binaries
|
+ +- include <- Header Directory
+ |
+- lib <- Cross-compiled Libraries
|
+ +- mrbgems
+ |
+- mrblib
|
+- src
- |
- +- test <- Cross-compiled mrbtest tool
- |
- +- tools
- |
- +- mirb
- |
- +- mrbc
- |
- +- mruby
An extra directory is created for the target platform. In case you
-compile for *i386* a directory called *i386* is created under the
+compile for `i386` a directory called `i386` is created under the
build directory.
The cross compilation workflow starts in the same way as the normal
-compilation by compiling all *native* libraries and binaries.
-Afterwards the cross compilation process proceeds like this:
-
-* cross-compile all files under *src* (object files will be stored
-in *build/i386/src*)
-* generate parser grammar out of *src/parse.y* (generated
-result will be stored in *build/i386/src/y.tab.c*)
-* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o*
-* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files
-under *mrblib* with the native `build/host/bin/mrbc`
-* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o*
-* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby)
-* create `build/i386/bin/mruby` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and
-linking with *build/i386/lib/libmruby.a*
-* create `build/i386/bin/mirb` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and
-linking with *build/i386/lib/libmruby.a*
-* create *build/i386/lib/libmruby_core.a* out of all object files (C only)
-* create `build/i386/bin/mrbc` by cross-compiling *tools/mrbc/mrbc.c* and
-linking with *build/i386/lib/libmruby_core.a*
+compilation by compiling all *native* libraries and binaries, except
+for we don't have `host/mrbc` directory (`host` directory itself works
+as placeholder for `mrbc`). Afterwards the cross compilation process
+proceeds like this:
+
+* cross-compile all files under `src` and store result in `build/i386/src`
+* create `build/i386/lib/libmruby_core.a` out of C object files
+* create `build/i386/mrblib/mrblib.c` by compiling all `*.rb` files under `mrblib` with native `build/host/bin/mrbc`
+* cross-compile `build/i386/mrblib/mrblib.c` to `build/i386/mrblib/mrblib.o`
+* create `build/i386/lib/libmruby.a` from object files from gems and `libmruby_core.a`
+* create binary commands according to binary gems (e.g. `mirb` and `mruby`)
+* copy binaries under `build/host/bin` to `bin` directory
```
_______________________________________________________________
@@ -526,24 +498,23 @@ feature due to the reason that there are functions (e.g. stdio) which
can't be disabled for the main build.
```ruby
-MRuby::CrossBuild.new('Minimal') do |conf|
+MRuby::CrossBuild.new('minimal') do |conf|
toolchain :gcc
conf.cc.defines = %w(MRB_NO_STDIO)
- conf.bins = []
end
```
-This configuration defines a cross compile build called 'Minimal' which
+This configuration defines a cross compile build called 'minimal' which
is using the GCC and compiles for the host machine. It also disables
-all usages of stdio and doesn't compile any binaries (e.g. mrbc).
+all usages of stdio and doesn't compile any binaries (e.g. `mrbc`).
## Test Environment
mruby's build process includes a test environment. In case you start the testing
of mruby, a native binary called `mrbtest` will be generated and executed.
-This binary contains all test cases which are defined under *test/t*. In case
-of a cross-compilation an additional cross-compiled *mrbtest* binary is
+This binary contains all test cases which are defined under `test/t`. In case
+of a cross-compilation an additional cross-compiled `mrbtest` binary is
generated. You can copy this binary and run on your target system.
## Embedding `mruby` in Your Application
@@ -562,6 +533,7 @@ Usage: mruby-config [switches]
--ldflags-before-libs print flags passed to linker before linked libraries
--libs print linked libraries
--libmruby-path print libmruby path
+ --help print this help
```
For example, when you have a C source file (`c.c`) and try to
diff --git a/doc/guides/mrbgems.md b/doc/guides/mrbgems.md
index 5ad00a5f2..5a6396e97 100644
--- a/doc/guides/mrbgems.md
+++ b/doc/guides/mrbgems.md
@@ -1,12 +1,13 @@
# mrbgems
mrbgems is a library manager to integrate C and Ruby extension in an easy and
-standardised way into mruby.
+standardised way into mruby. Conventionally, each mrbgem name is prefixed by
+`mruby-`, e.g. `mruby-time` for a gem that provides `Time` class functionality.
## Usage
You have to activate mrbgems explicitly in your build configuration. To add
-a GEM, add the following line to your build configuration file, for example:
+a gem, add the following line to your build configuration file, for example:
```ruby
conf.gem '/path/to/your/gem/dir'
@@ -69,7 +70,7 @@ into mruby, in the same format as if you were adding them to the build config
via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are
loaded into mruby via `config.gembox 'boxname'`.
-Below we have created a GemBox containing *mruby-time* and *mrbgems-example*:
+Below we have created a GemBox containing `mruby-time` and `mrbgems-example`:
```ruby
MRuby::GemBox.new do |conf|
@@ -79,10 +80,10 @@ end
```
As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox
-must be saved with a *.gembox* extension inside the *mrbgems* directory to to be
+must be saved with a `.gembox` extension inside the `mrbgems` directory to to be
picked up by mruby.
-To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems*
+To use this example GemBox, we save it as `custom.gembox` inside the `mrbgems`
directory in mruby, and add the following to your build configuration file inside
the build block:
@@ -90,8 +91,8 @@ the build block:
conf.gembox 'custom'
```
-This will cause the *custom* GemBox to be read in during the build process,
-adding *mruby-time* and *mrbgems-example* to the build.
+This will cause the `custom` GemBox to be read in during the build process,
+adding `mruby-time` and `mrbgems-example` to the build.
If you want, you can put GemBox outside of mruby directory. In that case you must
specify an absolute path like below.
@@ -103,7 +104,7 @@ conf.gembox "#{ENV["HOME"]}/mygemboxes/custom"
There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox)
and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox
contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox)
-contains every gem found in the *mrbgems* directory.
+contains every gem found in the `mrbgems` directory.
## GEM Structure
@@ -111,27 +112,29 @@ The maximal GEM structure looks like this:
+- GEM_NAME <- Name of GEM
|
+ +- README.md <- Readme for GEM
+ |
+ +- mrbgem.rake <- GEM Specification
+ |
+- include/ <- Header for Ruby extension (will exported)
|
+- mrblib/ <- Source for Ruby extension
|
+- src/ <- Source for C extension
|
- +- test/ <- Test code (Ruby)
- |
- +- mrbgem.rake <- GEM Specification
+ +- tools/ <- Source for Executable (in C)
|
- +- README.md <- Readme for GEM
+ +- test/ <- Test code (Ruby)
-The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src*
-contains C/C++ files to extend mruby. The folder *include* contains C/C++ header
-files. The folder *test* contains C/C++ and pure Ruby files for testing purposes
-which will be used by `mrbtest`. *mrbgem.rake* contains the specification
-to compile C and Ruby files. *README.md* is a short description of your GEM.
+The folder `mrblib` contains pure Ruby files to extend mruby. The folder `src`
+contains C/C++ files to extend mruby. The folder `include` contains C/C++ header
+files. The folder `test` contains C/C++ and pure Ruby files for testing purposes
+which will be used by `mrbtest`. `mrbgem.rake` contains the specification
+to compile C and Ruby files. `README.md` is a short description of your GEM.
## Build process
-mrbgems expects a specification file called *mrbgem.rake* inside of your
+mrbgems expects a specification file called `mrbgem.rake` inside of your
GEM directory. A typical GEM specification could look like this for example:
```ruby
@@ -143,7 +146,7 @@ end
```
The mrbgems build process will use this specification to compile Object and Ruby
-files. The compilation results will be added to *lib/libmruby.a*. This file exposes
+files. The compilation results will be added to `lib/libmruby.a`. This file exposes
the GEM functionality to tools like `mruby` and `mirb`.
The following properties can be set inside of your `MRuby::Gem::Specification` for
@@ -265,7 +268,7 @@ integrate C libraries into mruby.
mrbgems expects that you have implemented a C method called
`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced
-by the name of your GEM. If you call your GEM *c_extension_example*, your
+by the name of your GEM. If you call your GEM `c_extension_example`, your
initialisation method could look like this:
```C
@@ -280,7 +283,7 @@ mrb_c_extension_example_gem_init(mrb_state* mrb) {
mrbgems expects that you have implemented a C method called
`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced
-by the name of your GEM. If you call your GEM *c_extension_example*, your
+by the name of your GEM. If you call your GEM `c_extension_example`, your
finalizer method could look like this:
```C
@@ -294,6 +297,8 @@ mrb_c_extension_example_gem_final(mrb_state* mrb) {
+- c_extension_example/
|
+ +- README.md (Optional)
+ |
+- src/
| |
| +- example.c <- C extension source
@@ -303,13 +308,11 @@ mrb_c_extension_example_gem_final(mrb_state* mrb) {
| +- example.rb <- Test code for C extension
|
+- mrbgem.rake <- GEM specification
- |
- +- README.md
## Ruby Extension
mruby can be extended with pure Ruby. It is possible to override existing
-classes or add new ones in this way. Put all Ruby files into the *mrblib*
+classes or add new ones in this way. Put all Ruby files into the `mrblib`
folder.
### Pre-Conditions
@@ -320,25 +323,25 @@ none
+- ruby_extension_example/
|
+ +- README.md (Optional)
+ |
+- mrblib/
| |
- | +- example.rb <- Ruby extension source
+ | +- example.rb <- Ruby extension source
|
+- test/
| |
- | +- example.rb <- Test code for Ruby extension
+ | +- example.rb <- Test code for Ruby extension
|
- +- mrbgem.rake <- GEM specification
- |
- +- README.md
+ +- mrbgem.rake <- GEM specification
## C and Ruby Extension
mruby can be extended with C and Ruby at the same time. It is possible to
override existing classes or add new ones in this way. Put all Ruby files
-into the *mrblib* folder and all C files into the *src* folder.
+into the `mrblib` folder and all C files into the `src` folder.
-mruby codes under *mrblib* directory would be executed after gem init C
+mruby codes under `mrblib` directory would be executed after gem init C
function is called. Make sure *mruby script* depends on *C code* and
*C code* doesn't depend on *mruby script*.
@@ -350,18 +353,55 @@ See C and Ruby example.
+- c_and_ruby_extension_example/
|
+ +- README.md (Optional)
+ |
+- mrblib/
| |
- | +- example.rb <- Ruby extension source
+ | +- example.rb <- Ruby extension source
|
+- src/
| |
- | +- example.c <- C extension source
+ | +- example.c <- C extension source
|
+- test/
| |
- | +- example.rb <- Test code for C and Ruby extension
+ | +- example.rb <- Test code for C and Ruby extension
|
- +- mrbgem.rake <- GEM specification
+ +- mrbgem.rake <- GEM specification
+
+## Binary gems
+
+Some gems can generate executables under `bin` directory. Those gems are called
+binary gems. Names of binary gems are conventionally prefixed by `mruby-bin`,
+e.g. `mruby-bin-mirb` and `mruby-bin-strip`.
+
+To specify the name of executable, you need to specify `spec.bins` in the
+`mrbgem.rake`. The entry point `main()` should be in the C source file under
+`tools/<bin>/*.c` where `<bin>` is a name of the executable. C files under the
+`<bin>` directory are compiled and linked to the executable, but not included in
+`libmruby.a`, whereas files under `mrblib` and `src` are.
+
+It is strongly recommended not to include `mrblib` and `src` directories in the
+binary gems, to separate normal gems and binary gems.
+
+### Example
+
+ +- mruby-bin-example/
+ |
+ +- README.md (Optional)
+ |
+ +- bintest/
+ | |
+ | +- example.rb <- Test code for binary gem
+ |
+ +- mrbgem.rake <- Gem specification
+ |
+ +- mrblib/ <- Source for Ruby extension (Optional)
+ |
+ +- src/ <- Source for C extension (Optional)
|
- +- README.md
+ +- tools/
+ |
+ +- example/ <- Executable name directory
+ |
+ +- example.c <- Source for Executable (includes main)
diff --git a/doc/mruby3.md b/doc/mruby3.md
index ebd2673d5..b17f3d526 100644
--- a/doc/mruby3.md
+++ b/doc/mruby3.md
@@ -160,4 +160,4 @@ For better and faster random number generation.
Preallocated symbols are interned at compile-time. They can be accessed via symbols macros (e.g. `MRB_SYM()`).
-See [Symbols](https://github.com/mruby/mruby/blob/master/doc/guides/symbol.md).
+See [Symbols](./guides/symbol.md).
diff --git a/include/mruby/array.h b/include/mruby/array.h
index da811606a..16f78f773 100644
--- a/include/mruby/array.h
+++ b/include/mruby/array.h
@@ -21,7 +21,7 @@ typedef struct mrb_shared_array {
mrb_value *ptr;
} mrb_shared_array;
-#if defined(MRB_32BIT) && defined(MRB_NO_BOXING)
+#if defined(MRB_32BIT) && defined(MRB_NO_BOXING) && !defined(MRB_USE_FLOAT32)
# define MRB_ARY_NO_EMBED
# define MRB_ARY_EMBED_LEN_MAX 0
#else
@@ -65,7 +65,7 @@ struct RArray {
#define ARY_EMBED_PTR(a) ((a)->as.ary)
#endif
-#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
+#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(mrb_int)(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
@@ -107,7 +107,7 @@ MRB_API mrb_value mrb_ary_new(mrb_state *mrb);
* Array[value1, value2, ...]
*
* @param mrb The mruby state reference.
- * @param size The numer of values.
+ * @param size The number of values.
* @param vals The actual values.
* @return The initialized array.
*/
diff --git a/include/mruby/dump.h b/include/mruby/dump.h
index ed0c64b1a..3c48866d9 100644
--- a/include/mruby/dump.h
+++ b/include/mruby/dump.h
@@ -16,7 +16,10 @@
*/
MRB_BEGIN_DECL
-#define DUMP_DEBUG_INFO 1
+/* flags for mrb_dump_irep{,_binary,_cfunc,_cstruct} */
+#define MRB_DUMP_DEBUG_INFO 1
+#define MRB_DUMP_STATIC 2
+#define DUMP_DEBUG_INFO MRB_DUMP_DEBUG_INFO /* deprecated */
int mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
#ifndef MRB_NO_STDIO
diff --git a/lib/mruby/build.rb b/lib/mruby/build.rb
index a79732802..b9f26d49f 100644
--- a/lib/mruby/build.rb
+++ b/lib/mruby/build.rb
@@ -248,7 +248,7 @@ module MRuby
end
end
else
- cxx_src = "#{build_dir}/#{src.relative_path})".ext << "-cxx.cxx"
+ cxx_src = "#{build_dir}/#{src.relative_path.to_s.remove_leading_parents}".ext << "-cxx.cxx"
obj = cxx_src.ext(@exts.object)
end
diff --git a/lib/mruby/build/command.rb b/lib/mruby/build/command.rb
index 9d70ac086..dbe3763d9 100644
--- a/lib/mruby/build/command.rb
+++ b/lib/mruby/build/command.rb
@@ -328,13 +328,16 @@ module MRuby
@compile_options = "-B%{funcname} -o-"
end
- def run(out, infiles, funcname, cdump = true)
+ def run(out, infiles, funcname, cdump: true, static: false)
@command ||= @build.mrbcfile
infiles = [infiles].flatten
infiles.each_with_index do |f, i|
_pp i == 0 ? "MRBC" : "", f.relative_path, indent: 2
end
- cmd = %Q["#{filename @command}" #{cdump ? "-S" : ""} #{@compile_options % {:funcname => funcname}} #{filename(infiles).map{|f| %Q["#{f}"]}.join(' ')}]
+ opt = @compile_options % {funcname: funcname}
+ opt << " -S" if cdump
+ opt << " -s" if static
+ cmd = %["#{filename @command}" #{opt} #{filename(infiles).map{|f| %["#{f}"]}.join(' ')}]
puts cmd if Rake.verbose
IO.popen(cmd, 'r+') do |io|
out.puts io.read
diff --git a/lib/mruby/core_ext.rb b/lib/mruby/core_ext.rb
index 33454edad..1ad528c26 100644
--- a/lib/mruby/core_ext.rb
+++ b/lib/mruby/core_ext.rb
@@ -18,6 +18,10 @@ class String
def relative_path
relative_path_from(Dir.pwd)
end
+
+ def remove_leading_parents
+ Pathname.new(".#{Pathname.new("/#{self}").cleanpath}").cleanpath.to_s
+ end
end
def install_D(src, dst)
diff --git a/lib/mruby/gem.rb b/lib/mruby/gem.rb
index 48a14fc54..716f21286 100644
--- a/lib/mruby/gem.rb
+++ b/lib/mruby/gem.rb
@@ -119,6 +119,10 @@ module MRuby
@dir.start_with?("#{MRUBY_ROOT}/mrbgems/")
end
+ def bin?
+ @bins.size > 0
+ end
+
def add_dependency(name, *requirements)
default_gem = requirements.last.kind_of?(Hash) ? requirements.pop : nil
requirements = ['>= 0.0.0'] if requirements.empty?
@@ -194,10 +198,11 @@ module MRuby
open(fname, 'w') do |f|
print_gem_init_header f
unless rbfiles.empty?
+ opts = {cdump: cdump?, static: true}
if cdump?
- build.mrbc.run f, rbfiles, "gem_mrblib_#{funcname}_proc"
+ build.mrbc.run f, rbfiles, "gem_mrblib_#{funcname}_proc", **opts
else
- build.mrbc.run f, rbfiles, "gem_mrblib_irep_#{funcname}", false
+ build.mrbc.run f, rbfiles, "gem_mrblib_irep_#{funcname}", **opts
end
end
f.puts %Q[void mrb_#{funcname}_gem_init(mrb_state *mrb);]
@@ -496,8 +501,10 @@ module MRuby
end
end
- def linker_attrs
- map{|g| g.linker.run_attrs}.transpose
+ def linker_attrs(gem=nil)
+ gems = self.reject{|g| g.bin?} # library gems
+ gems << gem unless gem.nil?
+ gems.map{|g| g.linker.run_attrs}.transpose
end
end # List
end # Gem
diff --git a/mrbgems/mruby-bin-debugger/bintest/print.rb b/mrbgems/mruby-bin-debugger/bintest/print.rb
index 4a4339f5a..63ebded3e 100644
--- a/mrbgems/mruby-bin-debugger/bintest/print.rb
+++ b/mrbgems/mruby-bin-debugger/bintest/print.rb
@@ -264,7 +264,7 @@ SRC
BinTest_MrubyBinDebugger.test(src, tc)
end
-assert('mruby-bin-debugger(print) same name:instance variabe') do
+assert('mruby-bin-debugger(print) same name:instance variable') do
# ruby source (bp is break point)
src = <<"SRC"
@iv = 'top'
@@ -296,7 +296,7 @@ SRC
BinTest_MrubyBinDebugger.test(src, tc)
end
-# Kernel#instance_eval(string) does't work const.
+# Kernel#instance_eval(string) doesn't work const.
=begin
assert('mruby-bin-debugger(print) same name:const') do
# ruby source (bp is break point)
diff --git a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
index 31a4e6fa1..e17f32a2e 100644
--- a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
+++ b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
@@ -14,17 +14,17 @@
#define C_EXT ".c"
struct mrbc_args {
- int argc;
- char **argv;
- int idx;
const char *prog;
const char *outfile;
const char *initname;
+ char **argv;
+ int argc;
+ int idx;
mrb_bool dump_struct : 1;
mrb_bool check_syntax : 1;
mrb_bool verbose : 1;
mrb_bool remove_lv : 1;
- unsigned int flags : 4;
+ uint8_t flags : 4;
};
static void
@@ -38,6 +38,7 @@ usage(const char *name)
"-g produce debugging information",
"-B<symbol> binary <symbol> output in C language format",
"-S dump C struct (requires -B)",
+ "-s define <symbol> as static variable",
"--remove-lv remove local variables",
"--verbose run at verbose mode",
"--version print the version",
@@ -131,7 +132,10 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
args->verbose = TRUE;
break;
case 'g':
- args->flags |= DUMP_DEBUG_INFO;
+ args->flags |= MRB_DUMP_DEBUG_INFO;
+ break;
+ case 's':
+ args->flags |= MRB_DUMP_STATIC;
break;
case 'E':
case 'e':
diff --git a/mrbgems/mruby-catch/mrblib/catch.rb b/mrbgems/mruby-catch/mrblib/catch.rb
index 68b165c8d..9a60a67a3 100644
--- a/mrbgems/mruby-catch/mrblib/catch.rb
+++ b/mrbgems/mruby-catch/mrblib/catch.rb
@@ -1,22 +1,8 @@
-class ThrowCatchJump < Exception
- attr_reader :_tag, :_val
- def initialize(tag, val)
- @_tag = tag
- @_val = val
+class UncaughtThrowError < ArgumentError
+ attr_reader :tag, :value
+ def initialize(tag, value)
+ @tag = tag
+ @value = value
super("uncaught throw #{tag.inspect}")
end
end
-
-module Kernel
- def catch(tag=Object.new, &block)
- block.call(tag)
- rescue ThrowCatchJump => e
- unless e._tag.equal?(tag)
- raise e
- end
- return e._val
- end
- def throw(tag, val=nil)
- raise ThrowCatchJump.new(tag, val)
- end
-end
diff --git a/mrbgems/mruby-catch/src/catch.c b/mrbgems/mruby-catch/src/catch.c
new file mode 100644
index 000000000..d910cac7f
--- /dev/null
+++ b/mrbgems/mruby-catch/src/catch.c
@@ -0,0 +1,128 @@
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/variable.h>
+#include <mruby/error.h>
+#include <mruby/proc.h>
+#include <mruby/opcode.h>
+#include <mruby/presym.h>
+
+
+MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms_3, 1, MRB_SYM(call))
+static const mrb_code catch_iseq_3[18] = {
+ OP_ENTER, 0x00, 0x00, 0x00,
+ OP_GETUPVAR, 0x02, 0x02, 0x01,
+ OP_GETUPVAR, 0x03, 0x01, 0x01,
+ OP_SEND, 0x02, 0x00, 0x01,
+ OP_RETURN, 0x02,};
+static const mrb_irep catch_irep_3 = {
+ 2,5,0,
+ MRB_IREP_STATIC,catch_iseq_3,
+ NULL,catch_syms_3,NULL,
+ NULL,
+ NULL,
+ 18,0,1,0,0
+};
+static const mrb_irep *catch_reps_2[1] = {
+ &catch_irep_3,
+};
+static const mrb_code catch_iseq_2[13] = {
+ OP_ENTER, 0x00, 0x00, 0x00,
+ OP_LAMBDA, 0x02, 0x00,
+ OP_SEND, 0x02, 0x00, 0x00,
+ OP_RETURN, 0x02,};
+static const mrb_irep catch_irep_2 = {
+ 2,4,0,
+ MRB_IREP_STATIC,catch_iseq_2,
+ NULL,catch_syms_3,catch_reps_2,
+ NULL,
+ NULL,
+ 13,0,1,1,0
+};
+static const mrb_irep *catch_reps_1[1] = {
+ &catch_irep_2,
+};
+MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms_1, 3, MRB_SYM(Object), MRB_SYM(new), MRB_SYM(call))
+static const mrb_code catch_iseq_1[29] = {
+ OP_ENTER, 0x00, 0x20, 0x01,
+ OP_JMP, 0x00, 0x03,
+ OP_JMP, 0x00, 0x0a,
+ OP_GETCONST, 0x03, 0x00,
+ OP_SEND, 0x03, 0x01, 0x00,
+ OP_MOVE, 0x01, 0x03,
+ OP_LAMBDA, 0x03, 0x00,
+ OP_SEND, 0x03, 0x02, 0x00,
+ OP_RETURN, 0x03,};
+static const mrb_irep catch_irep = {
+ 3,5,0,
+ MRB_IREP_STATIC,catch_iseq_1,
+ NULL,catch_syms_1,catch_reps_1,
+ NULL,
+ NULL,
+ 29,0,3,1,0
+};
+
+#define ID_PRESERVED_CATCH MRB_SYM(__preserved_catch_proc)
+
+static const mrb_callinfo *
+find_catcher(mrb_state *mrb, mrb_value tag)
+{
+ mrb_value pval = mrb_obj_iv_get(mrb, (struct RObject *)mrb->kernel_module, ID_PRESERVED_CATCH);
+ mrb_assert(mrb_proc_p(pval));
+ const struct RProc *proc = mrb_proc_ptr(pval);
+
+ const mrb_callinfo *ci = mrb->c->ci;
+ size_t n = ci - mrb->c->cibase;
+ ci--;
+ for (; n > 0; n--, ci--) {
+ const mrb_value *arg1 = ci->stack + 1;
+ if (ci->proc == proc && mrb_obj_eq(mrb, *arg1, tag)) {
+ return ci;
+ }
+ }
+
+ return NULL;
+}
+
+static mrb_value
+mrb_f_throw(mrb_state *mrb, mrb_value self)
+{
+ mrb_value tag, obj;
+ if (mrb_get_args(mrb, "o|o", &tag, &obj) == 1) {
+ obj = mrb_nil_value();
+ }
+
+ const mrb_callinfo *ci = find_catcher(mrb, tag);
+ if (ci) {
+ struct RBreak *b = (struct RBreak *)mrb_obj_alloc(mrb, MRB_TT_BREAK, NULL);
+ mrb_break_value_set(b, obj);
+ mrb_break_proc_set(b, ci[2].proc); /* Back to the closure in `catch` method */
+ mrb_exc_raise(mrb, mrb_obj_value(b));
+ }
+ else {
+ mrb_value argv[2] = {tag, obj};
+ mrb_exc_raise(mrb, mrb_obj_new(mrb, mrb_exc_get_id(mrb, MRB_ERROR_SYM(UncaughtThrowError)), 2, argv));
+ }
+ /* not reached */
+ return mrb_nil_value();
+}
+
+void
+mrb_mruby_catch_gem_init(mrb_state *mrb)
+{
+ struct RProc *p;
+ mrb_method_t m;
+
+ MRB_PRESYM_INIT_SYMBOLS(mrb, catch_syms_3);
+ MRB_PRESYM_INIT_SYMBOLS(mrb, catch_syms_1);
+ p = mrb_proc_new(mrb, &catch_irep);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, mrb->kernel_module, MRB_SYM(catch), m);
+ mrb_obj_iv_set(mrb, (struct RObject *)mrb->kernel_module, ID_PRESERVED_CATCH, mrb_obj_value(p));
+
+ mrb_define_method(mrb, mrb->kernel_module, "throw", mrb_f_throw, MRB_ARGS_ARG(1,1));
+}
+
+void
+mrb_mruby_catch_gem_final(mrb_state *mrb)
+{
+}
diff --git a/mrbgems/mruby-catch/test/catch.rb b/mrbgems/mruby-catch/test/catch.rb
index fe5bda096..38a4eb907 100644
--- a/mrbgems/mruby-catch/test/catch.rb
+++ b/mrbgems/mruby-catch/test/catch.rb
@@ -3,10 +3,14 @@ assert "return throw value" do
result = catch :foo do
loop do
loop do
- throw :foo, val
+ begin
+ throw :foo, val
+ rescue Exception
+ flunk("should not reach here 1")
+ end
break
end
- flunk("should not reach here")
+ flunk("should not reach here 2")
end
false
end
@@ -30,13 +34,16 @@ assert "pass the given tag to block" do
catch(tag){|t| assert_same(tag, t)}
end
-assert "tag identity" do
- assert_raise_with_message_pattern(Exception, "uncaught throw *") do
- catch [:tag] do
- throw [:tag]
- end
- flunk("should not reach here")
+assert "tag identity, uncaught throw" do
+ tag, val = [:tag], [:val]
+ catch [:tag] do
+ throw tag, val
end
+ flunk("should not reach here")
+rescue Exception => e
+ assert_match("uncaught throw *", e.message)
+ assert_same(tag, e.tag)
+ assert_same(val, e.value)
end
assert "without catch arguments" do
diff --git a/mrbgems/mruby-cmath/mrbgem.rake b/mrbgems/mruby-cmath/mrbgem.rake
index e00725fef..00ac4b091 100644
--- a/mrbgems/mruby-cmath/mrbgem.rake
+++ b/mrbgems/mruby-cmath/mrbgem.rake
@@ -1,5 +1,5 @@
# This `mruby-cmath` gem uses C99 _Complex features
-# You need C compler that support C99+
+# You need C compiler that support C99+
MRuby::Gem::Specification.new('mruby-cmath') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
diff --git a/mrbgems/mruby-cmath/src/cmath.c b/mrbgems/mruby-cmath/src/cmath.c
index 857b58d26..03b181840 100644
--- a/mrbgems/mruby-cmath/src/cmath.c
+++ b/mrbgems/mruby-cmath/src/cmath.c
@@ -6,7 +6,7 @@
/*
** This `mruby-cmath` gem uses C99 _Complex features
-** You need C compler that support C99+
+** You need C compiler that support C99+
*/
#include <mruby.h>
@@ -47,10 +47,10 @@ cmath_get_complex(mrb_state *mrb, mrb_value c, mrb_float *r, mrb_float *i)
#ifdef MRB_USE_FLOAT32
#define F(x) x##f
#else
-#endif
#define F(x) x
+#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__MINGW32__)
#ifdef MRB_USE_FLOAT32
typedef _Fcomplex mrb_complex;
@@ -91,7 +91,6 @@ CXDIVc(mrb_complex a, mrb_complex b)
return CX(cr, ci);
}
-
#else
#if defined(__cplusplus) && defined(__APPLE__)
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 1a97b3ec6..1a07cc14b 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -1450,7 +1450,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 "numbered paraemeter"
+%token <num> tNUMPARAM "numbered parameter"
%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
%type <nd> literal numeric cpath symbol defn_head defs_head
@@ -4682,6 +4682,7 @@ heredoc_remove_indent(parser_state *p, parser_heredoc_info *hinf)
start = 0;
while (start < len) {
end = escaped ? (size_t)escaped->car : len;
+ if (end > len) end = len;
spaces = (size_t)nspaces->car;
size_t esclen = end - start;
heredoc_count_indent(hinf, str + start, esclen, spaces, &offset);
diff --git a/mrbgems/mruby-compiler/core/y.tab.c b/mrbgems/mruby-compiler/core/y.tab.c
index 6c7940a7b..3e5c6e116 100644
--- a/mrbgems/mruby-compiler/core/y.tab.c
+++ b/mrbgems/mruby-compiler/core/y.tab.c
@@ -16,7 +16,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -2085,7 +2085,7 @@ static const char *const yytname[] =
"\"constant\"", "\"class variable\"", "\"label\"", "\"integer literal\"",
"\"float literal\"", "\"character literal\"", "tXSTRING", "tREGEXP",
"tSTRING", "tSTRING_PART", "tSTRING_MID", "tNTH_REF", "tBACK_REF",
- "tREGEXP_END", "\"numbered paraemeter\"", "\"unary plus\"",
+ "tREGEXP_END", "\"numbered parameter\"", "\"unary plus\"",
"\"unary minus\"", "\"<=>\"", "\"==\"", "\"===\"", "\"!=\"", "\">=\"",
"\"<=\"", "\"&&\"", "\"||\"", "\"=~\"", "\"!~\"", "\"..\"", "\"...\"",
"tBDOT2", "tBDOT3", "tAREF", "tASET", "\"<<\"", "\">>\"", "\"::\"",
@@ -10718,6 +10718,7 @@ heredoc_remove_indent(parser_state *p, parser_heredoc_info *hinf)
start = 0;
while (start < len) {
end = escaped ? (size_t)escaped->car : len;
+ if (end > len) end = len;
spaces = (size_t)nspaces->car;
size_t esclen = end - start;
heredoc_count_indent(hinf, str + start, esclen, spaces, &offset);
diff --git a/mrbgems/mruby-hash-ext/src/hash-ext.c b/mrbgems/mruby-hash-ext/src/hash-ext.c
index 6345420ed..9c85858fe 100644
--- a/mrbgems/mruby-hash-ext/src/hash-ext.c
+++ b/mrbgems/mruby-hash-ext/src/hash-ext.c
@@ -74,7 +74,7 @@ hash_slice(mrb_state *mrb, mrb_value hash)
* hsh.except(*keys) -> a_hash
*
* Returns a hash excluding the given keys and their values.
- *
+ *
* h = { a: 100, b: 200, c: 300 }
* h.except(:a) #=> {:b=>200, :c=>300}
* h.except(:b, :c, :d) #=> {:a=>100}
diff --git a/mrbgems/mruby-math/test/math.rb b/mrbgems/mruby-math/test/math.rb
index 959eef788..6ea06151c 100644
--- a/mrbgems/mruby-math/test/math.rb
+++ b/mrbgems/mruby-math/test/math.rb
@@ -9,27 +9,18 @@ def assert_float_and_int(exp_ary, act_ary)
end
end
-assert('Math.sin 0') do
+assert('Math.sin') do
assert_float(0, Math.sin(0))
-end
-
-assert('Math.sin PI/2') do
assert_float(1, Math.sin(Math::PI / 2))
end
-assert('Math.cos 0') do
+assert('Math.cos') do
assert_float(1, Math.cos(0))
-end
-
-assert('Math.cos PI/2') do
assert_float(0, Math.cos(Math::PI / 2))
end
-assert('Math.tan 0') do
+assert('Math.tan') do
assert_float(0, Math.tan(0))
-end
-
-assert('Math.tan PI/4') do
assert_float(1, Math.tan(Math::PI / 4))
end
@@ -49,52 +40,27 @@ assert('Fundamental trig identities') do
end
end
-assert('Math.erf 0') do
- assert_float(0, Math.erf(0))
-end
-
-assert('Math.exp 0') do
+assert('Math.exp') do
assert_float(1.0, Math.exp(0))
-end
-
-assert('Math.exp 1') do
assert_float(2.718281828459045, Math.exp(1))
-end
-
-assert('Math.exp 1.5') do
assert_float(4.4816890703380645, Math.exp(1.5))
end
-assert('Math.log 1') do
+assert('Math.log') do
assert_float(0, Math.log(1))
-end
-
-assert('Math.log E') do
assert_float(1.0, Math.log(Math::E))
-end
-
-assert('Math.log E**3') do
assert_float(3.0, Math.log(Math::E**3))
end
-assert('Math.log2 1') do
+assert('Math.log2') do
assert_float(0.0, Math.log2(1))
-end
-
-assert('Math.log2 2') do
assert_float(1.0, Math.log2(2))
end
-assert('Math.log10 1') do
+assert('Math.log10') do
assert_float(0.0, Math.log10(1))
-end
-
-assert('Math.log10 10') do
assert_float(1.0, Math.log10(10))
-end
-
-assert('Math.log10 10**100') do
- assert_float(100.0, Math.log10(10**100))
+ assert_float(30.0, Math.log10(10**30))
end
assert('Math.sqrt') do
@@ -117,19 +83,14 @@ assert('Math.hypot') do
assert_float(5.0, Math.hypot(3, 4))
end
-assert('Math.erf 1') do
+assert('Math.erf') do
+ assert_float(0, Math.erf(0))
assert_float(0.842700792949715, Math.erf(1))
-end
-
-assert('Math.erfc 1') do
- assert_float(0.157299207050285, Math.erfc(1))
-end
-
-assert('Math.erf -1') do
assert_float(-0.8427007929497148, Math.erf(-1))
end
-assert('Math.erfc -1') do
+assert('Math.erfc') do
+ assert_float(0.157299207050285, Math.erfc(1))
assert_float(1.8427007929497148, Math.erfc(-1))
end
diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c
index 9081c2eec..618ffa805 100644
--- a/mrbgems/mruby-rational/src/rational.c
+++ b/mrbgems/mruby-rational/src/rational.c
@@ -156,10 +156,10 @@ rational_new_i(mrb_state *mrb, mrb_int n, mrb_int d)
if (d == 0) {
rat_zerodiv(mrb);
}
- a = i_gcd(n, d);
- if ((n == MRB_INT_MIN || d == MRB_INT_MIN) && a == -1) {
+ if (n == MRB_INT_MIN || d == MRB_INT_MIN) {
rat_overflow(mrb);
}
+ a = i_gcd(n, d);
return rational_new(mrb, n/a, d/a);
}
diff --git a/mrbgems/mruby-sleep/src/mrb_sleep.c b/mrbgems/mruby-sleep/src/sleep.c
index 79a5af650..79a5af650 100644
--- a/mrbgems/mruby-sleep/src/mrb_sleep.c
+++ b/mrbgems/mruby-sleep/src/sleep.c
diff --git a/mrbgems/mruby-sprintf/test/sprintf.rb b/mrbgems/mruby-sprintf/test/sprintf.rb
index 8f99f9cd0..0a8166bae 100644
--- a/mrbgems/mruby-sprintf/test/sprintf.rb
+++ b/mrbgems/mruby-sprintf/test/sprintf.rb
@@ -10,11 +10,11 @@ assert('String#%') do
assert_equal 15, ("%b" % (1<<14)).size
skip unless Object.const_defined?(:Float)
assert_equal "1.0", "%3.1f" % 1.01
- assert_equal " 123456789.12", "% 4.2f" % 123456789.123456789
- assert_equal "123456789.12", "%-4.2f" % 123456789.123456789
- assert_equal "+123456789.12", "%+4.2f" % 123456789.123456789
- assert_equal "123456789.12", "%04.2f" % 123456789.123456789
- assert_equal "00000000123456789.12", "%020.2f" % 123456789.123456789
+ assert_equal " 1234567.12", "% 4.2f" % 1234567.123456789
+ assert_equal "1234567.12", "%-4.2f" % 1234567.123456789
+ assert_equal "+1234567.12", "%+4.2f" % 1234567.123456789
+ assert_equal "1234567.12", "%04.2f" % 1234567.123456789
+ assert_equal "00000000001234567.12", "%020.2f" % 1234567.123456789
end
assert('String#% with inf') do
diff --git a/mrbgems/mruby-struct/mrblib/struct.rb b/mrbgems/mruby-struct/mrblib/struct.rb
index b398409c3..2439e2a37 100644
--- a/mrbgems/mruby-struct/mrblib/struct.rb
+++ b/mrbgems/mruby-struct/mrblib/struct.rb
@@ -2,99 +2,96 @@
# Struct
#
# ISO 15.2.18
+class Struct
-if Object.const_defined?(:Struct)
- class Struct
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element.
+ #
+ # ISO 15.2.18.4.4
+ def each(&block)
+ self.class.members.each{|field|
+ block.call(self[field])
+ }
+ self
+ end
- ##
- # Calls the given block for each element of +self+
- # and pass the respective element.
- #
- # ISO 15.2.18.4.4
- def each(&block)
- self.class.members.each{|field|
- block.call(self[field])
- }
- self
- end
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the name and value of the respective
+ # element.
+ #
+ # ISO 15.2.18.4.5
+ def each_pair(&block)
+ self.class.members.each{|field|
+ block.call(field.to_sym, self[field])
+ }
+ self
+ end
- ##
- # Calls the given block for each element of +self+
- # and pass the name and value of the respective
- # element.
- #
- # ISO 15.2.18.4.5
- def each_pair(&block)
- self.class.members.each{|field|
- block.call(field.to_sym, self[field])
- }
- self
- end
+ ##
+ # Calls the given block for each element of +self+
+ # and returns an array with all elements of which
+ # block is not false.
+ #
+ # ISO 15.2.18.4.7
+ def select(&block)
+ ary = []
+ self.class.members.each{|field|
+ val = self[field]
+ ary.push(val) if block.call(val)
+ }
+ ary
+ end
- ##
- # Calls the given block for each element of +self+
- # and returns an array with all elements of which
- # block is not false.
- #
- # ISO 15.2.18.4.7
- def select(&block)
- ary = []
- self.class.members.each{|field|
- val = self[field]
- ary.push(val) if block.call(val)
- }
- ary
+ def _inspect(recur_list)
+ return "#<struct #{self.class}:...>" if recur_list[self.object_id]
+ recur_list[self.object_id] = true
+ name = self.class.to_s
+ if name[0] == "#"
+ str = "#<struct "
+ else
+ str = "#<struct #{name} "
end
-
- def _inspect(recur_list)
- return "#<struct #{self.class}:...>" if recur_list[self.object_id]
- recur_list[self.object_id] = true
- name = self.class.to_s
- if name[0] == "#"
- str = "#<struct "
- else
- str = "#<struct #{name} "
- end
- buf = []
- self.each_pair do |k,v|
- buf.push k.to_s + "=" + v._inspect(recur_list)
- end
- str + buf.join(", ") + ">"
+ buf = []
+ self.each_pair do |k,v|
+ buf.push k.to_s + "=" + v._inspect(recur_list)
end
+ str + buf.join(", ") + ">"
+ end
- ##
- # call-seq:
- # struct.to_s -> string
- # struct.inspect -> string
- #
- # Describe the contents of this struct in a string.
- #
- # 15.2.18.4.10(x)
- #
- def inspect
- self._inspect({})
- end
+ ##
+ # call-seq:
+ # struct.to_s -> string
+ # struct.inspect -> string
+ #
+ # Describe the contents of this struct in a string.
+ #
+ # 15.2.18.4.10(x)
+ #
+ def inspect
+ self._inspect({})
+ end
- ##
- # 15.2.18.4.11(x)
- #
- alias to_s inspect
+ ##
+ # 15.2.18.4.11(x)
+ #
+ alias to_s inspect
- ##
- # call-seq:
- # hsh.dig(key,...) -> object
- #
- # Extracts the nested value specified by the sequence of <i>key</i>
- # objects by calling +dig+ at each step, returning +nil+ if any
- # intermediate step is +nil+.
- #
- def dig(idx,*args)
- n = self[idx]
- if args.size > 0
- n&.dig(*args)
- else
- n
- end
+ ##
+ # call-seq:
+ # hsh.dig(key,...) -> object
+ #
+ # Extracts the nested value specified by the sequence of <i>key</i>
+ # objects by calling +dig+ at each step, returning +nil+ if any
+ # intermediate step is +nil+.
+ #
+ def dig(idx,*args)
+ n = self[idx]
+ if args.size > 0
+ n&.dig(*args)
+ else
+ n
end
end
end
diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c
index d26233683..958e87dd1 100644
--- a/mrbgems/mruby-test/driver.c
+++ b/mrbgems/mruby-test/driver.c
@@ -226,9 +226,9 @@ mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose)
#ifndef MRB_NO_FLOAT
#ifdef MRB_USE_FLOAT32
- mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-6));
+ mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-5));
#else
- mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-12));
+ mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-10));
#endif
#endif
diff --git a/mrbgems/mruby-test/mrbgem.rake b/mrbgems/mruby-test/mrbgem.rake
index 421108e0b..927447b4f 100644
--- a/mrbgems/mruby-test/mrbgem.rake
+++ b/mrbgems/mruby-test/mrbgem.rake
@@ -20,7 +20,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
_pp "GEN", t.name.relative_path
mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
- mrbc.run f, assert_rb, 'mrbtest_assert_irep', false
+ mrbc.run f, assert_rb, 'mrbtest_assert_irep', cdump: false
end
end
@@ -52,10 +52,10 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
if test_preload.nil?
f.puts %Q[extern const uint8_t mrbtest_assert_irep[];]
else
- g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload", false
+ g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload", cdump: false
end
g.test_rbfiles.flatten.each_with_index do |rbfile, i|
- g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}", false
+ g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}", cdump: false, static: true
end
f.puts %Q[void mrb_#{g.funcname}_gem_test(mrb_state *mrb);] if g.custom_test_init?
dep_list.each do |d|
diff --git a/src/array.c b/src/array.c
index a66ff8183..8ab30bd8e 100644
--- a/src/array.c
+++ b/src/array.c
@@ -56,18 +56,17 @@ mrb_ary_new(mrb_state *mrb)
}
/*
- * to copy array, use this instead of memcpy because of portability
+ * To copy array, use this instead of memcpy because of portability
* * gcc on ARM may fail optimization of memcpy
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3934.html
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56620
* * gcc on MIPS also fail
- * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39755
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39755
* * memcpy doesn't exist on freestanding environment
*
* If you optimize for binary size, use memcpy instead of this at your own risk
* of above portability issue.
*
- * see also http://togetter.com/li/462898
- *
+ * See also https://togetter.com/li/462898 (Japanese)
*/
static inline void
array_copy(mrb_value *dst, const mrb_value *src, mrb_int size)
diff --git a/src/dump.c b/src/dump.c
index 5173b88e5..e3f3320ea 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -806,7 +806,7 @@ dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, si
section_irep_size += get_irep_record_size(mrb, irep);
/* DEBUG section size */
- if (flags & DUMP_DEBUG_INFO) {
+ if (flags & MRB_DUMP_DEBUG_INFO) {
if (debug_info_defined) {
section_lineno_size += sizeof(struct rite_section_debug_header);
/* filename table */
@@ -842,7 +842,7 @@ dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, si
sizeof(struct rite_binary_footer);
/* write DEBUG section */
- if (flags & DUMP_DEBUG_INFO) {
+ if (flags & MRB_DUMP_DEBUG_INFO) {
if (debug_info_defined) {
result = write_section_debug(mrb, irep, cur, filenames, filenames_len);
if (result != MRB_DUMP_OK) {
@@ -920,11 +920,13 @@ mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *f
return MRB_DUMP_WRITE_FAULT;
}
if (fprintf(fp,
- "#ifdef __cplusplus\n"
- "extern const uint8_t %s[];\n"
- "#endif\n"
+ "%s\n"
"const uint8_t %s[] = {",
- initname, initname) < 0) {
+ (flags & MRB_DUMP_STATIC) ? "static"
+ : "#ifdef __cplusplus\n"
+ "extern\n"
+ "#endif",
+ initname) < 0) {
mrb_free(mrb, bin);
return MRB_DUMP_WRITE_FAULT;
}
@@ -1232,8 +1234,14 @@ mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE
int max = 1;
int n = dump_irep_struct(mrb, irep, flags, fp, initname, 0, init_syms_code, &max);
if (n != MRB_DUMP_OK) return n;
- fprintf(fp, "#ifdef __cplusplus\nextern const struct RProc %s[];\n#endif\n", initname);
- fprintf(fp, "const struct RProc %s[] = {{\n", initname);
+ fprintf(fp,
+ "%s\n"
+ "const struct RProc %s[] = {{\n",
+ (flags & MRB_DUMP_STATIC) ? "static"
+ : "#ifdef __cplusplus\n"
+ "extern\n"
+ "#endif",
+ initname);
fprintf(fp, "NULL,NULL,MRB_TT_PROC,7,0,{&%s_irep_0},NULL,{NULL},\n}};\n", initname);
fputs("static void\n", fp);
fprintf(fp, "%s_init_syms(mrb_state *mrb)\n", initname);
diff --git a/src/hash.c b/src/hash.c
index 289f02a91..c5b4c5cbe 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -215,40 +215,70 @@ DEFINE_SWITCHER(ht, HT)
} while (0)
/*
- * `h_check_modified` raises an exception when a dangerous modification is
- * made to `h` by executing `code`.
- *
- * This macro is not called if `h->ht` (`h->ea`) is `NULL` (`Hash` size is
- * zero). And because the `hash_entry` is rather large, `h->ht->ea` and
- * `h->ht->ea_capa` are able to be safely accessed even in AR. This nature
- * is used to eliminate branch of AR or HT.
- *
- * `HT_ASSERT_SAFE_READ` checks if members can be accessed according to its
- * assumptions.
+ * In `h_check_modified()`, in the case of `MRB_NO_BOXING`, `ht_ea()` or
+ * `ht_ea_capa()` for AR may read uninitialized area (#5332). Therefore, do
+ * not use those macros for AR in `MRB_NO_BOXING` (but in the case of
+ * `MRB_64BIT`, `ht_ea_capa()` is the same as `ar_ea_capa()`, so use it).
*/
-#define HT_ASSERT_SAFE_READ(attr_name) \
+#ifdef MRB_NO_BOXING
+# define H_CHECK_MODIFIED_USE_HT_EA_FOR_AR FALSE
+# ifdef MRB_64BIT
+# define H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR TRUE
+# else
+# define H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR FALSE
+# endif /* MRB_64BIT */
+#else
+# define H_CHECK_MODIFIED_USE_HT_EA_FOR_AR TRUE
+# define H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR TRUE
+ /*
+ * `h_check_modified` raises an exception when a dangerous modification is
+ * made to `h` by executing `code`.
+ *
+ * `h_check_modified` macro is not called if `h->ht` (`h->ea`) is `NULL`
+ * (`Hash` size is zero). And because the `hash_entry` is rather large,
+ * `h->ht->ea` and `h->ht->ea_capa` are able to be safely accessed even for
+ * AR. This nature is used to eliminate branch of AR or HT.
+ *
+ * `HT_ASSERT_SAFE_READ` checks if members can be accessed according to its
+ * assumptions.
+ */
+# define HT_ASSERT_SAFE_READ(attr_name) \
mrb_static_assert1( \
offsetof(hash_table, attr_name) + sizeof(((hash_table*)0)->attr_name) <= \
sizeof(hash_entry))
HT_ASSERT_SAFE_READ(ea);
-#ifdef MRB_32BIT
+# ifdef MRB_32BIT
HT_ASSERT_SAFE_READ(ea_capa);
-#endif
-#undef HT_ASSERT_SAFE_READ
-#define h_check_modified(mrb, h, code) do { \
- struct RHash *h__ = h; \
- uint32_t mask = MRB_HASH_HT|MRB_HASH_IB_BIT_MASK|MRB_HASH_AR_EA_CAPA_MASK; \
- uint32_t flags = h__->flags & mask; \
- void* tbl__ = (mrb_assert(h__->ht), h__->ht); \
- uint32_t ht_ea_capa__ = ht_ea_capa(h__); \
- hash_entry *ht_ea__ = ht_ea(h__); \
- code; \
- if (flags != (h__->flags & mask) || \
- tbl__ != h__->ht || \
- ht_ea_capa__ != ht_ea_capa(h__) || \
- ht_ea__ != ht_ea(h__)) { \
- mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified"); \
- } \
+# endif
+# undef HT_ASSERT_SAFE_READ
+#endif /* MRB_NO_BOXING */
+
+/*
+ * `h_check_modified` raises an exception when a dangerous modification is
+ * made to `h` by executing `code`.
+ */
+#define h_check_modified(mrb, h, code) do { \
+ struct RHash *h__ = h; \
+ uint32_t mask__ = MRB_HASH_HT|MRB_HASH_IB_BIT_MASK|MRB_HASH_AR_EA_CAPA_MASK; \
+ uint32_t flags__ = h__->flags & mask__; \
+ void* tbl__ = (mrb_assert(h__->ht), h__->ht); \
+ uint32_t ht_ea_capa__ = 0; \
+ hash_entry *ht_ea__ = NULL; \
+ if (H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR || h_ht_p(h__)) { \
+ ht_ea_capa__ = ht_ea_capa(h__); \
+ } \
+ if (H_CHECK_MODIFIED_USE_HT_EA_FOR_AR || h_ht_p(h__)) { \
+ ht_ea__ = ht_ea(h__); \
+ } \
+ code; \
+ if (flags__ != (h__->flags & mask__) || \
+ tbl__ != h__->ht || \
+ ((H_CHECK_MODIFIED_USE_HT_EA_CAPA_FOR_AR || h_ht_p(h__)) && \
+ ht_ea_capa__ != ht_ea_capa(h__)) || \
+ ((H_CHECK_MODIFIED_USE_HT_EA_FOR_AR || h_ht_p(h__)) && \
+ ht_ea__ != ht_ea(h__))) { \
+ mrb_raise(mrb, E_RUNTIME_ERROR, "hash modified"); \
+ } \
} while (0)
#define U32(v) ((uint32_t)(v))
@@ -718,6 +748,7 @@ ib_bit_for(uint32_t size)
static uint32_t
ib_byte_size_for(uint32_t ib_bit)
{
+ mrb_assert(IB_INIT_BIT <= ib_bit);
uint32_t ary_size = IB_INIT_BIT == 4 ?
ib_bit_to_capa(ib_bit) * 2 / IB_TYPE_BIT * ib_bit / 2 :
ib_bit_to_capa(ib_bit) / IB_TYPE_BIT * ib_bit;
@@ -892,7 +923,13 @@ static void
ht_rehash(mrb_state *mrb, struct RHash *h)
{
/* see comments in `h_rehash` */
- uint32_t size = ht_size(h), w_size = 0, ea_capa = ht_ea_capa(h);
+ uint32_t size = ht_size(h);
+ if (size <= AR_MAX_SIZE) {
+ ht_to_ar(mrb, h);
+ ar_rehash(mrb, h);
+ return;
+ }
+ uint32_t w_size = 0, ea_capa = ht_ea_capa(h);
hash_entry *ea = ht_ea(h);
ht_init(mrb, h, 0, ea, ea_capa, h_ht(h), ib_bit_for(size));
ht_set_size(h, size);
diff --git a/src/print.c b/src/print.c
index 607eb9d1f..c96189fe9 100644
--- a/src/print.c
+++ b/src/print.c
@@ -28,10 +28,6 @@ printstr(mrb_value obj, FILE *stream)
printcstr(RSTRING_PTR(obj), RSTRING_LEN(obj), stream);
}
}
-#else
-# define printcstr(str, len, stream) (void)0
-# define printstr(obj, stream) (void)0
-#endif
void
mrb_core_init_printabort(void)
@@ -51,6 +47,17 @@ mrb_p(mrb_state *mrb, mrb_value obj)
printstr(mrb_inspect(mrb, obj), stdout);
}
}
+#else
+void
+mrb_core_init_printabort(void)
+{
+}
+
+MRB_API void
+mrb_p(mrb_state *mrb, mrb_value obj)
+{
+}
+#endif
MRB_API void
mrb_print_error(mrb_state *mrb)
diff --git a/src/vm.c b/src/vm.c
index 390ce8aaa..0e7eb65e5 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1022,7 +1022,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
const struct mrb_irep_catch_handler *ch;
#ifdef DIRECT_THREADED
- static void *optable[] = {
+ static const void * const optable[] = {
#define OPCODE(x,_) &&L_OP_ ## x,
#include "mruby/ops.h"
#undef OPCODE
diff --git a/tasks/bin.rake b/tasks/bin.rake
index bc8820b66..5c764458d 100644
--- a/tasks/bin.rake
+++ b/tasks/bin.rake
@@ -6,8 +6,8 @@ MRuby.each_target do |build|
build.bins.each{|bin| build.products << define_installer_if_needed(bin)}
- linker_attrs = build.gems.linker_attrs
build.gems.each do |gem|
+ linker_attrs = build.gems.linker_attrs(gem)
gem.bins.each do |bin|
exe = build.exefile("#{build.build_dir}/bin/#{bin}")
objs = Dir["#{gem.dir}/tools/#{bin}/*.{c,cpp,cxx,cc}"].map do |f|
diff --git a/tasks/libmruby.rake b/tasks/libmruby.rake
index 23cd992ff..8cdb4ca2e 100644
--- a/tasks/libmruby.rake
+++ b/tasks/libmruby.rake
@@ -16,14 +16,15 @@ MRuby.each_target do
open(t.name, 'w') do |f|
f.puts "MRUBY_CFLAGS = #{cc.all_flags}"
- gem_flags = gems.map { |g| g.linker.flags }
- gem_library_paths = gems.map { |g| g.linker.library_paths }
+ libgems = gems.reject{|g| g.bin?}
+ gem_flags = libgems.map {|g| g.linker.flags }
+ gem_library_paths = libgems.map {|g| g.linker.library_paths }
f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % "#{build_dir}/lib"}"
- gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
+ gem_flags_before_libraries = libgems.map {|g| g.linker.flags_before_libraries }
f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ')}"
- gem_libraries = gems.map { |g| g.linker.libraries }
+ gem_libraries = libgems.map {|g| g.linker.libraries }
f.puts "MRUBY_LIBS = #{linker.option_library % 'mruby'} #{linker.library_flags(gem_libraries)}"
f.puts "MRUBY_LIBMRUBY_PATH = #{libmruby_static}"
diff --git a/tasks/mrblib.rake b/tasks/mrblib.rake
index 5567515d6..485375e55 100644
--- a/tasks/mrblib.rake
+++ b/tasks/mrblib.rake
@@ -28,7 +28,7 @@ MRuby.each_target do
f.puts %Q[#include <mruby.h>]
f.puts %Q[#include <mruby/irep.h>]
end
- mrbc.run f, rbfiles, "mrblib_#{suffix}", cdump
+ mrbc.run f, rbfiles, "mrblib_#{suffix}", cdump: cdump, static: true
f.puts %Q[void]
f.puts %Q[mrb_init_mrblib(mrb_state *mrb)]
f.puts %Q[{]
diff --git a/tasks/test.rake b/tasks/test.rake
index a18635cc6..32a03fce6 100644
--- a/tasks/test.rake
+++ b/tasks/test.rake
@@ -10,7 +10,7 @@ namespace :test do |test_ns|
end
desc "build and run command binaries tests"
- task :bin => :all do
+ task :bin => "rake:all" do
test_ns["run:bin"].invoke
end
@@ -19,9 +19,10 @@ namespace :test do |test_ns|
namespace :build do |test_build_ns|
desc "build library tests"
- task :lib => :all do
+ task :lib => "rake:all" do
MRuby.each_target{|build| build.gem(core: 'mruby-test')}
- test_build_ns["lib_without_loading_gem"].invoke
+ test = test_build_ns["lib_without_loading_gem"]
+ test.invoke if test
end
end
diff --git a/test/t/hash.rb b/test/t/hash.rb
index c51af03aa..a5e51d83b 100644
--- a/test/t/hash.rb
+++ b/test/t/hash.rb
@@ -944,6 +944,14 @@ assert('Hash#rehash') do
h = {}
assert_same(h, h.rehash)
assert_predicate(h, :empty?)
+
+ h = {}
+ (1..17).each{h[_1] = _1 * 2}
+ (2..16).each{h.delete(_1)}
+ assert_same(h, h.rehash)
+ assert_equal([[1, 2], [17, 34]], h.to_a)
+ assert_equal(2, h.size)
+ [1, 17].each{assert_equal(_1 * 2, h[_1])}
end
assert('#eql? receiver should be specified key') do